협업 필터링(Collaborative Filtering)은 "비슷한 취향을 가진 사용자들은 비슷한 아이템을 좋아한다"는 가정에 기반한 추천 기법이다. 아이템의 내용 분석 없이 사용자-아이템 상호작용 데이터만으로 추천한다.
User-Based vs Item-Based CF
| 항목 | User-Based | Item-Based |
|---|
| 유사도 기준 | 사용자 간 유사도 | 아이템 간 유사도 |
| 확장성 | 사용자 증가 시 느림 | 아이템 변화 적을 때 유리 |
| 안정성 | 사용자 취향 변화 | 아이템 유사도 안정적 |
| 적합한 상황 | 소규모 사용자 | 대규모 사용자 |
메모리 기반 CF
python
import pandas as pd
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
# MovieLens 스타일 데이터 로드
ratings_df = pd.DataFrame({
'userId': [1,1,1,2,2,3,3,3],
'movieId': [1,2,3,1,3,2,3,4],
'rating': [5,4,3,4,5,3,4,5],
})
# 사용자-아이템 행렬 생성
user_movie_matrix = ratings_df.pivot_table(
index='userId', columns='movieId', values='rating'
).fillna(0)
# 코사인 유사도 계산
user_similarity = cosine_similarity(user_movie_matrix)
user_sim_df = pd.DataFrame(
user_similarity,
index=user_movie_matrix.index,
columns=user_movie_matrix.index,
)
def user_based_recommend(user_id: int, n_recs: int = 3):
# 유사 사용자 찾기
similar_users = user_sim_df[user_id].sort_values(ascending=False)[1:4]
# 유사 사용자의 평점 가중 평균
weighted_ratings = np.zeros(user_movie_matrix.shape[1])
for similar_user, similarity in similar_users.items():
weighted_ratings += similarity * user_movie_matrix.loc[similar_user].values
# 현재 사용자가 평가하지 않은 아이템만 추천
rated_items = user_movie_matrix.loc[user_id] > 0
weighted_ratings[rated_items.values] = -1
top_items = np.argsort(weighted_ratings)[::-1][:n_recs]
return user_movie_matrix.columns[top_items].tolist()
ALS (Implicit Feedback)
python
from implicit import als
import scipy.sparse as sparse
# 구매 횟수 같은 암묵적 피드백
user_item_matrix = sparse.csr_matrix(interactions_matrix)
model = als.AlternatingLeastSquares(
factors=64,
regularization=0.05,
iterations=20,
use_gpu=True,
)
model.fit(user_item_matrix)
# 추천 생성
user_id = 42
item_ids, scores = model.recommend(
user_id,
user_item_matrix[user_id],
N=10,
filter_already_liked_items=True,
)