인턴을 하는 중에 요즘에 중요한 머신러닝의 한 분야가 되고 있는 개인화 추천에 대한 개발을 맡게 되었다. 요즘 넷플릭스, 왓챠와 같은 OTT 서비스는 물론이고, SNS에 표기되는 광고, 당근마켓 등등과 같은 중고거래 및 쇼핑 어플리케이션에서도 중요한 것이 사용자의 취향을 분석하여서 알맞은 아이템을 추천하는 기술이 핵심이다. 어쩌면 사용자가 의식적으로 파악하고 있는 이상의 취향을 파악해서 추천해야 할 때도 있다. 이전 포스트에서 다루었듯이 개인화 추천에는 여러 통계기반 머신러닝 기법들이 있다. 그리고 인공 신경망이라는 딥러닝 기법이 등장하게 되면서 더욱 세밀하고 정확한 개인화 추천이 가능해졌다.

처음 접했기 때문에 매우 생소하고 낯선 분야였지만 많은 자료들을 찾아보면서 현재 내 삶(유튜브나 넷플릭스의 노예…)과 아주 밀접하게 연관이 되어 있는 많은 어플리케이션과 서비스등에 실제로 사용되고 있는 인공지능 기법이라는 것이 금방 흥미를 불러 일으켰다. 조금 어렵긴 하지만 facebook에서 공개한 DLRM(Deep Learning Recommendation Model) 자료나 구글에서 공개한 유튜브 개인화 추천 논문, 국내의 당근마켓에서 쓴 개인화 추천 관련 블로그 포스트 등을 참고하면서 개인화 추천에 대한 대략적인 아이디어나 개념을 잡았다. 물론 매우 매우 어렵기 때문에 모든 것을 이해하는 것은 (나는) 힘들다. 가볍지만 꼼꼼하게 읽으면서 대략적인 맥락을 파악하는 것을 추천한다!

이후에 구현되어 있었던 pytorch를 활용한 딥러닝 모델 예시를 보게 되었고 참고하여 응용하면서 아주 간단한 딥러닝 영화 개인화 추천 모델을 구현하였다. 이번 포스트는 해당 개발의 초반, 데이터 전처리에 관한 내용을 다룰 예정이다. 전체 코드를 보고 싶다면 다음 github repo를 참고하시길.

데이터 모양새

딥러닝 개인화 추천 모델 구현을 시작하면서 가장 먼저 한 일은 입력 데이터의 형식에 대해서 파악한 것이다. 본 모델을 사용자와 영화 아이템, 그리고 해당 영화에 대한 각 사용자의 ratings 데이터를 담고 있는 MovieLens 데이터를 사용하였다. 해당 사이트에 가서 원하는 파일을 다운받아서 열면 다음과 같은 형식으로 데이터가 담겨져 있다.

image

해당 csv. 파일을 읽어서 validation 과 test 데이터를 나누어야 한다. 다음 명령어를 써서 읽은 csv 파일 data frame에 대한 마스크를 씌울 수 있다.

msk = np.random.rand(len(data)) < 0.8

나는 구현할 때 80% 정도의 데이터를 학습 데이터로, 나머지 20%의 데이터를 검증 데이터로 사용했다.

데이터 전처리

데이터 전처리에서 해야할 일들은 매우 간단하다. 기본적으로 학습 데이터와 검증 데이터는 모두 비슷한 과정의 데이터 전처리 과정을 거치지만 개인화 추천을 위한 영화 데이터에 대해서 구현할 때는 검증 데이터 전처리에 관해 조금 다른 부분이 필요하기도 하다.

학습에서 사용되는 데이터는 ratings.csv 파일에서도 특히 userIdmovieId 부분이다. 따라서 해당 column를 하나씩 끌어다가 전처리를 해주어야 한다. 여기서 필요한 전처리 과정은 다음과 같다.

  1. 중복을 제거하여 순수한 유저와 아이템 리스트 갯수 및 리스트 생성
  2. 학습 데이터가 아닌 검증 또는 테스트 데이터일 경우, 학습 데이터에 존재하지 않는 유저와 아이템에 대하여 -1 처리하여 제외

1번 과정이 필요한 이유는 이후에 신경망 layers를 쌓고 임베딩 할 때에 pytorch의 모듈을 사용하여서 임베딩 테이블을 생성해야하기 때문이다. 2번 과정이 필요한 이유는 검증 또는 테스트 데이터에 학습 데이터로 학습되지 않은 전혀 새로운 유저나 영화가 나왔을 경우, 제대로 예측할 수 없기 때문에 미리 제거해 주는 것이다.

코드

위의 데이터 전처리를 하기 위해서 유용한 몇가지 파이썬 코드를 소개한다.

  1. 데이터 columns의 중복제거
uni = train_col.unique()

위 메소드는 입력으로 들어온 column에 대해서 중복을 제거한 리스트를 uni 변수에 저장해준다.

  1. 존재하지 않는 아이템에 대하여 -1 처리하기
np.array([name2idx.get(x, -1) for x in col])

여기서 name2idx는 중복이 없는 순수한 유저 또는 아이템 리스트와 해당 index이다. 위와 같은 코드를 실행하면 name2idx에서 해당 col에 있는 x 값이 있다면 해당 값을 가져오고, 그렇지 않다면 -1을 입력하도록 하는 간편한 파이썬 문법이다.

이후에 학습 데이터에 존재하지 않는 유저 또는 아이템이 음수로 들어와 있으니 해당 처리를 다음과 같이하면 제외하고 검증 및 테스트 할 수 있다.

df = df[df[col_name] >= 0]

결과 화면

위와 같은 데이터 전처리를 끝내면 다음과 같은 전처리된 데이터가 생성된다. 물론 임베딩하는 전처리가 추가로 필요하지만 다음 포스트에서 학습과 함께 다루도록 하겠다. 결과 화면의 데이터는 csv의 데이터와 크게 차이가 없이 지저분한 데이터들을 제외하고 처리해 놓은 데이터라고 생각하면 된다.

image

[참고 자료]: https://jyoondev.tistory.com/65