
오늘날 넷플릭스, 아마존, 유튜브와 같은 플랫폼은 추천 시스템을 활용하여 사용자 경험을 극대화하고 있습니다.
이 글에서는 상관계수(Pearson Correlation Coefficient)를 활용한 협업 필터링 추천 시스템을 Python과 Jupyter Notebook을 이용해 직접 구현해보겠습니다.
📖 1️⃣ 추천 시스템이란?
추천 시스템(Recommendation System)은 사용자의 이전 행동 데이터 및 선호도를 분석하여 사용자가 관심을 가질 만한 콘텐츠(상품, 영화, 음악 등)를 추천하는 알고리즘입니다.
추천 시스템의 유형
콘텐츠 기반 필터링 | 사용자가 과거에 좋아했던 콘텐츠와 유사한 아이템을 추천 |
협업 필터링 | 사용자들 간의 유사성을 기반으로 추천 (오늘 다룰 핵심 내용) |
📌 2️⃣ 협업 필터링(Collaborative Filtering)이란?
협업 필터링은 사용자의 **행동 데이터(예: 영화 평점, 상품 클릭)**를 바탕으로 비슷한 사용자 또는 아이템을 찾아 새로운 추천을 생성하는 방식입니다.
💡 협업 필터링의 두 가지 접근법
- 사용자 기반(User-Based)
- 나와 유사한 취향을 가진 사용자를 찾고, 그들이 좋아하는 아이템을 추천
- 예: A와 B 사용자가 같은 영화를 좋아하면, B가 좋아한 다른 영화도 A에게 추천
- 아이템 기반(Item-Based)
- 특정 아이템과 비슷한 아이템을 찾아 추천
- 예: 스타워즈를 본 사용자들이 "인터스텔라"도 봤다면, 스타워즈를 본 다른 사용자에게 "인터스텔라" 추천
📖 3️⃣ 상관계수를 이용한 추천 시스템
**상관계수(Pearson Correlation Coefficient)**는 두 사용자 또는 아이템 간의 선호 패턴 유사도를 측정하는 대표적인 방법입니다.
📌 상관계수 공식

✔️ 1에 가까울수록 강한 양의 상관관계
✔️ -1에 가까울수록 강한 음의 상관관계
🛠️ 4️⃣ Python 실습: 영화 추천 시스템 만들기
🎯 목표: 특정 사용자가 좋아할 영화를 추천하는 시스템을 구현
🎬 사용 데이터: MovieLens 데이터셋 (사용자별 영화 평점)
📌 Step 1: 데이터 불러오기
import pandas as pd
df_movie = pd.read_csv('movie_title.csv')
df_movie.head()
df_rating = pd.read_csv('movie_review.csv')
df_rating
df = pd.merge(df_rating, df_movie, on = 'item_id')
df



- 데이터 요약 및 구조화: 대량의 데이터를 효과적으로 정리합니다.
- 효율적인 데이터 처리: 복잡한 데이터에서 필요한 정보를 쉽게 추출합니다.
- 다차원 데이터 분석: 여러 변수 간의 관계를 동시에 분석할 수 있습니다.
- 시각화 용이성: 상관관계를 시각적으로 표현하기 쉽습니다.
- 동적 데이터 분석: 데이터 업데이트 시 자동으로 갱신됩니다.
- 필터링 및 그룹화: 특정 조건에 따른 세부적인 분석이 가능합니다.
📌 Step 2: 사용자-영화 평점 매트릭스 만들기
# 사용자 ID를 인덱스로, 영화 제목을 컬럼으로 사용
movie_matrix = data.pivot_table(index='user_id', columns='title', values='rating')
# 일부 데이터만 확인
movie_matrix.head()

✅ 출력 결과:
"타이타닉(1997)"을 좋아하는 사용자는 아래 영화를 좋아할 가능성이 높음
River Wild, The (1994) 0.497600
Abyss, The (1989) 0.472103
Bram Stoker's Dracula (1992) 0.443560
📌 Step 3: 특정 사용자에게 영화 추천하기
# 영화 간 상관계수 계산 (최소 50개 이상의 공통 평점을 가진 경우만)
df_corr = movie_matrix.corr(min_periods=50)
# 특정 사용자 선택 (예: user_id = 4)
user_id = 4
my_rating = data.loc[data['user_id'] == user_id, ['user_id', 'title', 'rating']].reset_index(drop=True)
df_similar_movie = pd.DataFrame()
# 내가 본 영화 리스트를 기반으로 추천 생성
for i in range(my_rating.shape[0]):
movie_title = my_rating['title'][i]
recom_movie = df_corr[movie_title].dropna().sort_values(ascending=False).to_frame()
recom_movie.columns = ['correlation']
recom_movie['weight'] = recom_movie['correlation'] * my_rating['rating'][i]
df_similar_movie = pd.concat([df_similar_movie, recom_movie])
# 중복된 영화 제거 (가장 높은 weight 값 유지)
df_similar_movie = df_similar_movie.groupby('title')['weight'].max().sort_values(ascending=False)
# 내가 본 영화 제외
df_new = df_similar_movie.to_frame().reset_index()
df_new = df_new.loc[~df_new['title'].isin(my_rating['title']), ]
# 최종 추천 영화 출력
df_new.head(10)

📖 5️⃣ 협업 필터링의 한계점
❌ 콜드 스타트 문제: 신규 사용자/아이템의 데이터가 부족하면 추천이 어려움
❌ 데이터 희소성 문제: 평점이 적은 경우 유사도 계산이 어려울 수 있음
❌ 확장성 문제: 데이터가 많아질수록 연산량이 증가
➡️ 해결 방법:
🔹 K-최근접 이웃(KNN) 적용
🔹 Matrix Factorization (행렬 분해) 기법 활용
🔹 딥러닝 기반 추천 시스템 적용
'Streamlit > 실습' 카테고리의 다른 글
150.[AI] [LlamaIndex RAG] Mistral 모델로 PDF 텍스트 추출 (0) | 2025.02.10 |
---|---|
148. [Python] [Streamlit] : 주피터노트북에서 학습한 인공지능을 스트림릿에서 사용하는 방법 (0) | 2025.02.04 |