Mahoutでレコメンドを作ってみよう!
目次
こんにちは。入社2年目の大橋です。昨年の話ですが、Mahoutを使ってレコメンド機能を実装しました。右も左もわからないというところから始めましたが、実際にやってみたら割と簡単に作れました。というわけで今回はApache MahoutというJavaライブラリを使って、Javaでレコメンド機能を実装する方法をご紹介します。
Mahoutとは
Apache Software Foundationが公開しているOSSの機械学習ライブラリです。今回は、Mahoutの一機能であるレコメンドを紹介します。Z
レコメンドとは
ショッピングサイトでよく見かける「この商品を見ている人は、こういう商品も見ています」、「あなたへのおすすめ」を算出してくれる機能がレコメンドです。レコメンドは大きく分けて、ユーザベースとアイテムベースの2種類があります。
ユーザベース | レコメンド対象となるユーザーと類似しているユーザーが*評価したアイテムを算出する |
---|---|
アイテムベース | 対象となるアイテムと類似したアイテムを算出する |
*ここでいう評価とは、ユーザーがアイテムに対して行う全ての操作(閲覧、購入、レイティングなど)を意味する
レコメンドの仕組み
ユーザベース:
アイテムベース:
*レコメンダとはレコメンドを提供してくれるプログラム
基本的な使い方
さて、本題に入りましょう。Mahoutの使い方を説明していきます。
レコメンドを実現するためにはまずデータが必要です。
ここで、下表の3種類のデータを用います。
定義 | 説明 | 例 |
---|---|---|
ユーザー | ユーザーを表す値 | ユーザIDなど |
アイテム | 商品などを表す値 | 商品IDなど |
プリファレンス | 嗜好の度合い | ユーザ自身の評価(レイティング)、購入回数など |
ユーザーがアイテムを評価した時に「ユーザー」、「アイテム」をプログラムを用いて蓄積していきます。またオプションとして、プリファレンスを加えることがよくあります。
プリファレンスとは、ユーザーがアイテムに対してどれくらい評価しているかを表す値です。例えば、ECサイトなどのレイティング機能を用いて、レイティングの結果をプリファレンス値として蓄積したりします。または動画なら再生数、商品なら購入履歴などの数よりプリファレンス値を生成することもできます。
もちろん、プリファレンス値が必要ない場合もあります。その時、プログラムはユーザーがアイテムを評価したと判断し、ブーリアン値や固定値(1など)を設定すれば良いです。
プリファレンス値のイメージとしてユーザーとアイテムの関係図で見ると掴みやすいかと思います。
図のようにアイテムとユーザーを繋いでいる線が太くて短いほど、プリファレンス値が高くなります。プリファレンスがない場合、全て線が同じ長さで、ユーザーとアイテムの間も同じ距離になります。
ではこのようなデータを取得したとしましょう。
あとはMahoutに任せれば、レコメンド候補を算出するところまで一気にできます。
sample.java(ユーザーベースの場合)
1 2 3 4 5 6 7 8 |
// CSVファイルのデータを読み込みDataModelに入れる DataModel model = new FileDataModel(new File("/Users/ohashi/Downloads/data.csv")); // DataModelのデータに基づき、商品の類似度を算出する UserSimilarity similarity = new PearsonCorrelationSimilarity(model); // 類似度の高いアイテムを取得する UserNeighborhood neighborhood = new NearestNUserNeighborhood(2, similarity, model); // レコメンドアイテムを算出する Recommender recommender = new GenericUserBasedRecommender(model, neighborhood, similarity); |
これでレコメンドするための準備が整いました。と言っても何がなんだか分からないですよね。使用したインターフェースを順番に説明します。
インターフェース | 説明 |
---|---|
DataModel | User、Item、Preference を蓄積するストレージ |
UserSimilarity | 2人のユーザーの間の類似性を定義するインターフェース(アイテムベース用のItemSimilarityもあります) |
UserNeighborhood | ユーザーに近い他のユーザーたちを算出するインターフェース(Mahoutではそのユーザーたちを「近傍」と呼ぶ) |
Recommender | レコメンドを提供するためのインターフェース、DataModel、UserSimilarity、UserNeighborhoodをもとに生成される |
また、PearsonCorrelationSimilarity、NearestNUserNeighborhoodとGenericUserBasedRecommenderなどは、レコメンダを算出するためのインターフェースの実装クラスです。他にもたくさんあるのでここでは説明しません。詳しい情報はAPIを参照していただければと思います。
さて、いよいよレコメンダ(Recommender)にユーザーへのレコメンドを出してもらいましょう。
1 |
List<RecommendedItem> recommendations = recommender.recommend(1, 3); |
メソッドの中の引数は、ユーザーIDが1の人に対して、3つのアイテムをレコメンドするという意味です。
1 2 3 |
for (RecommendedItem recommedation : recommendations) { System.out.println(recommedation); } |
出力結果は以下のようになります。valueの値で表されているのはおすすめ度です。(3つのアイテムをレコメンドしていますが、この例ではデータがあまりに少なく、2つしか算出できませんでした)
まとめ
今回はサンプルコードを紹介しましたがいかがでしたか?わりとシンプルな構造ではないでしょうか。機械学習とかレコメンドというと難しそうに思えますが、適切なモデルを選び、データをちゃんと渡すことさえできれば、後はMahoutのAPIから生成されるインスタンスたちが適切に処理してくれます。
どんなレコメンドにしようと、Mahoutのインターフェースを使うことになりますが、機能の目的やコンセプトとマッチした実装クラスを適切に選ぶことがとても重要です。それぞれの実装クラスで類似度(similarity)、近傍(Neighborhood)を算出する数式が違いますので、それによってレコメンド結果は変わってきます。また精度の高いレコメンドを実現するためには、データをできるだけ多く取得して適切なプリファレンス値を得ることがポイントです。