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')
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')
오늘은 여기까지..
'ML-DL > RS' 카테고리의 다른 글
[개인 프로젝트] S-Walk 논문 모델로 추천 모델 구현해보기 -2 [모델 구현] (1) | 2024.11.04 |
---|---|
GNN [Graph Neural Network] - 1 (5) | 2024.09.13 |