4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

mahout をとりあえず動かしてレコメンドしてみる(動作確認程度)

Last updated at Posted at 2015-11-19

シンプルなレコメンドの考え方

特にMahoutの仕組や分散による高速化には触れない。
ごく単純にmahoutをJavaで試すだけ。

但し、前提として単純に言うと

好きなもの 好きなもの 好きなもの
Aさん 林檎 蜜柑
Bさん 葡萄 バナナ
Cさん 林檎 蜜柑
Dさん 林檎 蜜柑

さて、Cさんが次に欲しいものは何?

感覚的にそれは「おそらく苺」だろう、と。

ここでは4件しか無い上に好きなもの丸かぶりだから直ぐ分かるけど
Cさんに似た嗜好を持つ人はだれかを探して(AさんとDさん)、
そこからオススメの果物(苺)をレコメンドする。

image

今回はユークリッド距離を利用し、
より距離が近い=好みが類似している人を特定する。
(映画の評価など厳しめや甘めの人が混在するような場合は
本当はユークリッド距離は向かない)

実装

maven

pom.xml
    <dependency>
        <groupId>org.apache.mahout</groupId>
        <artifactId>mahout-core</artifactId>
        <scope>provided</scope>
        <version>0.9</version>
    </dependency>
    <dependency>
        <groupId>org.apache.mahout</groupId>
        <artifactId>mahout-math</artifactId>
        <scope>provided</scope>
        <version>0.10.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.mahout</groupId>
        <artifactId>mahout-examples</artifactId>
        <scope>provided</scope>
        <version>0.10.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.mahout</groupId>
        <artifactId>mahout-collections</artifactId>
        <scope>provided</scope>
        <version>1.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.mahout</groupId>
        <artifactId>mahout-utils</artifactId>
        <scope>provided</scope>
        <version>0.5</version>
        <exclusions>
            <exclusion>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-jcl</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

Javaコード

sample.java
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.impl.common.FastByIDMap;
import org.apache.mahout.cf.taste.impl.model.GenericDataModel;
import org.apache.mahout.cf.taste.impl.model.GenericPreference;
import org.apache.mahout.cf.taste.impl.model.GenericUserPreferenceArray;
import org.apache.mahout.cf.taste.impl.neighborhood.NearestNUserNeighborhood;
import org.apache.mahout.cf.taste.impl.recommender.GenericUserBasedRecommender;
import org.apache.mahout.cf.taste.impl.similarity.EuclideanDistanceSimilarity;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.model.Preference;
import org.apache.mahout.cf.taste.model.PreferenceArray;
import org.apache.mahout.cf.taste.neighborhood.UserNeighborhood;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.mahout.cf.taste.recommender.Recommender;
import org.apache.mahout.cf.taste.similarity.UserSimilarity;

public class AdHocTestSpace {
    public static void main(String argv[]){
        
        try {
            /*
            * 数値型に置き換えて値を渡す
            * 第1引数
            *   100 Aさん
            *   200 Bさん
            *   300 Cさん
            *   400 Cさん
            *
            * 第2引数
            *   1 林檎
            *   2 蜜柑
            *   3 苺
            *   4 梨
            *   5 葡萄
            *   6 バナナ
            *
            * 第3引数
            *   ここは好みを表すが今回は5.0固定(値に特に意味は無い)
            *   やろうと思えば
            *   1.0 あんまり・・・
            *   2.0 ふつー
            *   3.0 好き
            *   みたいに好みの重さを指定できる。
            */
            
            List<Preference> list_1 = new ArrayList<>();
            List<Preference> list_2 = new ArrayList<>();
            List<Preference> list_3 = new ArrayList<>();
            List<Preference> list_4 = new ArrayList<>();
            
            // Aさんは、林檎と蜜柑と苺が好き
            list_1.add(new GenericPreference(100, 1, 5.0f));
            list_1.add(new GenericPreference(100, 2, 5.0f));
            list_1.add(new GenericPreference(100, 3, 5.0f));
            
            // Bさんは、梨と葡萄とバナナが好き
            list_2.add(new GenericPreference(200, 4, 5.0f));
            list_2.add(new GenericPreference(200, 5, 5.0f));
            list_2.add(new GenericPreference(200, 6, 5.0f));
            
            // Cさんは、林檎と蜜柑が好き
            list_3.add(new GenericPreference(300, 1, 5.0f));
            list_3.add(new GenericPreference(300, 2, 5.0f));

            // Dさんは、林檎と蜜柑と苺が好き
            list_4.add(new GenericPreference(400, 1, 5.0f));
            list_4.add(new GenericPreference(400, 2, 5.0f));
            list_4.add(new GenericPreference(400, 3, 5.0f));
            
            /*
             * これらの情報をモデルにセット
             */
            FastByIDMap<PreferenceArray> input_info = new FastByIDMap<>();
            input_info.put(100, new GenericUserPreferenceArray(list_1));
            input_info.put(200, new GenericUserPreferenceArray(list_2));
            input_info.put(300, new GenericUserPreferenceArray(list_3));
            input_info.put(400, new GenericUserPreferenceArray(list_4));
            
            DataModel model = new GenericDataModel(input_info);
            
            // ユークリッド距離を利用
            UserSimilarity similarity = new EuclideanDistanceSimilarity(model);
            
            /**
             * 類似(距離の近い)ユーザをn件迄を検索
             * とりあえず、3くらいで
             */
            UserNeighborhood neighborhood = new NearestNUserNeighborhood(3, similarity , model);
            
            /**
             * Cさんの好みをレコメンド
             * 結果は 3:苺 になる
             */
            Recommender recommender = new GenericUserBasedRecommender(model, neighborhood, similarity);
            List<RecommendedItem> rcmmList = recommender.recommend(300, 5);
            System.out.println("Cさんにオススメしたい果物のIDは以下のとおり");
            rcmmList.stream().forEach(System.out::println);
            
        } catch (TasteException ex) {
            Logger.getLogger(AdHocTestSpace.class.getName()).log(Level.SEVERE, null, ex);
        }
    }    
}
4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?