사용 데이터: 카카오페이지 웹툰

줄거리나 제목을 입력하면 유사도 기반으로 비슷한 웹툰을 추천하는 추천 시스템 구현

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()

+ Recent posts