[Hadoop]Hadoop上でMahoutを使って「このアイテムを見た人は、こちらのアイテムも見ています」というレコメンドをやってみる
前回はHadoopのインストールで、今回がいきなり実用的な内容で、ちょっと基礎を飛ばしてますが、気にしない。
レコメンドというと、パッと思いつくのはAmazonのレコメンドではないでしょうか。
商品を見ていると、「この商品を買った人はこれも一緒に買っています。」といった感じの物ですね。
今回はこのレコメンドを簡単に実装する方法を探ってみます。
まず、解析後に欲しいデータとして
あるアイテム(item1)に対して、関連するアイテム(item2,item3,item4)をひもづけるデータです。
データベースに入れて使える状態で言うと
(ユーザが今開いたアイテムのID), (ユーザが開いたアイテムに関連するアイテムのID)
item1, item2
item1, item3
item2, item4
…
というキーバリューのペアです。
この結果を得るために必要な情報ですが
ユーザ毎にアクセスしたアイテムの一覧を、解析にかける元データとします。
ユーザID, アイテムID
user1, item1
user1, item2
user1, item4
user2, item1
user2, item5
user3, item3
…
というキーバリューのペアです。
このデータから解析結果を導き出すのですが
Hadoop界隈には、便利な機械学習ライブラリがあります。
Mahoutというライブラリで、様々な解析をするジョブがたくさん入っています。
今回はこの中のItemSimilarityJobという機能を使います。
ItemSimilarityJobには解析方法として
SIMILARITY_COOCCURRENCE
SIMILARITY_LOGLIKELIHOOD
SIMILARITY_TANIMOTO_COEFFICIENT
SIMILARITY_CITY_BLOCK
SIMILARITY_COSINE
SIMILARITY_PEARSON_CORRELATION
SIMILARITY_EUCLIDEAN_DISTANCE
というオプションが指定できます。
今回はSIMILARITY_COSINEという、コサイン関数による類似アイテムの解析を実行します。
とりあえず、ItemSimilarityJobのオプションを見てみましょう。
$> hadoop jar $MAHOUT_HOME/mahout-core-0.6-job.jar org.apache.mahout.cf.taste.hadoop.similarity.item.ItemSimilarityJob
とすれば、オプションの一覧が表示されます。
usage: [Generic Options] [Job-Specific Options] Generic Options: -archives comma separated archives to be unarchived on the compute machines. -conf specify an application configuration file -D <property=value> use value for given property -files comma separated files to be copied to the map reduce cluster -fs <local|namenode:port> specify a namenode -jt <local|jobtracker:port> specify a job tracker -libjars comma separated jar files to include in the classpath. -tokenCacheFile name of the file with the tokens Job-Specific Options: --input (-i) input Path to job input directory. --output (-o) output The directory pathname for output. --similarityClassname (-s) similarityClassname Name of distributed similarity measures class to instantiate, alternatively use one of the predefined similarities ([SIMILARITY_COOCCURRE NCE, SIMILARITY_LOGLIKELIHO OD, SIMILARITY_TANIMOTO_CO EFFICIENT, SIMILARITY_CITY_BLOCK, SIMILARITY_COSINE, SIMILARITY_PEARSON_COR RELATION, SIMILARITY_EUCLIDEAN_D ISTANCE]) --maxSimilaritiesPerItem (-m) maxSimilaritiesPerItem try to cap the number of similar items per item to this number (default: 100) --maxPrefsPerUser (-mppu) maxPrefsPerUser max number of preferences to consider per user, users with more preferences will be sampled down (default: 1000) --minPrefsPerUser (-mp) minPrefsPerUser ignore users with less preferences than this (default: 1) --booleanData (-b) booleanData Treat input as without pref values --threshold (-tr) threshold discard item pairs with a similarity value below this --help (-h) Print out help --tempDir tempDir Intermediate output directory --startPhase startPhase First phase to run --endPhase endPhase Last phase to run Specify HDFS directories while running on hadoop; else specify local file system directories
このオプションの中で今回設定する物は、
です。
inputは、解析する元データ
outputは解析結果の保存場所
similarityClassnameは解析方法
booleanDataは、元データにレートがあるかどうか
今回の元データには、レートがないので、booleanDataにはtrueを指定
similarityClassnameにはSIMILARITY_COSINEを指定します。
では、元データを準備してみましょう。
○user-item.tsv(実際に使った物はもっとでかい)
10000 4577 10000 5724 10000 6195 10000 4569 10000 1930 10000 1583 10000 2295 10000 5454 10000 4569 10000 2672 10000 5926 10000 5906 10000 5126 20000 3278 30000 5655 40000 3192 50000 3362 60000 2779 70000 2670 80000 4203 90000 6468 100000 269 110000 3192 120000 3817 130000 3096 140000 2703 140000 3228
このファイルを、HadoopのHDFS上に送り込みます。
$> hadoop fs -put user-item.tsv data
これでhadoopのHDFS上にファイルが送信されました。
このファイルをItemSimilarityJobで解析するようにコマンドオプションを組み立ててみます。
$> hadoop jar $MAHOUT_HOME/mahout-core-0.6-job.jar \ org.apache.mahout.cf.taste.hadoop.similarity.item.ItemSimilarityJob \ -Dmapred.input.dir=data \ -Dmapred.output.dir=output \ --similarityClassname SIMILARITY_COSINE \ --booleanData true
このコマンドを実行すると、outputに解析結果ファイルが作成されます。
$> hadoop fs -cat output/part-r-00000 2 15 0.3333333333333333 2 19 0.7071067811865475 2 23 0.7071067811865475 2 33 0.5773502691896258 2 34 1.0 2 45 0.7071067811865475 2 46 0.5 2 51 0.31622776601683794 2 882 0.3779644730092272 2 905 0.5773502691896258 2 1104 0.7071067811865475 2 1360 0.31622776601683794 2 1438 0.2672612419124244 2 1695 0.4472135954999579 2 2507 0.30151134457776363 2 5082 0.35355339059327373 15 19 0.2357022603955158 15 23 0.2357022603955158 15 33 0.19245008972987526 15 34 0.3333333333333333 15 45 0.2357022603955158 15 46 0.16666666666666666 15 905 0.19245008972987526 15 1104 0.2357022603955158 15 2444 0.19245008972987526 15 3382 0.13608276348795434 19 23 0.4999999999999999 19 33 0.408248290463863 19 34 0.7071067811865475 19 35 0.408248290463863 19 45 0.4999999999999999 19 46 0.7071067811865475 19 58 0.408248290463863 19 882 0.26726124191242434 19 905 0.408248290463863 19 1104 0.4999999999999999 19 1360 0.22360679774997896 19 1623 0.2357022603955158 19 1695 0.3162277660168379 19 2278 0.2041241452319315 19 2398 0.2886751345948129 19 2435 0.35355339059327373 19 2507 0.21320071635561041 19 3764 0.26726124191242434 19 4964 0.35355339059327373 19 5082 0.4999999999999999 19 5132 0.18257418583505533 19 5468 0.16222142113076252 19 5475 0.3162277660168379 19 5877 0.35355339059327373 19 6064 0.15811388300841894 23 33 0.408248290463863 23 34 0.7071067811865475 23 45 0.4999999999999999 23 46 0.35355339059327373 23 51 0.22360679774997896 23 882 0.26726124191242434 23 905 0.408248290463863 23 1104 0.4999999999999999 23 1360 0.22360679774997896 23 1695 0.3162277660168379 23 2507 0.21320071635561041 23 5082 0.24999999999999994 27 965 0.05504818825631803 27 1160 0.057735026918962574 27 1478 0.04564354645876384 27 2924 0.06085806194501845 27 3222 0.04564354645876384 27 3945 0.07453559924999299 27 4790 0.09128709291752768 27 5543 0.06085806194501845 27 5839 0.05063696835418333 27 6390 0.06085806194501845 28 2265 0.10910894511799618 28 2333 0.15811388300841894
という感じで、できあがります。
一つ目のアイテムIDに対して、二つ目が関連するアイテムID、最後にそのアイテムのレート(おすすめ度?)となります。より近いアイテムほど数値が高くなります。
なので、おすすめとして表示する時にはレートでソートして表示するのが良いかもしれません。