<< I/O Multiplexing(select, poll, epoll, kqueue) | Home | 처세술 >>

Mahout를 활용한 영화 추천 샘플링

1. 기계 학습 개요
- Collaborative filtering : 사람들 중에 나와 비슷한 기호를 가지고 있는 사람이 추천 점수를 순위를 매겨서 활용함.
  • User-based : 유사한 사용자를 찾아서 항목을 추천. 사용자가 많을 경우 성능 저하가 됨.
  • Item-based : Item 간의 유사성을 계산하여 추천. 미리 비슷한 상품들은 계산해 놓고(item similarity table 유지 비용은 있지만) 추천할때 필터링하면 성능 효과를 볼 수 있음.
  • Slope-One : 사용자가 등급을 지정할 때 적용 가능한 매우 빠르고 간단한 항목 기반의 추천 방식.
  • Model-based : 사용자와 등급으로 구성된 모델을 기반으로 추천.

- Clustering : 대량의 데이터 세트가 있을 경우 유사한 항목끼리 그룹화 또는 클러스터링하는 방법.
  • K-means.
  • Fuzzy K-means.
  • Canopy.
  • Dirichlet.
  • Mean-Shift.

- Classification(Categorization) : 항목에 레이블을 지정하여 분류하는 것.
  • Distributed Naive Bayes.
  • Complementary Naive Bayes.

유사성(Similarity) 발견하는 방법으로는
  • Euclidean distance : 두 개체간의 Euclidean 거리를 측정해서 가까운 개체끼리 묶음.
  • Pearson Correlation Score : 얼마나 두 변수들의 집합이 일직선에 위치하는가 평가. 크고 작음의 편차를 극볼할 수 있음.
  • Manhattan distance : 직각 형태로 두 축사이의 거리 측정해서 유사도 확보.
  • Cosign similirity : 두 개체 벡터의 코사인 유사도.

2. Mahout 개요 및 내부 구조
Mahout은 현재 빠르고 유연한 CF용 엔진인 Taste 라이브러리를 통해 추천 엔진을 빌드할 수 있는 도구를 제공한다. Taste는 사용자 기반 및 항목 기반 추천을 지원하며 추천 항목을 만들 수 있는 여러 가지 선택 사항과 사용자가 정의할 수 있는 인터페이스도 함께 제공한다.
Taste는 User, Item 및 Preference와 작동하는 다음과 같은 5가지 주요 구성 요소로 구성되어 있다.
  • DataModel: User, Item 및 Preference를 위한 저장소
  • UserSimilarity: 두 사용자 간의 유사성을 정의하는 인터페이스.
  • ItemSimilarity: 두 항목 간의 유사성을 정의하는 인터페이스.
  • Recommender: 추천 항목을 제공하기 위한 인터페이스.
  • UserNeighborhood: Recommender에 의해 사용될 수 있는 유사한 사용자의 인접성을 계산하기 위한 인터페이스.

3. Mahout 맛보기
- Mahout 컴파일
특별한 이유가 없다면 최신 버전을 받기 위해서 svn으로 받음.
> svn co http://svn.apache.org/repos/asf/mahout/trunk
> cd trunk
> mvn install
> cd ../
> ln -s mahout-0.7-SNAPSHOT mahout
- 샘플 테스트
u.data movielens에서 다운로드 받음
> more u.data 
196,242,3,881250949
186,302,3,891717742
22,377,1,878887116
244,51,2,880606923
166,346,1,886397596
298,474,4,884182806
115,265,2,881171488
253,465,5,891628467
305,451,3,886324817
> hadoop fs -put u.data /mahout
> hadoop fs -ls /mahout
Found 1 items
-rw-r--r--   1 k2 sg  1979172 2012-03-23 16:17 /mahout/u.data
> hadoop jar /database/server/mahout/mahout-core-0.7-SNAPSHOT-job.jar \
 org.apache.mahout.cf.taste.hadoop.item.RecommenderJob \
 --input /mahout/u.data --output /mahout_movie_recommendation \
 --similarityClassname SIMILARITY_PEARSON_CORRELATION
>
> hadoop fs -ls /mahout_movie_recommendation
Found 3 items
-rw-r--r-- 1 k2 sg     0 2012-03-23 /mahout_movie_recommendation/_SUCCESS
drwxr-xr-x - k2 sg     0 2012-03-23 /mahout_movie_recommendation/_logs
-rw-r--r-- 1 k2 sg 91250 2012-03-23 /mahout_movie_recommendation/part-r-00000
> hadoop fs -cat /mahout_movie_recommendation/part-r-00000 |more
1  [1652:5.0,1646:5.0,1644:5.0,1642:5.0,1629:5.0,1628:5.0,1622:5.0,1612:5.0]
2  [1038:5.0,1426:5.0,1026:5.0,1020:5.0,1016:5.0,1012:5.0,1011:5.0,1010:5.0]
3  [617:5.0,632:5.0,841:5.0,345:5.0,303:5.0,959:5.0,875:5.0,940:5.0]
4  [1038:5.0,1488:5.0,2:5.0,350:5.0,1027:5.0,1026:5.0,1024:5.0,1022:5.0]
5  [1629:5.0,1612:5.0,1592:5.0,1590:5.0,1589:5.0,1588:5.0,1585:5.0,1578:5.0]
6  [1646:5.0,1644:5.0,1642:5.0,1629:5.0,1628:5.0,1615:5.0,1612:5.0,1592:5.0]
7  [1646:5.0,1644:5.0,1642:5.0,1629:5.0,1628:5.0,1620:5.0,1615:5.0,1612:5.0]
8  [1589:5.0,1560:5.0,1027:5.0,13:5.0,1019:5.0,23:5.0,26:5.0,534:5.0]
9  [774:5.0,1111:5.0,1200:5.0,550:5.0,546:5.0,12:5.0,1101:5.0,1097:5.0]
10 [1629:5.0,1612:5.0,1592:5.0,1590:5.0,1589:5.0,1588:5.0,1585:5.0,1578:5.0]
11 [1662:5.0,1592:5.0,1590:5.0,1589:5.0,1588:5.0,1585:5.0,1578:5.0,1573:5.0]
#결과는 User Id, <[Movie Id:Score], …> 형식으로 떨어지면 성공.

