← AI 놀이터 홈으로

🍿 협업 필터링 — 유튜브가 내 취향을 아는 법 (Collaborative Filtering)

'나와 비슷하게 별점을 매긴 사람이 좋아한 영화'를 빌려오는 추천의 원리 — 유튜브·넷플릭스 추천의 뼈대예요. 별점을 남기고 추천을 받아 보세요.

📖 따라하기 가이드 — 1 / 7 단계

Step 1. 유튜브는 어떻게 내 취향을 알까?

유튜브·넷플릭스는 영화의 내용을 “보고” 추천하는 게 아니에요. 나와 비슷하게 별점을 매긴 사람들이 좋아한 걸 빌려오죠 — 이걸 협업 필터링(Collaborative Filtering)이라고 해요. 표를 읽어 볼까요? 행 = 영화, 열 = 친구, 별점은 ★ 개수(1~5), 연한 ▢는 아직 안 본 영화예요. 맨 오른쪽 파란 ‘나’ 열의 칸을 클릭하면 ▢→★→★★→…→★★★★★→▢로 돌아가며 내 별점을 줄 수 있어요.

⭐ 별점 표 — 영화 8편 × 친구 6명 + 나

🖱️ 맨 오른쪽 파란 나 열의 칸을 클릭하면 ▢ → ★ → ★★ → … → ★★★★★ → ▢ 순서로 내 별점이 바뀌어요. 친구들 별점은 고정이에요.

영화
민준
SF파
서연
SF파
지호
SF파
하은
로맨스파
도윤
로맨스파
유나
로맨스파
나 👤
클릭!
🚀 우주 해적단★★★★★★★★★★★★★★★★▢★
🤖 로봇 전쟁★★★★★★★★★★★★★★★★▢
🪐 화성 탈출★★★★★▢★★★★★★★▢
⏳ 시간 여행자★★★★★★★★★★★★★▢★★★★★
🥐 봄날의 빵집★★★★★★★★★★★★★★★★★★
📚 첫사랑 도서관▢★★▢★★★★★★★★★★★★★
🐱 고양이와 나★★★★★★★★★★★★★★★★★★★★★
🌊 바닷가 편지★★★★★★★★▢★★★★★

읽는 법: 행 = 영화(위 4편은 SF, 아래 4편은 로맨스), 열 = 친구들의 별점(★ 1~5개), 연한 ▢ = 아직 안 봄. 친구들의 별점만 보고 취향 그룹이 나뉘는 게 보이나요? 추천 시스템이 가진 정보는 이 표가 전부예요.

🎛️ 추천 조종석

표의 나 열에 별점을 남긴 뒤 추천을 받아 보세요. 별점을 바꾸면 이전 결과는 사라져요.

📊 지금 상태

내가 준 별점 수
0개
가장 비슷한 친구
—
추천 영화
—
추천 실행 횟수
0회

내 별점이 바뀔 때마다 유사도와 추천이 함께 달라져요. SF와 로맨스에 번갈아 별점을 주며 추천이 뒤집히는 순간을 찾아 보세요.

🧪 이렇게 실험해 보세요

  1. 별점 0개로 추천 받기 — 콜드 스타트를 직접 확인
  2. SF에만 ★5 → 로맨스에만 ★5 — 추천이 통째로 뒤집혀요
  3. 8편 전부 ★5를 주면? — 유사도가 다들 비슷해지고 추천할 영화도 없어요
  4. 딱 1편만 평가하면? — 겹치는 영화가 부족해 유사도 계산이 거부돼요

🧮 수식과 파이썬

유사도(나, 친구) = (나·친구) / (‖나‖‖친구‖)
'나와 비슷하게 매긴 사람들'의 점수를 빌려와요. 영화 내용은 하나도 안 봐요!
예측 별점 = Σ 유사도×별점 ÷ Σ 유사도
비슷한 친구의 별점일수록 큰 가중치로 평균해요 (겹침 2편 미만은 유사도 0).
🐍 파이썬 코드로 보면? (펼치기)
import numpy as np

# 영화 8편: 앞 4편은 SF/액션, 뒤 4편은 로맨스/일상 (R의 열 순서와 같아요)
MOVIES = ["우주 해적단", "로봇 전쟁", "화성 탈출", "시간 여행자",
          "봄날의 빵집", "첫사랑 도서관", "고양이와 나", "바닷가 편지"]

# 별점 행렬: 행=친구, 열=영화 8편 (0 = 안 봄)
R = np.array([
    [5, 4, 5, 4, 2, 0, 3, 1],   # 민준 (SF파)
    [4, 5, 0, 4, 1, 2, 2, 2],   # 서연 (SF파)
    [5, 4, 4, 5, 1, 0, 2, 1],   # 지호 (SF파)
    [2, 1, 2, 0, 5, 4, 5, 4],   # 하은 (로맨스파)
    [0, 2, 1, 2, 4, 5, 5, 0],   # 도윤 (로맨스파)
    [1, 0, 0, 3, 5, 4, 4, 5],   # 유나 (로맨스파)
])
me = np.array([5, 5, 0, 0, 0, 0, 0, 0])   # 내 별점

def cos_sim(a, b):
    both = (a > 0) & (b > 0)               # 둘 다 본 영화만 비교
    if both.sum() < 2: return 0.0          # 2편 미만 겹치면 못 믿어요
    x, y = a[both], b[both]
    return x @ y / (np.linalg.norm(x) * np.linalg.norm(y))

sims = np.array([cos_sim(me, r) for r in R])   # 나 vs 친구들 유사도
for m in np.where(me == 0)[0]:                 # 내가 안 본 영화마다
    seen = R[:, m] > 0                         # 그 영화를 본 친구들의
    w = sims[seen]                             # 유사도를 가중치로 삼아
    if w.sum() > 0:                            # 가중 평균 = 예측 별점
        print(MOVIES[m], (w @ R[seen, m]) / w.sum())