SlideShare a Scribd company logo
はてな id:skozawa
Elasticsearch勉強会 in 大阪/京都
Elasticsearchを用いた
はてなブックマークのトピック生成
自己紹介
id:skozawa / @5kozawa
2007-2012
大学院で自然言語処理の研究に従事
2012
株式会社はてな入社
アプリケーションエンジニア
・ブックマークチーム
・アドテクチーム
2
  はてなブックマーク
3
トピックページ (http://b.hatena.ne.jp/topiclist)
関連性の高い話題の記事をまとめたページ
4
トピックページ
5
トピックページ
6
トピックタイトル
トピックに
関連する記事
トピックページの自動生成
● トピック生成
○ トピックに関連する記事を収集
● トピックタイトル生成
○ トピックを表すタイトルを生成
7
トピックページの自動生成
● トピック生成
○ トピックに関連する記事を収集
● トピックタイトル生成
○ トピックを表すタイトルを生成
8
Elasticsearchを活用
トピックとは?
トピック
キーワードの集合から表現
トピックモデル
PLSI (Probabilistic Latent Semantic Indexing)
LDA (Latent Dirichlet Allocation)
*今回は使ってない
官邸、首相、ドローン、落下、カメラ
阿久津、AWAKE、将棋、棋士、投了
9
北陸、新幹線、金沢、開業、長野
トピック生成の流れ
1. トピックキーワードを生成
Significant Terms Aggregation
2. トピックキーワードに関連する記事の収集
Function Score Query
3. トピックのマージ
10
官邸、首相、ドローン、落下、カメラ
● 首相官邸にドローン落下 けが人はなし :日本経済新聞
● 首相官邸の屋上にドローン落下、微量の放射線を検出| Reuters
はてなブックマークのインデックス構造(一部)
11
“mapping”: {
“entry”: {
“_id” : { “path”: “id” },
“properties”: {
“id”: { “type”: “integer” },
“url”: { “type”: “string” },
“title”: { “type”: “string” },
“content”: { “type”: “string” },
“created”: { “type”: “date”, “format”: “date_time_no_mills” }
}
}
}
Significant Terms Aggregation
重要語を取得できる機能
トピックキーワードの生成に利用
期間を区切って記事のタイトルや本文を対象に実行
話題のキーワードが取得できる
12
https://www.elastic.co/guide/en/elasticsearch/reference/1.6/search-aggregations-bucket-
significantterms-aggregation.html
An aggregation that returns interesting or unusual
occurrences of terms in a set.
Significant Terms Aggregation
"aggregations": {
"sample": {
"buckets": [
{ "key": "シャリル", "doc_count": 55,
"score": 2.502, "bg_count": 400 },
{ "key": "エブド", "doc_count": 39,
"score": 2.278, "bg_count": 221 },
{ "key": "スイスフラン", "doc_count": 57,
"score": 1.802, "bg_count": 596 },
{ "key": "ニュース", "doc_count": 1966,
"score": 1.606, "bg_count": 732518 },
{ "key": "ようじ", "doc_count": 48,
"score": 1.511, "bg_count": 504 },
]
} }
{
“aggs”: {
“sample”: {
“significant_terms” : {
“field”: “title”,
“size”: 5
}
}
}
}
Request Response
2015年1月13日 ~
2015年1月20日 13
Significant Terms Aggregation
"aggregations": {
"sample": {
"buckets": [
{ "key": "シャリル", "doc_count": 55,
"score": 2.502, "bg_count": 400 },
{ "key": "エブド", "doc_count": 39,
"score": 2.278, "bg_count": 221 },
{ "key": "スイスフラン", "doc_count": 57,
"score": 1.802, "bg_count": 596 },
{ "key": "ニュース", "doc_count": 1966,
"score": 1.606, "bg_count": 732518 },
{ "key": "ようじ", "doc_count": 48,
"score": 1.511, "bg_count": 504 },
]
} }
{
“aggs”: {
“sample”: {
“significant_terms” : {
“field”: “title”,
“size”: 5
}
}
}
}
Request Response
2015年1月13日 ~
2015年1月20日
key: キーワード
doc_count: 指定範囲でのキーワードの頻度
score: キーワードのスコア
bg_count: 文書全体でのキーワードの頻度
14
Elasticsearchは何を計算してる?
● スコア計算方法は現在5種類 (version 1.6)
○ JLH score
○ mutual information
○ Chi square
○ google normalized distance
○ Percentage
15
JLH
全体と指定範囲の出現割合を利用
JLH = 絶対割合変化 × 相対割合変化
絶対割合変化 = 指定範囲での出現割合 - 全体での出現割合
相対割合変化 = 指定範囲での出現割合 / 全体での出現割合
例:1年(全体)で30,000文書、直近1日(指定範囲)で100文書の文書集合利用
  「スイスフラン」という単語が全体で100、指定範囲で10回出現した場合
絶対割合変化 = 10/100 - 100/30000 = 29/300
相対割合変化 = 10/100 / 100/30000 = 30
JLH = 29/300 * 30 = 2.9
16
JLH
全体と指定範囲の出現割合を利用
JLH = 絶対割合変化 × 相対割合変化
絶対割合変化 = 指定範囲での出現割合 - 全体での出現割合
相対割合変化 = 指定範囲での出現割合 / 全体での出現割合
17
指定範囲で頻出する単語のスコアが高くなる
Significant Terms Aggregation
"aggregations": {
"sample": {
"buckets": [
{ "key": "シャリル", "doc_count": 55,
"score": 2.502, "bg_count": 400 },
{ "key": "エブド", "doc_count": 39,
"score": 2.278, "bg_count": 221 },
{ "key": "スイスフラン", "doc_count": 57,
"score": 1.802, "bg_count": 596 },
{ "key": "ニュース", "doc_count": 1966,
"score": 1.606, "bg_count": 732518 },
{ "key": "ようじ", "doc_count": 48,
"score": 1.511, "bg_count": 504 },
]
} }
{
“aggs”: {
“sample”: {
“significant_terms” : {
“field”: “title”,
“size”: 5
}
}
}
}
Request Response
2015年1月13日 ~
2015年1月20日 18
{
“query”: {
“filtered”: { “filter”: { “bool”: { “must”: [
{ “range”: { “created”: {
“from”: “2015-01-13T00:00:00+09:00”,
“to”: “2015-01-20T00:00:00+09:00”
} } }
] } } }
},
“aggs”: { “sample”: {
“significant_terms” : { “field”: “title”, “size”: 5, “jlh”: {} },
“aggs”: { “sample2”: {
“significant_terms”: { “field”: “title”, “size”: 5, “jlh”: {} }
} }
} }
}
Request
2015年1月13日 ~ 2015年1月20日
significant_termsを2層で利用
19
"aggregations": { "sample": { "buckets": [
{
"key": "シャルリ", "score": 2.502,
"sample2": { "buckets": [ { "key": "シャルリ", "score": 129926.04 },
{ "key": "エブド", "score": 99737.62 }, { "key": "赦す", "score": 5522.22 },
{ "key": "ムハンマド", "score": 4729.32 }, { "key": "風刺", "score": 4172.57 }
] }
}, …, {
"key": "スイスフラン", "score": 1.802,
"sample2": { "buckets": [ { "key": "スイスフラン", "score": 89385.22 },
{ "key": "急騰", "score": 1992.90 }, { "key": "上限", "score": 1391.56 },
{ "key": "損失", "score": 1118.69 }, { "key": "暴騰", "score": 766.13 }
] }
}, …, {
"key": "ようじ", "score": 1.511,
"sample2": { "buckets": [ { "key": "ようじ", "score": 80424.75 },
{ "key": "つま", "score": 26207.62 }, { "key": "混入", "score": 4192.10 },
{ "key": "スナック菓子", "score": 2759.62 }, { "key": "手配", "score": 2128.30 }
] }
}
] } }
Response
20
"aggregations": { "sample": { "buckets": [
{
"key": "シャルリ", "score": 2.502,
"sample2": { "buckets": [ { "key": "シャルリ", "score": 129926.04 },
{ "key": "エブド", "score": 99737.62 }, { "key": "赦す", "score": 5522.22 },
{ "key": "ムハンマド", "score": 4729.32 }, { "key": "風刺", "score": 4172.57 }
] }
}, …, {
"key": "スイスフラン", "score": 1.802,
"sample2": { "buckets": [ { "key": "スイスフラン", "score": 89385.22 },
{ "key": "急騰", "score": 1992.90 }, { "key": "上限", "score": 1391.56 },
{ "key": "損失", "score": 1118.69 }, { "key": "暴騰", "score": 766.13 }
] }
}, …, {
"key": "ようじ", "score": 1.511,
"sample2": { "buckets": [ { "key": "ようじ", "score": 80424.75 },
{ "key": "つま", "score": 26207.62 }, { "key": "混入", "score": 4192.10 },
{ "key": "スナック菓子", "score": 2759.62 }, { "key": "手配", "score": 2128.30 }
] }
}
] } }
Response
トピックキーワード
21
トピックキーワードの生成例
22
シャルリ、エブド、赦す、ムハンマド、風刺
エブド、シャルリ、赦す、ムハンマド、風刺
スイスフラン、急騰、上限、損失、暴騰
ニュース、yahoo、風刺、ようじ、nhk
ようじ、つま、混入、スナック菓子、手配
トピックキーワードの生成例
23
シャルリ、エブド、赦す、ムハンマド、風刺
エブド、シャルリ、赦す、ムハンマド、風刺
スイスフラン、急騰、上限、損失、暴騰
ニュース、yahoo、風刺、ようじ、nhk
ようじ、つま、混入、スナック菓子、手配
同じ内容のトピックキーワード
トピック??
トピックキーワードの誤生成の原因
● 誤生成の要因
○ 記事タイトルにサイト名が含まれている
24
ニュース、yahoo、風刺、ようじ、nhk
● 「ピタゴラスイッチ」の“ゴール”発売 旗が立ってあの音が流れる! - はてなニュース
● “商品につまようじ”動画投稿 少年逮捕 NHKニュース
● 事件模倣か、17歳逮捕=菓子につまようじ―長崎県警 (時事通信) - Yahoo!ニュー
ス
● Yahoo!ニュース - 銃撃された仏紙、最新号表紙にムハンマド風刺画 (AFP=時事)
● 仏新聞社 預言者の風刺画を掲載へ NHKニュース
● 芥川賞に小野正嗣さん 直木賞に西加奈子さん NHKニュース
● Microsoft、月例パッチの事前通知を“ほぼ”打ち切り - ITmedia ニュース
トピックキーワード誤生成への対策
● 記事タイトルによくでてくるキーワードは除く
● 範囲を指定せずにSignificant Terms Aggragation
25
"aggregations": { "stop_words": {
"buckets": [
{ "key": "2", "score": 0.388, ... },
{ "key": "ニュース", "score": 0.326, … },
{ "key": "1", "score": 0.323, … },
{ "key": "3", "score": 0.240, ... },
{ "key": "com", "score": 0.234, … },
{ "key": "アンテナ", "score": 0.222, … },
{ "key": "twitter", "score": 0.219, ... },
{ "key": "動画", "score": 0.218, … },
{ "key": "まとめ", "score": 0.202, … },
{ "key": "online", "score": 0.190, ... }
]
} }
“aggs”: {
“stop_words”: {
“significant_terms” : {
“field”: “title”,
“size”: 10
}
}
}
Request Response
期間指定なし
トピックキーワードの生成例
26
シャルリ、エブド、赦す、ムハンマド、風刺
エブド、シャルリ、赦す、ムハンマド、風刺
スイスフラン、急騰、上限、損失、暴騰
ようじ、つま、混入、スナック菓子、手配
ニュース、yahoo、風刺、ようじ、nhk
トピックキーワードに関する記事の取得
生成されたトピックの単語が含まれていればよい?
単に含まれるだけだと関係ないエントリも取得してしまう
重要な単語が含まれることは重要
キーワードのスコアを利用
27
シャルリ、エブド、赦す、ムハンマド、風刺
"buckets": [
{ "key": "シャルリ", "score": 129926.04 }, { "key": "エブド", "score": 99737.62 },
{ "key": "赦す", "score": 5522.22 }, { "key": "ムハンマド", "score": 4729.32 },
{ "key": "風刺", "score": 4172.57 }
]
記事スコア
「シャルリ」「エブド」を含む記事の場合
記事スコア = 0.94
( 129926+99737 / 129926+99737+5522+4729+4172 )
28
"buckets": [
{ "key": "シャルリ", "score": 129926.04 }, { "key": "エブド", "score": 99737.62 },
{ "key": "赦す", "score": 5522.22 }, { "key": "ムハンマド", "score": 4729.32 },
{ "key": "風刺", "score": 4172.57 }
]
記事スコア =
記事に含まれるトピックキーワードのスコアの和
トピックキーワードのスコアの和
トピックにどの程度関連する記事か
キーワードスコアを考慮した記事検索
● トピックキーワードに関連する記事の検索
○ 記事スコアを考慮して取得したい
● Elasticsearchの通常の検索
○ TF-IDF, BM-25
○ トピックキーワードのスコアを考慮できない
● Function Score Query
○ 独自のスコアイングが可能
29https://www.elastic.co/guide/en/elasticsearch/reference/1.6/query-dsl-function-score-query.html
30
“function_score”: {
“query”: { “bool”: {
“should”: [ … ], “minimum_should_match”: 1,
} },
“functions”: [ { “script_score”: {
“params”: {
“field”: “title”,
“words”: [ "シャルリ", "エブド", "赦す", "ムハンマド", "風刺" ],
“scores”: [ 129926.04, 99737.62, 5522.23, 4729.32, 4172.57 ]
},
“lang”: “groovy”,
“script”: “def score=0;for(i in 0..4) { if (_index[field][words[i]].tf() > 0) { score +=
scores[i]}; scores;”
} } ],
“min_score”: 195270
}
31
“function_score”: {
“query”: { “bool”: {
“should”: [ … ], “minimum_should_match”: 1,
} },
“functions”: [ { “script_score”: {
“params”: {
“field”: “title”,
“words”: [ "シャルリ", "エブド", "赦す", "ムハンマド", "風刺" ],
“scores”: [ 129926.04, 99737.62, 5522.23, 4729.32, 4172.57 ]
},
“lang”: “groovy”,
“script”: “def score=0;for(i in 0..4) { if (_index[field][words[i]].tf() > 0) { score +=
scores[i]}; scores;”
} } ],
“min_score”: 195270
}
シャルリ OR エブド OR 赦す OR ムハンマド OR 風刺
トピックキーワードのスコアの和を計算
記事スコアが0.8(195270)以上
トピックキーワードに関連する記事例
32
シャルリ、エブド、赦す、ムハンマド、風刺
● パリで風刺週刊誌『シャーリー・エブド』銃撃事件。死者10名 - Togetterまとめ
● Yahoo!ニュース - 風刺週刊紙建物で銃撃、11人死亡=イスラム過激派の犯行か―パ
リ (時事通信)
● 【シャルリー・エブド】パリで襲撃された新聞はどんなことを報じていたのか
● 時事ドットコム:「ひれ伏すより立って死ぬ」=過激主義との対決貫く−仏銃撃事件で
殺害の風刺画家
● 我々イスラム教徒は「シャルリー・エブド」を支持する | Asif Arif
● 【パリ銃撃】メディアは風刺漫画をどう掲載したか 各社で分かれた判断
● フランスの立てこもり 容疑者2人死亡 NHKニュース
● 仏の立てこもり、容疑者が電話で語った内容とは:朝日新聞デジタル
トピックのマージ
同じ内容を表すトピックをマージする
重複トピック生成の予防
トピックの変化への追従
以下を考慮してトピックを統合
トピックのキーワードのスコア重複率
トピックの記事の重複率
33
シャルリ、エブド、赦す、ムハンマド、風刺
エブド、シャルリ、赦す、ムハンマド、風刺
34
まとめ
Elasticsearchを使ってトピックを生成
ブックマークに蓄積された過去10年のデータを利用
Significant Terms Aggregation
Function Score Query
35
参考文献
確率的トピックモデル:
http://www.ism.ac.jp/~daichi/lectures/ISM-2012-TopicModels-daichi.pdf
Elasticsearch:
aggregation significant terms:
http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-aggregations-
bucket-significantterms-aggregation.html
aggregation significant terms (JLH):
http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-aggregations-
bucket-significantterms-aggregation.html#_jlh_score
function score:
http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-function-score-
query.html
36

More Related Content

Elasticsearchを用いたはてなブックマークのトピック生成