[Hadoop]Hadoop上でMahoutを使って「このアイテムを見た人は、こちらのアイテムも見ています」というレコメンドをやってみる

2012年4月19日

前回は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

です。

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、最後にそのアイテムのレート(おすすめ度?)となります。より近いアイテムほど数値が高くなります。

なので、おすすめとして表示する時にはレートでソートして表示するのが良いかもしれません。

HadoopMahout

Posted by GENDOSU