4. Netflix처럼 Mahout를 활용한 영화 추천 샘플 테스트
- 샘플의 내용은 영화 별로 비슷한 영화를 10개 추천해주는 화면에 보여주는 기능으로 Spring + Jpa + Mahout + Wicket으로 구성되어 있음.
- 테스트 샘플 다운로드 : Mahout - Taste :: Part Two - Getting started
- 테스트 데이터 다운로드 : http://www.grouplens.org/node/73
- u.item(영화 상세 정보)를 src/main/resources/grouplens/100K/data/ 카피 . 파일 내용 :
movie id | movie title | release date | video release date |
IMDb URL | unknown | Action | Adventure | Animation |
Children's | Comedy | Crime | Documentary | Drama | Fantasy |
Film-Noir | Horror | Musical | Mystery | Romance | Sci-Fi |
Thriller | War | Western |

- u.data를 src/main/resources/grouplens/100K/ratings/ 카피 . 맨 끝라인 공백 제거.
. 파일 내용 : user id | item id | rating | timestamp.

- MySQL 데이터베이스, 테이블 생성 및 데이터 로드.
create database movielens
GRANT ALL ON movielens.* TO movielens@localhost IDENTIFIED BY 'movielens';
flush privileges

CREATE TABLE `movie` (
  `id` bigint(20) NOT NULL,
  `title` varchar(255) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

LOAD DATA LOCAL INFILE '../grouplens/100K/data/u.item'
INTO TABLE movie
FIELDS TERMINATED BY '|'
LINES TERMINATED BY '\n'
(id, title);

아래는 추천 소스들에 대한 설명이다.
- MovieServiceImpl.java
@SuppressWarnings("unchecked")
public List moreLikeThis(long movieId) {
    try {
        // 해당 영화 ID와 비슷한 영화 10개 뽑아 달라.
        List recommendedItems = 
        		movieRecommender.mostSimilarItems(movieId, 10);

        List ids = new ArrayList();
        for (RecommendedItem r : recommendedItems) {
            ids.add(r.getItemID());
        }
        //10개의 영화 ID기준으로 DB에 영화 상세 정보 조회
        return movieRepository.getMoviesById(ids);

    } catch (TasteException e) {
        return (List) Collections.EMPTY_LIST;
    }
}

- ResourceDataModel.java
public ResourceDataModel(Resource resource) {
    try {
        // 원시 데이터 입력(로드)
        this.delegate = new FileDataModel(resource.getFile());
    } catch (Exception e) {
        throw new RuntimeException("Could not read resource " + 
          resource.getDescription(), e);
    }
}
.........
- MoviePage.java(웹 뷰잉)
@SuppressWarnings("serial")
public MoviePage(PageParameters pageParameters) {
    final long movieId = pageParameters.getLong(MOVIE_ID, 1);

    MovieModel model = new MovieModel(movieId);
    add(new Label("title", model.getObject().getTitle()));

    PropertyListView recommendedMovies = 
     new PropertyListView("moreLikeThis", 
      new RecommendedMoviesModel(movieId)) {
        @Override// 추천된 영화 상세 정보 뷰잉
        protected void populateItem(ListItem listItem) {
            Movie movie = (Movie) listItem.getModelObject();
            PageParameters pageParameters = new PageParameters();
            pageParameters.put(MOVIE_ID, movie.getId());

            BookmarkablePageLink movieLink = 
            new BookmarkablePageLink("link", 
              MoviePage.class, pageParameters);
            listItem.add(movieLink);
            Label movieTitle = new Label("title");
            movieTitle.setRenderBodyOnly(true);
            movieLink.add(movieTitle);
        }
    };
    add(recommendedMovies);
}

- recommender-context.xml(Spring 설정)
// Recommender 지정
<bean id="euclidianDistanceRecommender" class="org.apache.mahout.cf.taste
  .impl.recommender.GenericItemBasedRecommender">
    <constructor-arg index="0" ref="movielensDataModel10M"/>
    <constructor-arg index="1" ref="euclidianDistanceSimilarity"/>
</bean>
//DataModel 지정
<bean id="movielensDataModel10M" class="nl.jteam.mahout
  .gettingstarted.datamodel.ResourceDataModel">
    <constructor-arg value="classpath:/grouplens/100K/ratings/u.data"/>
</bean>
//Similarity(유사도) 지정
<bean id="euclidianDistanceSimilarity" class="org.apache.mahout.cf
  .taste.impl.similarity.EuclideanDistanceSimilarity">
    <constructor-arg ref="movielensDataModel10M"/>
    <constructor-arg value="WEIGHTED"/>
</bean>

5. Mahout 영화 추천 샘플 결과 화면
Movie Id 1번(Toy Story (1995))에 대한 추천 결과는 아래와 같다.

[참조 사이트]
Tags : ,



Add a comment Send a TrackBack