Upload
sho-shimauchi
View
3.435
Download
3
Embed Size (px)
DESCRIPTION
This document is written about "Data-Intensive Text Processing with MapReduce" Chapter 4.This chapter describes how to design inverted index with MapReduce algorithm.
Citation preview
Data-Intensive Text Processing with MapReduce
(Ch4 Inverted Indexing for Text Retrieval)
2010/10/03shiumachi
http://d.hatena.ne.jp/shiumachi/http://twitter.com/shiumachi
Agenda
● 4章 テキスト検索のための転置インデックス● 4.1 Webクローリング● 4.2 転置インデックス● 4.3 転置インデックスの基本実装● 4.4 転置インデックスの改良版● 4.5 インデックス圧縮● 4.6 Retrievalには使えるの?● 4.7 まとめ(より深く勉強したい人への案内)
Chapter 4Inverted Indexing for Text Retrieval
4章テキスト検索のための転置インデックス
Web検索● Webって結構でっかいよ
● 数百億ページ● テキストだけで数百TB
● でもユーザは検索を待ってはくれない● せいぜい数百ms
● Web 検索というのは非常に特殊だけど不可欠なlarge-data problem
Web検索の3要素● crawling, indexing, retrieval● crawling と indexing は性質的に似ている
● リアルタイム性は必要ない● オフラインで処理可能● 要スケーラビリティ
● retrieval は全く逆● リアルタイム性が要求される● 突然のクエリ増加にも耐えられる必要がある
転置インデックス● Web検索における標準的なデータ構造● term に対し、document と payload のリストが割り当てられて構成されている
● この章のメイン。後述
4.1 Webクローリング
なんでクローリングの話?● Webページのデータなんて金出せば買えない?
● 学術目的ならカーネギーメロン大学に問い合わせれば一応手に入る(25TBほど)
● でも現実のWebデータは更新され続けてるわけだし、これじゃ到底用をなさない
● クローラなんて作るの簡単じゃない?● html → →ページを取得 リンク取得 リンク先のページ
→ →……を取得 リンク取得 だけ● 概念的にはそれでOKだが、実際作るとなるといろいろ問題が発生する
クローリング、ここに注意● Webサーバに高負荷かけないエチケット
● librahack を思い出そう● クロール先のスコアリング
● スパム避けして優先順位つける● Webはコピーされた文書がいっぱいなので、どれがクロールするのに適切かを見極める
● 更新頻度のパターンを分析する● 普通は分散クラスタを組むので障害対策は万全に● Webは多言語。英語・日本語・中国語混じってて当たり前● とても書ききれないので詳しくは自分で調べろ
4.2 転置インデックス
転置インデックスの構造
● 1 つの term に対し、<doc-id,payload> のリストが並ぶ● payload は千差万別
● その term が文書に出てくる頻度は比較的単純なもの● 出てくる位置とか、タイトルに出てくるかどうかとか、payload に入るものはプログラマ次第
payload (postingじゃないよ)
検索の仕組み(ブーリアン検索)
天一 こってり
天一
こってり doc 100 1 doc 200 3 doc 300 4
doc 10 1 doc 100 2 doc 200 1
OR検索なら全てのドキュメントが対象になるが、AND検索なら両方のキーワードが共通して登場するドキュメントのみ考慮する
普通は関連文書などをあらかじめ計算しておいて(アキュムレータ)、計算コストをさらに下げたりする
インデックスも大変● インデックスは巨大なので普通はメモリに乗らない
● だからディスクに置いたりするのが普通● でもGoogleは全部メモリに乗せてるとか
● クローリングと同様、概要しか説明してないので興味があれば自分で調べること
4.3 転置インデックスの基本実装
MapReduceだとメチャ簡単です● 通常転置インデックスは巨大なので、実装しようと思うとメモリ管理とかもろもろしなきゃいけないので大変
● しかしMRならそんなことを気にしなくても大丈夫
● 大学1年生レベルでも簡単に実装できます● 上級生なら1週間あれば書けるでしょ
図4.2 MapReduceによる転置インデックス実装 今回は payload を頻度で出している。
一目でわかる通りとても単純。
図4.2 の解説● Map
● ワードカウントして <term,<文書id, count>>で出力してるだけ
● count の部分が payload。別に他のものに変えても構わないし、それはとても簡単
● Reduce● Mapからきたデータのvalueをposting list にして出力してるだけ
● 具体例は図4.3にある
図4.3 MapReduceによる転置インデックス作成(具体例)
4.4 転置インデックスの改良版
やっぱりメモリに乗りません● 図4.2 のコードは、ポスティングデータがメモリに乗ることが前提● スケールしないのでなんとかしよう
● value-to-key conversion パターンを使う
<term t, <docid, f>>
<<term t, docid>, f>
図4.4 MapReduceによる転置インデックス実装(改良版)value-to-key conversion パターンを実装したもの。
図4.4 の解説● Map については前述の通り
● ただしPartitioner は自作する必要がある(同一termが同一reducerに集まるようにしなければならない)
● Reduce● 現在のtermと一つ前のtermが異なっていたら、ある
termの処理が完了しているとみなしてEmit()● データ末尾のtermの場合はClose処理内でEmit()
ドキュメントの長さ● ほぼ全ての検索モデルで必須● MRにおける計算方法は2つ
● in-mapper combining パターンを使ってメモリ上に長さを持っておき、CLOSE処理時にサイドデータとして書き出す– 通常これがメモリあふれを起こすことはない(らしい)
● 特殊なkey-valueペアを持たせておき、これだけ別処理が走るようにする(3.3 での * みたいに)
4.5 インデックス圧縮
インデックス圧縮● ナイーブな実装は d-gap
● 数値そのものを保存するのではなく、ソートした上でその差分だけを保存
● うまく一定のデータ単位に収めると、速度・サイズともに効率のいい圧縮ができる
1, 2, 4, 7, 12, 17, ...
1, 1, 2, 3, 5, 5, ...
バイト単位コード、ワード単位コード
● 数値を表すのに1ワードで表すと圧縮にならない(後述)
● 1バイト、1ワードのうち数ビットを区切り位置指定用予約スペースにし、残りをうまく切り分けてやると効率よくデータを収めることができる
そのままだと圧縮にならない?● 4バイト符号なしint型を考える
● ソートして差分をとっているため負数は考えなくていい
● 差分の最大値は当然2^32-1、つまり上記int型の最大値に等しい
● よって、1通りのデータ形式で表そうと思ったらやっぱり4バイト必要になる
varInt 法
必要なバイト数だけ使おう
1 1 1 1 1 1 1 1
終端フラグ1 で終端を示す
値保持領域7bit分のデータを保持
例) 127, 128 の場合
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0
127までなら1バイトで表せる
varInt 法の改良(group varInt)
GoogleのJeff Deanが開発。varIntより高速ある1バイト全部を、続く数バイトの内訳を示すのに使う
次の値が1バイトであることを示している
0 0 0 1 1 0 1 100〜11で1〜4を表している
この例の場合、続く4つの値はそれぞれ1バイト、2バイト、3バイト、4バイトとなる
Simple-9
4バイトの上位4bitをフラグとして、残り28bitを9通りの方法で分割する
1 1 1 1 1 1 1 1
フラグ28bitを指定された方法で分割
値保持領域28bit分のデータを保持
111 1…
Simple-9 のフラグ [4] 上位bit 符号の個数 符号のビット長0000 28 1
0001 14 2
0010 9 3
0011 7 4
0100 5 5
0101 4 7
0110 3 9
0111 2 14
1000 1 28
最適化するにはDPを使う必要があるが、tsubosakaさんによると0.2%ほどしか圧縮率
が改善しなかったため実用的ではないらしい [4]
ビット単位コード● バイト単位コード
● 高速● 無駄ビットが多い
● ビット単位コードだと無駄ビットが出ない● 1つの値を表すビット範囲を示すのにprefixコードを使う● prefix-free コードとも呼ばれるらしい。どっちやねん
図4.5 bit-aligned code における prefix コードの一例
unary code(alpha code)
● 0からスタート● 1を示している。1が最小値。他のprefixコードも同じ
● 10, 110, 1110, ... と続く(それぞれ2, 3, 4)
● 見ての通り効率メチャ悪いのでこのまま使われることはない● が、他のコーディングスキームの一部となっている
Elias Gamma Code
unary code + binary code の組み合わせ 以下の例は 9 を表している
1 1 1 0 0 0 1
unary code3bit が後ろに続くことを示している
binary code000 = 1 なので
これは 2 を表している
いくつかの gamma code をまとめて別の gamma code で表す delta code というのもある
大きい数値を扱う場合は delta の方がいい
Golomb code
パラメータを用いた符号化 以下はパラメータ b = 10 で 32 を表したとき
1 1 1 0 0 0 1
unary code値をbで割ったときの商32/10 の商は3
binary code000 = 1 なので
これは 2 を表している
バイナリコード部分はパラメータや値によってビット数が変わる(が、説明大変なので省略)
パラメータが2のべき乗のときRice code という
ゴロム符号と d-gap
d-gap に適用するときの最適なパラメータは以下の式で算出できる
N:ドキュメントの数df: ある term の document frequency
符号化の速度比較● エンコードはGolomb(Rice)が一番速く、group
varInt が一番遅い● デコードは全く逆
● group varInt 最速、ビット符号化が遅い● Riceはその中では最速、Golombが一番遅い(group
varInt の 1/10)
MapReduce と Golomb コード● Golomb の最適パラメータの計算には df が必要
● 事前に計算しておく必要がある● 鶏が先か卵が先か
● メモリに載らないから圧縮しようとしてるのにその計算をするのにメモリに載せなきゃいけない
● in-mapper combining パターンと order inversion パターンを使って解決しよう
in-mapper combining で df を出す
<<term t, docid>, tf f>
<<term t, *>, df e>
1つのmapタスクで処理した文書集合におけるdfはin-mapper combiningを使えば算出可能(単に出現した文書数をカウントアップするだけ)
この * つき出力を order-inversion で各termの一番最初に 来るようにすれば、トータルの df を得た上で b を計算
可能
4.6 Retrievalには使えるの?
big data における検索● リアルタイム処理が要求されるので
MapReduceはどの道無理● 以下MapReduce ……全く出てこない
● でも分散させるのは一緒● 分散の方法は2つ
● ドキュメントを分割し、それぞれのサーバで全てのterm を持つ
● term を分割し、それぞれのサーバで全てのドキュメントを持つ
図4.6 ドキュメント分割とterm分割を表した図縦に3分割するとドキュメントの分割になり、横に3分割するとtermの分割になる
ドキュメントの分割● 長所
● レイテンシが短くなる● 短所
● 全サーバにクエリを投げるので負荷が高くなる
termの分割● 長所
● トータルのディスクアクセスの量が少ないため高スループット
● 短所● レイテンシ長い● クエリ評価が複雑になる● クラスタ全体のハードウェア障害耐性が低い
● 結局はドキュメント分割の方に分がある● Googleが採用してるのもドキュメント分割
ドキュメント分割の方法● クオリティで分割
● 優先度の高いページをまとめたインデックスを作っておき、優先度の高い方から順にアクセスしていく
● コンテンツで分割● 多分どんな種類のコンテンツかということだと思う
他にも考えなきゃいけないことがいっぱい
● サーバは地理的に分散している場合がある● 一番近いサーバを選択する手法
● 検索して返すのはドキュメントIDだけだが、これは何も意味がない● 文書サーバを別に立て、IDからメタデータを引けるようにする必要がある
● クエリも投入頻度が異なる● 頻出クエリ用のサーバを上位に位置づけることで負荷低減
参考文献
1. Facebook has the world's largest Hadoop cluster!, Facebook has the world's largest Hadoop cluster!, http://hadoopblog.blogspot.com/2010/05/facebook-has-worlds-largest-hadoop.html
2. ユーティリティコンピューティング, wikipedia, http://ja.wikipedia.org/wiki/%E3%83%A6%E3%83%BC%E3%83%86%E3%82%A3%E3%83%AA%E3%83%86%E3%82%A3%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0
3.Hadoop, Tom White, オライリー・ジャパン, 2009
4.Simple-9 – について解説 tsubosakaの日記, http://d.hatena.ne.jp/tsubosaka/20090810/1249915586
Thank you !