Thursday, March 24, 2016

딥러닝을 이용한 추천엔진 (넷플릭스 컨테스트) 코드 설명

재미있는 글이 올라왔습니다.
https://karthkk.wordpress.com/2016/03/22/deep-learning-solution-for-netflix-prize/
딥러닝으로 협업 필터링(collaborative filtering) 문제를 푸는 코드입니다.

넷플릭스

는 우리가 다 아는 그 넷플릭스입니다.

컨테스트

각 사용자가 영화에 매긴 평점을 학습 데이터로 줍니다. 그리고 사용자가 다른 영화엔 어떤 평점을 줄지를 예측하는 문제입니다. 이걸 이용해서 사용자가 좋아할법한 영화를 추천할 수 있겠죠. 
해당 컨테스트는 100만달러의 상금이 걸려있었고 몇차례 잘 진행되었으나 개인정보관련 문제로 소송이 들어와서 중단되었습니다. 이후에도 데이터를 이용해 논문을 쓰는건 막을수가 없어서 사람들이 계속 활용하고 있습니다.
아마 컨텐츠 추천으로는 제일 널리 쓰이는 데이터셋일겁니다.

요번에 나온 코드

는 아래와 같습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
movie_count = 17771
user_count = 2649430
model_left = Sequential()
model_left.add(Embedding(movie_count, 60, input_length=1))
model_right = Sequential()
model_right.add(Embedding(user_count, 20, input_length=1))
model = Sequential()
model.add(Merge([model_left, model_right], mode='concat'))
model.add(Flatten())
model.add(Dense(64))
model.add(Activation('sigmoid'))
model.add(Dense(64))
model.add(Activation('sigmoid'))
model.add(Dense(64))
model.add(Activation('sigmoid'))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adadelta')

별로 아름답게 코드가 안뜨지만 양해 바랍니다.

설명

  • [1] 데이터에 있는 전체 영화의 수입니다.
  • [2] 데이터에 있는 전체 사용자의 수 입니다.
  • [3-6] 영화의 인덱스를 60차원 벡터로, 사용자 인덱스를 20차원 벡터로 바꿔주는 embedding층을 추가합니다. keras문법을 참고하면, 입력은 [[1],[3],[9],[232423],[534]...], 즉 영화의 인덱스를 받고 그 인덱스 하나하나를 60차원의 벡터로 변환해줍니다. 사용자도 마찬가지구요. 
  • [7-8] 여기에서는 위에서 embedding층의 결과를 다시 입력으로 받습니다. 두 개의 embedding벡터를 이어줍니다.
  • [9-16] 그리고 3개의 dense layer, 혹은 fully connected layer, 혹은 일반적인 인공신경망의 층을, 혹은 3개의 MLP를..아무튼 뉴럴넷을 이어줍니다. 최종 출력은 노드가 1개인 스칼라 값이네요. 넷플릭스는 총 5단계 (1,2,3,4,5)로 평가합니다. 따라서 값의 범위가 1-5인데, 이걸 그대로 사용했군요. 
  • [17] MSE로 loss function을 정해주고 adadelta로 최적화합니다.
여기에서 일어나는 학습을 세 가지로 나눠볼 수 있겠네요.
  1. 영화 인덱스 → 60차원 벡터
  2. 사용자 인덱스 → 20차원 벡터
  3. 80차원의 벡터 [60차원 영화 임베딩 + 20차원 사용자 임베딩] → 스칼라 값 (평점)
이 세 가지 학습의 목표는 평점을 정확히 예측하는 것 이구요.
보통 추천 시스템에서 사용하는 Matrix factorisation과 풀이 과정이 달라서 좀 이해가 안갔는데, 아예 다른 접근법이라고 보면 될 것 같습니다. 

생각할 거리

  • 출력층의 [1,2,3,4,5]값을 [0.2, 0.4, 0.6, 0.8, 1.0]으로 바꿔주고 (혹은 [0.1, 0.3, 0.5, 0.7, 0.9]가 더 괜찮을지도..) 출력층에도 sigmoid를 적용한 뒤 crossentropy를 쓰거나,
  • [1,2,3,4,5]의 범주로 분류하는 분류 문제(classification problem)으로 설정하고 softmax를 쓰면 어떻게 될지 궁금하네요.
  • 그 외에 다양한 머신러닝 학습 기법이 어떻게 적용될 수 있을런지도 마찬가지로..
  • 이 방법이 정말 테스트셋에서도 잘 된다면 굉장한겁니다. 엔지니어링쪽은 잘 모르지만 일단 새 아이템 엔트리를 추가하기도 아주 간단하고 (학습데이터에 그냥 넣어서 계속 돌리면 되죠) 메모리도 많이 차지할 것 같지 않은데요? 저정도 크기의 파라미터는 GPU메모리에 충분히 들어갈테니...
  • 업데이트된 글에 의하면 실제 컨테스트에서 썼던 test set과, 글에 나온것처럼 트레이닝셋을 나눠서 하는것과는 성능 차이가 좀 난다고 하네요. test set의 경우엔 아예 평점을 매긴 날짜 자체가 다르고 등등, 난이도 차이가 있다고 합니다. 


Saturday, March 19, 2016

머신러닝/딥러닝 용어 번역의 문제

언어 순화, 우리말 사용, 이런 말들을 하죠.
전 '순화'엔 별 관심이 없습니다. 하지만,

저는 우리말을 지켜야 한다고 생각하는 사람이 아닙니다. 다만 처음 접하는 사람에게 더 쉬운 번역이 좋은 번역이라고 생각하고, 그래서 가급적 한국어로 된 용어를 써서 번역을 하려고 합니다. 저한테도 어색한 단어가 많지만요.

의 이유로 머신러닝 용어를 어떻게 번역해야 할지 정리한 깃헙 저장소를 하나 만들었습니다.어차피 다 아는 연구자들끼리는 편한대로 사용하더라도 초보자나 대중을 상대로 하는 글을 쓸때는 신경쓰는것이 좋다고 생각해요.

별 대단한 내용이 있는 것은 아니지만 아무튼 참고하시길 바랍니다.