Analysis of MovieLens dataset(begginers')
여러 추천시스템 관련 연구를 살펴보면, dataset으로 GroupLens에서 배포하는
MovieLens 데이터셋을 이용하는 경우가 대부분이다.
본 게시글에서는 추천시스템 연구에 앞서 MovieLens 데이터셋 중 가장 작은 데이터셋인
'ml-latest-small'에 대한 기초적인 수준의 EDA를 진행하고자 한다(데이터셋 다운로드 경로).
나중에 포트폴리오를 블로그에 천천히 작성할 예정이지만, 필자는 분석 경험이 매우 짧은 편이며 속해있는 연구실 또한 추천시스템을 전문적으로 다루는 연구실이 아니라 데이터마이닝 연구실이다.
혹시라도 전문적인 수준의 글을 접하고 싶어 찾아오셨다면 뒤로가기 해주셔도 좋고,
이녀석 어떤 실수를 했나 구경이나 해볼까 싶으셔서 읽게 되셨다면,
여러 지적해주시면 좋겠다.
Data EDA
분석 환경은 구글 Colab이다.
# 데이터 경로 설정 path = '/content/drive/MyDrive/ml-latest-small/' # ml-latest-small의 구성 os.listdir(path) ['ratings.csv', 'tags.csv', 'movies.csv', 'links.csv', 'README.txt']
ml-latest-small dataset은 총 4개의 csv 파일로 구성되어있다.
각 파일에 대한 shape와 head를 찍어보면 아래와 같다.
각 데이터에 대한 설명은 데이터셋의 zip파일에서 readme를 반드시 읽어보길 권한다.
print(ratings_df.shape) print(ratings_df.head()) (100836, 4) userId movieId rating timestamp 0 1 1 4.0 964982703 1 1 3 4.0 964981247 2 1 6 4.0 964982224 3 1 47 5.0 964983815 4 1 50 5.0 964982931 print(tags_df.shape) print(tags_df.head()) (3683, 4) userId movieId tag timestamp 0 2 60756 funny 1445714994 1 2 60756 Highly quotable 1445714996 2 2 60756 will ferrell 1445714992 3 2 89774 Boxing story 1445715207 4 2 89774 MMA 1445715200 print(movies_df.shape) print(movies_df.head()) (9742, 2) title genres movieId 1 Toy Story (1995) Adventure|Animation|Children|Comedy|Fantasy 2 Jumanji (1995) Adventure|Children|Fantasy 3 Grumpier Old Men (1995) Comedy|Romance 4 Waiting to Exhale (1995) Comedy|Drama|Romance 5 Father of the Bride Part II (1995) Comedy print(links_df.shape) print(links_df.head()) (9742, 3) movieId imdbId tmdbId 0 1 114709 862.0 1 2 113497 8844.0 2 3 113228 15602.0 3 4 114885 31357.0 4 5 113041 11862.0
구체적인 EDA에 앞서 데이터셋의 구성 중 PK(Primary Key)가 될법한 변수명들이 눈에 띄어 다른이가 그려둔 ERD가 없을까 찾아보게 되었다.
사실, ERD를 그려보는 것이 데이터셋 각각에 대한 EDA를 진행하는 것에 도움이 될까 싶긴
하지만 내 기초지식의 일부가 산업시스템공학에 존재하므로 그냥 또 '츄라이' 해본다.
그 중 Github에 vivek-bombatkar란 유저가 ERD를 작성한 것을 보았다. (링크)
genom_tags와 genome_scores를 제외하고 바라보면, 현재 우리가 아무 모델링도 가하지
않은 상태의 데이터셋과 일치하는 ERD가 된다. EDA에 앞서 ERD를 수행하는 모습은 일전에 dacon 대회에 참여했을 때 어떤 유저가 사용하는 것을 보고 지금 여기서도 해보게 되었는데, 확실히 데이터셋에 대해서는 직관성을 더 해주는 것 같다. 앞으로도 애용해야 할 듯 하다.
ratings_df의 info를 살펴보면 아래와 같다. 결측값의 존재 여부도 확인한다.
ratings_df.info() <class 'pandas.core.frame.DataFrame'> RangeIndex: 100836 entries, 0 to 100835 Data columns (total 4 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 userId 100836 non-null int64 1 movieId 100836 non-null int64 2 rating 100836 non-null float64 3 timestamp 100836 non-null int64 dtypes: float64(1), int64(3) memory usage: 3.1 MB # 결측값의 수 확인 ratings_df.isnull().sum() userId 0 movieId 0 rating 0 timestamp 0 dtype: int64
다음으로 user의 movie에 대한 평가횟수 / rating의 평균 / rating의 편차를 확인한다.
movieid_user_df = pd.DataFrame({ 'no_user_wat': ratings_df.groupby('movieId')['userId'].count(), 'ratings_mean': ratings_df.groupby('movieId')['rating'].mean(), 'ratings_std': ratings_df.groupby('movieId')['rating'].std() }) movieid_user_df = movieid_user_df.reset_index() print(movieid_user_df.shape) print(movieid_user_df.head(10)) (9724, 4) movieId no_user_wat ratings_mean ratings_std 0 1 215 3.920930 0.834859 1 2 110 3.431818 0.881713 2 3 52 3.259615 1.054823 3 4 7 2.357143 0.852168 4 5 49 3.071429 0.907148 5 6 102 3.946078 0.817224 6 7 54 3.185185 0.977561 7 8 8 2.875000 1.125992 8 9 16 3.125000 0.974679 9 10 132 3.496212 0.859381
rating이 부여된 횟수(no_user_wat)를 x축으로 하여 분포를 확인하면 아래와 같다.
추천시스템 관련 연구에서는 sparse dataset의 형태를 거르고 넘어갈 수 없다.
(내용 추가 예정)
-------------------------------------
우선 여기까지 하고 게시글을 잠시 멈춘다.
분석 목표에 따라 EDA는 다르게 진행되어야 한다.
장르별 분석이 목표라면 링크의 kaggle 자료를 참고해도 좋을 듯 하다(링크).
댓글 없음:
댓글 쓰기