사용 데이터: 카카오페이지 웹툰
줄거리나 제목을 입력하면 유사도 기반으로 비슷한 웹툰을 추천하는 추천 시스템 구현
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
data= pd.read_csv('kakao_webtoon_data.csv')
data.head()
데이터 수집은 셀레니움을 이용하였습니다. 이 부분은 나중에 정리하겠습니다.
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1559 entries, 0 to 1558
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Title 1559 non-null object
1 Summary 1559 non-null object
2 Category_Tag 1380 non-null object
dtypes: object(3)
memory usage: 36.7+ KB
셀레니움을 활용한 데이터 수집 과정에서 아쉬웠던 부분이 존재했습니다.
- 수집 중, 데이터가 존재하지 않을 경우 건너뛰기
- 이 경우, 공백이나 NaN값으로 대체하면 수집된 데이터가 풍부하지 않았을까 생각합니다.
- 타 데이터 병합
- AI-Hub의 데이터(다양한 문화 콘텐츠 스토리 데이터)를 추가로 가져와 병합했습니다.
- 다른 웹툰 사이트의 데이터를 추가로 수집하는 방향이 목표에 적절했을 것 같다는 생각이 듭니다.
# 유사도를 이용한 추천 시스템 구현
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
# TF-IDF 모듈 : 벡터화
vectorizer= TfidfVectorizer()
tfidf_matrix= vectorizer.fit_transform(data['Summary'])
# 코사인 유사도 계산
cosine_sim= cosine_similarity(tfidf_matrix, tfidf_matrix)
# 유사도 행렬 출력
pd.DataFrame(cosine_sim, index=data['Title'], columns=data['Title'])
상위 30개를 가져와 그래프로 정리하면 다음과 같다
selected_doc_index = 0
selected_doc_title = data.loc[selected_doc_index, "Title"]
similarities = cosine_sim[selected_doc_index]
N = 30
# 자기 자신 제외
similar_doc_indices = np.argsort(similarities)[::-1][1:N+1]
similar_docs = [(data.loc[idx, "Title"], similarities[idx]) for idx in similar_doc_indices]
colors = sns.color_palette("crest", len(similar_docs))
plt.figure(figsize=(8, 5))
plt.barh([title for title, _ in similar_docs], [score for _, score in similar_docs], color=colors)
plt.xlabel("Cosine Similarity Score")
plt.ylabel("Title")
plt.title(f"{selected_doc_title} 과 유사한 웹툰")
plt.gca().invert_yaxis()
plt.show()