본문 바로가기

ML-DL/RS

[개인 프로젝트] S-Walk 논문 모델로 추천 모델 구현해보기 -1 [MovieLens 데이터셋 설명, 코랩 구글드라이브 연동하기, 데이터 전처리]

1. Data

https://grouplens.org/datasets/movielens/

 

MovieLens

GroupLens Research has collected and made available rating data sets from the MovieLens web site ( The data sets were collected over various periods of time, depending on the size of the set. …

grouplens.org

위의 MovieLens 데이터셋을 활용했다.

 

해당 데이터는 87,585개의 영화에 대해 32,000,204 개 평가와 2,000,072 개 태그가 포함되어 있으며, 모든 사용자가 최소 20개 이상을 평가했다. 

 

Colab 에서 진행했으므로 위의 데이터를 구글 드라이브에 저장한 뒤, 아래와 같은 코드로 Colab과 구글 드라이브를 연동시켜줬다.

# 구글 드라이브 연동
from google.colab import drive

drive.mount('/content/gdrive/')

 

 

1. movies, ratings, links, tags 데이터가 csv 형태로 저장되어 있는데, 어떤 데이터가 필요할지 몰라서 모두 불러왔다.

 

1. movies.csv : 영화 데이터, 장르는 미분류까지 포함하여 19개로 나뉘어져 있음

2. ratings.csv : 평가 데이터, 한 사용자가 한개의 영화에 대해 한 가지 평가를 진행함, 평가는 5점 만점

3. tags.csv : 태그 데이터, 태그는 영화에 대해 사용자가 생성한 메타데이터를 의미함

4. links.csv : 다른 영화 데이터 소스에 연결하기 위해 사용할 수 있는 식별자 데이터

    1) movieId : https://movielens.org 에서 사용하는 영화 식별자

    2) imdbId : http://www.imdb.com 에서 사용하는 영화 식별자

    3) tmdbId : https://www.themoviedb.org 에서 사용하는 영화 식별자

 

# 현재 폴더 경로 체크
import os

print(os.getcwd())


# 데이터 불러오기
import pandas as pd

movies_data = pd.read_csv('./gdrive/MyDrive/ml-32m/movies.csv')
ratings_data = pd.read_csv('./gdrive/MyDrive/ml-32m/ratings.csv')
links_data = pd.read_csv('./gdrive/MyDrive/ml-32m/links.csv')
tags_data = pd.read_csv('./gdrive/MyDrive/ml-32m/tags.csv')

 

movies.csv
ratings.csv
links.csv
tags.csv

 

2. 다른 데이터 셋과 연동은 하지 않을 생각이어서 links.csv 를 제외하고 나머지 데이터 셋들을 합쳐주었다.

# ratings 와 tags 데이터를 movieId 와 userId 기준으로 병합
pre_data = pd.merge(ratings_data, tags_data, how='inner', on=['userId', 'movieId'])


# pre_data(raings + tags) 와 movies 데이터를 movieId 기준으로 병합
data = pd.merge(pre_data, movies_data, how='left', on='movieId')

 

 

3. timestamp_x, timestamp_y 변수명을 각각 rating_timestamp, tag_timestamp 로 변경해주고, Nan 값의 유무를 확인해주었다.

# 변수명 변경
data = data.rename(columns={"timestamp_x": "rating_timestamp", "timestamp_y": "tag_timestamp"})


# null 확인
data.isnull().sum()

 

4. s-walk 모델에 들어갈 수 있는 입력 형태로 데이터를 변형해준다.

# 예시
sessions = [
    ['A', 'B', 'C'],  # 첫 번째 세션: 사용자가 A, B, C를 선택함
    ['A', 'C'],       # 두 번째 세션: 사용자가 A, C를 선택함
    ['B', 'D'],       # 세 번째 세션: 사용자가 B, D를 선택함
    ['C', 'D', 'E']   # 네 번째 세션: 사용자가 C, D, E를 선택함
]

 

  • 세션 (Session) : 각 세션은 특정 시간 동안 유저가 본 아이템의 리스트
    • 예시 : 한 유저가 영화 A, B, C 를 차례대로 클릭했다면, 이 세션은 ['A', 'B', 'C'] 로 표현된다.
  • 아이템 (Item) : 세션 내의 각 항목은 추천하고자 하는 영화를 나타낸다.

 

1) 보기 편하도록 먼저 timestamp 를 datetime으로 변환시킨다. 

# 보기 쉽게 timestamp -> datetime 변환
data['rating_date'] = pd.to_datetime(data['rating_timestamp'], unit='s').dt.date
data['tag_date'] = pd.to_datetime(data['tag_timestamp'], unit='s').dt.date

 

2) 위의 형태를 위해 유저 몇명의 datetime의 간격을 확인한다. [세션 정의를 위해]

data[data['userId'] == 34][['userId', 'rating_date']]

data[data['userId'] == 162279][['userId', 'rating_date']]

 

각 유저마다 데이터 개수도 차이가 많이 나고 세션 정의하기가 쉽지는 않지만 1일을 한 세션으로 지정할 예정이다.

예시

 

2) 위의 형태를 생각해보면 한 유저 당 하나의 리스트가 만들어 지는데, 그 리스트 안에 하루 동안 rating 을 진행한 영화들이 리스트로 나열되어 있어야 한다.

 

이 부분이 살짝 꼬였었는데 계속해서 결과를 확인하면서 했더니 결국 원하는대로 형태가 나왔다.

# 'userId'와 'rating_date'를 기준으로 그룹화하고 'movieId'를 리스트로 묶는 작업
result = data.groupby(['userId', 'rating_date'])['movieId'].apply(list).reset_index()

# 각 'userId'별로 리스트로 묶어줌
final_result = result.groupby('userId').apply(lambda x: x[['rating_date', 'movieId']].to_dict(orient='records')).reset_index(name='movie_list')

# movie_list 컬럼을 explode를 사용해 각 dict를 개별 row로 분리
exploded_result = final_result.explode('movie_list').reset_index(drop=True)

# movie_list 컬럼을 다시 분리하여 'rating_date'와 'movieId'로 나눔
exploded_result['rating_date'] = exploded_result['movie_list'].apply(lambda x: x['rating_date'])
exploded_result['movieId'] = exploded_result['movie_list'].apply(lambda x: x['movieId'])

# movie_list 컬럼 삭제
exploded_result = exploded_result.drop(columns=['movie_list'])

# 각 'userId'별로 'rating_date'에 따른 'movieId' 리스트를 하나의 열로 묶음
final_grouped_result = exploded_result.groupby('userId').apply(lambda x: x['movieId'].to_list()).reset_index(name='movie_list')

 

 

 

오늘은 여기까지..