끄적끄적
2025.08.18 추천시스템 & LLM 1회차 (과제) 본문
🔥 과제
지금까지 콘텐츠 기반 필터링 프로세스에 대해 코드를 배웠습니다.
아래 스켈레톤 코드를 바탕으로 user_id를 입력 받았을 때 추천 웹툰을 반환하는 함수를 만들어봅시다.
조건
- TF-IDF로 'keyword' 컬럼 기준 웹툰을 벡터화한다.
- 사용자가 읽은 웹툰들의 평균 벡터를 계산해서 사용자 벡터를 만든다.
- 사용자 벡터와 전체 웹툰 벡터 간의 유사도를 계산한다.
- 아직 읽지 않은 웹툰 중에서 상위 5개를 추천한다.
1. TF-IDF로 keyword 컬럼 벡터화를 진행할 것이기에 필요한 라이브러리를 import하고, 사용할 데이터를 불러온다.
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
import pandas as pd
webtoon = pd.read_csv('/content/drive/MyDrive/Colab Notebooks/스파르타/llm세션/1강/cbf_webtoon_data.csv')
user_logs = pd.read_csv('/content/drive/MyDrive/Colab Notebooks/스파르타/llm세션/1강/cbf_user_logs.csv')
이때, webtoon과 user_logs는 아래와 같은 데이터이다.


2. 각 웹툰에 대한 TF-IDF 벡터를 생성하고, user_id 별로 데이터를 묶어준다.
tfidf = TfidfVectorizer()
tfidf_matrix = tfidf.fit_transform(webtoon['keyword'])
user_read_webtoons = user_logs.groupby('user_id')['webtoon_id'].apply(set).reset_index()
3. 입력된 사용자가 본 웹툰 목록을 정의한다.
이 때, 사용자 정보가 없거나, 사용자의 시청 기록이 없는 경우도 고려한다.
user_data = user_read_webtoons[user_read_webtoons['user_id'] == user_id]
if user_data.empty:
return print(f"{user_id}의 사용자 정보가 없습니다.")
user_read_webtoonids = list(user_data['webtoon_id'].iloc[0])
if not user_read_webtoonids:
return print(f"{user_id}의 시청 기록이 없습니다.")
4. 사용자가 본 웹툰들의 TF-IDF 평균을 구해 사용자 벡터를 구한다.
user_vector = tfidf_matrix[user_read_webtoonids].mean(axis=0)
user_vec = np.asarray(user_vector)
5. 사용자 벡터와 전체 웹툰과의 유사도를 계산한다.
cos_sim = cosine_similarity(user_vec,tfidf_matrix)
recommend_indicies = cos_sim.argsort()[0][::-1]
6. 사용자가 이미 본 웹툰을 제외한 상위 N개의 웹툰 목록을 반환한다.
recommend_indicies = [i for i in recommend_indicies if i not in user_read_webtoonids]
top_n_webtoons = recommend_indicies[:top_n]
print(f'{user_id}에게 추천하는 웹툰 Top {top_n}')
recommended_webtoons = webtoon.loc[top_n_webtoons][['webtoon_title', 'main_genre']]
최종코드
# HINT : 웹툰을 벡터화하는 연산은 추천 함수 안에 들어갈 필요가 없습니다. (모든 사용자가 공통으로 사용하는 값이기 때문에)
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
import pandas as pd
webtoon = pd.read_csv('/content/drive/MyDrive/Colab Notebooks/스파르타/llm세션/1강/cbf_webtoon_data.csv')
user_logs = pd.read_csv('/content/drive/MyDrive/Colab Notebooks/스파르타/llm세션/1강/cbf_user_logs.csv')
# 1. 웹툰 아이템에 대한 TF-IDF 벡터 생성 및 user_id 그룹화
tfidf = TfidfVectorizer()
tfidf_matrix = tfidf.fit_transform(webtoon['keyword'])
user_read_webtoons = user_logs.groupby('user_id')['webtoon_id'].apply(set).reset_index()
# 2. 추천 함수 정의
def cbf_recommend(user_id, top_n=5) :
# (1) 해당 유저가 본 웹툰 목록 정의
user_data = user_read_webtoons[user_read_webtoons['user_id'] == user_id]
if user_data.empty:
return print(f"{user_id}의 사용자 정보가 없습니다.")
user_read_webtoonids = list(user_data['webtoon_id'].iloc[0])
if not user_read_webtoonids:
return print(f"{user_id}의 시청 기록이 없습니다.")
# (2) 사용자가 본 웹툰들의 TF-IDF 벡터 평균을 통해 사용자 벡터 구하기
user_vector = tfidf_matrix[user_read_webtoonids].mean(axis=0)
user_vec = np.asarray(user_vector)
# (3) 전체 웹툰과의 유사도 계산
cos_sim = cosine_similarity(user_vec,tfidf_matrix)
recommend_indicies = cos_sim.argsort()[0][::-1]
# (4) 사용자가 이미 본 웹툰 제외하기
recommend_indicies = [i for i in recommend_indicies if i not in user_read_webtoonids]
# (5) 유사도 기준으로 top-N 웹툰 추천하기
top_n_webtoons = recommend_indicies[:top_n]
# (6) 결과 반환 (DataFrame, webtoon_title과 main_genre 포함)
print(f'{user_id}에게 추천하는 웹툰 Top {top_n}')
recommended_webtoons = webtoon.loc[top_n_webtoons][['webtoon_title', 'main_genre']]
return recommended_webtoons
cbf_recommend('user_1',5)'[스파르타]내일배움캠프 데이터 분석 트랙 > Session' 카테고리의 다른 글
| 2025.08.21 추천시스템 & LLM 3회차 (0) | 2025.08.21 |
|---|---|
| 2025.08.19 추천시스템 & LLM 2회차 (8) | 2025.08.19 |
| 2025.08.18 추천시스템 & LLM 1회차 (7) | 2025.08.18 |
| 2025.07.09 Pandas 실무 기초 세션 4 (5) | 2025.07.09 |
| 2025.07.09 머신러닝 세션 4 (3) | 2025.07.09 |