///
Search
Duplicate
🧶

3강 - 컨텐츠 기반 모델 - Word2Vec(CBOW)

3강 컨텐츠 기반 모델

Intoduction

컨텐츠 기반 모델은 상관관계를 통해 유사성을 발견하고 추천을 하는 방법에서 조금 벗어나 컨텐츠 사이의 유사도를 기반으로 추천을 해주는 모델입니다. 예를 들어 아이언맨 영화를 재밌게 본 사람에게 이와 비슷한 영화인 어벤져스나 마블시리즈 영화를 추천해 주는 방식이죠. 이러한 방식은 새로운 아이템이나 평가가 적은 아이템에 적용하기 좋습니다.

Word2Vec

word2vec모델은 기존에 자연어 처리를 위해 만들어진 모델입니다. 앞 뒤 단어를 통해 단어를 저차원의 벡터로 임베딩하는 방식이죠. 여기서 단어를 아이템으로 바꾸게 되면 인접한 아이템들을 통해 아이템을 벡터화할 수 있습니다. 구글play에서는 이와 같은 내용을 Item2vec이라는 모델로 소개하였습니다.

CBOW

Word2Vec모델 중 하나인 CBOW모델은 주변 단어들을 통해 중심 단어를 예측하는 모델입니다. 주변 단어들의 개수를 window size라고 부르고 window를 계속 옮겨 가며 학습을 진행합니다.
위의 그림에서 w(t)가 중심 단어이고 나머지 w(t-2) ~ w(t+2)까지가 주변 단어입니다. 각각의 주변단어에 대해서 같은 작업을 반복해 주고 평균을 내기 때문에 하나의 주변 단어를 기준으로 모델에 대해 알아보겠습니다.
위의 그림은 하나의 주변 단어에 대한 모델의 세부적인 구조입니다. 총 세개의 layer가 있고 2개의 가중치 벡터가 존재합니다. Input layer에는 one-hot 인코딩 방식으로 만들어진 단어 벡터가 들어옵니다. x는 v차원의 벡터이고 첫번째 가중치 벡터와의 연산을 통해 N차원의 벡터로 변환됩니다. N차원의 벡터는 다시 가중치와의 연산을 통해 v차원의 벡터로 변하게 됩니다.
WRV×N,WRN×VW \in R^{V \times N}, W' \in R^{N \times V}
P(xcxcm,...xc1,xc+m)P(x_c|x_{c-m},...x_{c-1}, x_{c+m})
위의 확률을 최대화 하는 것이 이 모델의 목적입니다.
(vcm=Wxcm,...vc+m=Wxc+m)Rn(v_{c-m} = Wx^{c-m},...v_{c+m} = Wx^{c+m}) \in R^n
hidden layer에 속하는 벡터들을 위와 같이 표현할 수 있습니다.
z=Wvz = W'v
output layer에 속하는 벡터들은 hidden layer벡터에 W’가중치를 곱한 형태입니다.
y^=softmax(z)\hat{y} = softmax(z)
softmax함수를 이용해 정규화를 해줍니다.
H(y^,y)=yilog(yi^)H(\hat{y},y) = -y_ilog(\hat{y_i})
마지막으로 크로스 엔트로피를 사용하여 loss값을 구합니다.
minimizeJ=logP(wcwcm,...,wc+m)=logP(ucv)=logexp(ucTv^)j=1vexp(ujTv^)minimizeJ = -logP(w_c|w_{c-m}, ...,w_{c+m}) \\ = -logP(u_c|v) \\ =-log{exp(u_c^T\hat{v})\over \sum_{j=1}^{|v|}exp(u_j^T\hat{v})}
크로스 엔트로피를 사용해서 구한 loss값과 역전파 방법을 통해 파라미터를 수정하며 오차를 줄여나갑니다. optimization 방법으로는 SGD를 사용합니다.

Word2vec 추천시스템 구현

#필요한 라이브러리 불러오기 import pandas as pd import numpy as np from sklearn.feature_extraction.text import TfidfVectorizer import gensim
Python
복사
#경로설정하기 path_meta = "./drive/MyDrive/machine_learning/movies_metadata.csv" path_ratings = "./drive/MyDrive/machine_learning/ratings.csv"
Python
복사
#판다스를 이용해 데이터 불러오기, 데이터 정렬 movie = pd.read_csv(path_ratings) movie = movie.sort_values(by='timestamp', ascending=True).reset_index(drop=True)
Python
복사
#데이터 전처리, column이름을 바꾸고 데이터 병합 meta = pd.read_csv(path_meta) meta = meta.rename(columns={'id':'movieId'}) movie['movieId'] = movie['movieId'].astype(str) meta['movieId'] = meta['movieId'].astype(str) movie = pd.merge(movie, meta[['movieId', 'original_title']], how='left', on='movieId'
Python
복사
movie = movie[movie['original_title'].notnull()].reset_index(drop=True)
Python
복사
#userId를 기준으로 묶어주기 agg = movie.groupby(['userId'])['original_title'].agg({'unique'}) agg.head()
Python
복사
#각각의 user가 본 영화끼리 묶어서 저장하기 sentence = [] for user_sentence in agg['unique'].values: sentence.append(list(map(str, user_sentence)))
Python
복사
#word2vec 모델 학습 from gensim.models import Word2Vec embedding_model = Word2Vec(sentence, size=20, window = 5, min_count=1, workers=4, iter=200, sg=1)
Python
복사
#결과확인 embedding_model.wv.most_similar(positive=['The Phantom of the Opera'], topn=10)
Python
복사