Thursday, May 12, 2016

딥러닝 세미나@키스텝, 2015-05-09


딥러닝 개요 (2015-05-09 KISTEP) from Keunwoo Choi


2015-05-09 키스텝에서 진행한 딥러닝 개요입니다. 

짧은 분량이지만 세미나는 매우 인터랙티브하게 진행되어 두시간을 꽉 채웠던 슬라이드입니다. 
다시 말해 슬라이드만 보시면 부족한 부분이 많이 있으니 참고하시기 바랍니다. 
8페이지에 6개의 텐서플로 플레이그라운드 데모를 연결해두었습니다. 링크 눌러보시고 직접 돌려보시면 뉴럴넷에 대해 쉽게 이해하실 수 있을겁니다.

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의 경우엔 아예 평점을 매긴 날짜 자체가 다르고 등등, 난이도 차이가 있다고 합니다.