Develop/ML·DL

추천 시스템에 대해 알아보자.

YOOZI. 2025. 2. 4. 21:00
728x90
당신의 취향을 분석하는 AI

 

 

 

오늘은 추천 시스템에 대해 알아보자.

오늘의 배움
  • 추천 시스템의 기본 개념과 종류
  • 각 추천 시스템의 작동 원리
  • 실제 서비스에서의 적용 사례

1. 추천 시스템

  • 정의: 사용자의 선호도와 행동 패턴을 분석하여 관심을 가질만한 항목을 제안하는 시스템
  • 핵심 개념 한 줄 설명: 사용자 데이터를 기반으로 개인화된 추천을 제공하는 AI 시스템
  • 특징:
    • 개인화된 서비스 제공
    • 사용자 경험 향상
    • 서비스 참여도 증가
[핵심 공식]
- 코사인 유사도 = A·B / (||A|| ||B||)
- 피어슨 상관계수 = cov(X,Y) / (σx σy)
- 유클리드 거리 = √Σ(xi - yi)²

 

📚 실제 예시로 이해하기
  1. [일상적인 예시] 음악 추천 시스템:
    • 콘텐츠 기반: "방탄소년단을 좋아하니 비슷한 K-pop 그룹을 추천합니다"
    • 협업 필터링: "방탄소년단 팬들이 자주 듣는 다른 음악을 추천합니다"
  2. [실무/현업 예시] 넷플릭스 추천 시스템:
    • 시청 기록 분석
    • 장르 선호도 파악
    • 비슷한 사용자의 시청 패턴 분석

 


 

2. 핵심 개념 정리

[콘텐츠 기반 필터링]

  • 정의: 아이템의 특성을 분석하여 유사한 아이템을 추천
  • 작동 원리: 아이템의 속성을 벡터화하여 코사인 유사도 측정
  • 특징: 새로운 아이템도 추천 가능
  • 예시: 영화 장르, 출연진, 감독 정보 기반 추천
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np

class ContentBasedRecommender:
    def __init__(self):
        self.tfidf = TfidfVectorizer(stop_words='english')
        
    def fit(self, movies_data):
        # 영화 설명에서 특성 추출
        self.tfidf_matrix = self.tfidf.fit_transform(movies_data['description'])
        self.cosine_sim = cosine_similarity(self.tfidf_matrix, self.tfidf_matrix)
        self.movies = movies_data
        self.indices = pd.Series(movies_data.index, index=movies_data['title'])
        
    def get_recommendations(self, title, n=5):
        # 영화 제목으로부터 인덱스 가져오기
        idx = self.indices[title]
        
        # 모든 영화에 대해 유사도 점수 구하기
        sim_scores = list(enumerate(self.cosine_sim[idx]))
        
        # 유사도 기준으로 정렬
        sim_scores = sorted(sim_scores, key=lambda x: x[1], reverse=True)
        
        # 가장 유사한 n개의 영화 가져오기
        sim_scores = sim_scores[1:n+1]
        movie_indices = [i[0] for i in sim_scores]
        
        return self.movies['title'].iloc[movie_indices]

# 사용 예시
movies_df = pd.DataFrame({
    'title': ['어벤져스', '아이언맨', '스파이더맨', '인셉션', '매트릭스'],
    'description': [
        '슈퍼히어로들이 지구를 지키는 액션 영화',
        '천재 사업가가 아이언맨이 되어 세상을 구하는 이야기',
        '거미줄을 쏘는 고등학생 히어로의 성장 이야기',
        '꿈속에서 벌어지는 미션을 다루는 SF영화',
        '가상현실 속 인류의 운명을 다루는 SF영화'
    ]
})

recommender = ContentBasedRecommender()
recommender.fit(movies_df)
recommendations = recommender.get_recommendations('매트릭스')
print("매트릭스와 비슷한 영화들:", recommendations.tolist())

 

  • TF-IDF를 사용하여 콘텐츠 특성 추출
  • 코사인 유사도로 아이템 간 유사성 계산
  • 가장 유사한 아이템들을 추천

 

 

 

 

[협업 필터링]

  • 정의: 비슷한 취향을 가진 사용자들의 선호도/유사성을 기반으로 추천
  • 작동 원리: 사용자 기반과 아이템 기반으로 각각 추천
  • 특징: 예상하지 못한 추천이 가능
  • 예시: "이 상품을 구매한 사람들이 함께 구매한 상품"
import pandas as pd
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity

class CollaborativeFilter:
    def __init__(self):
        self.user_ratings = None
        self.similarity_matrix = None
        
    def fit(self, ratings_matrix):
        """
        ratings_matrix: 사용자-아이템 평점 행렬
        """
        self.user_ratings = ratings_matrix
        # 사용자 간 유사도 계산
        self.similarity_matrix = cosine_similarity(ratings_matrix)
        
    def predict_rating(self, user_id, item_id, k=5):
        """
        특정 사용자의 특정 아이템에 대한 평점 예측
        k: 고려할 이웃 수
        """
        # 현재 사용자와 다른 사용자들 간의 유사도
        user_similarities = self.similarity_matrix[user_id]
        
        # k개의 가장 유사한 이웃 선택
        similar_users = np.argsort(user_similarities)[::-1][1:k+1]
        
        # 이웃들의 해당 아이템 평점
        neighbor_ratings = self.user_ratings[similar_users, item_id]
        
        # 유사도 가중치 적용하여 평점 예측
        weighted_ratings = (neighbor_ratings * 
                          user_similarities[similar_users])
        predicted_rating = weighted_ratings.sum() / \
                          user_similarities[similar_users].sum()
        
        return predicted_rating

# 사용 예시
# 사용자-아이템 평점 행렬 생성
ratings = np.array([
    [5, 3, 0, 1],  # 사용자 1의 평점
    [4, 0, 0, 1],  # 사용자 2의 평점
    [1, 1, 0, 5],  # 사용자 3의 평점
    [1, 0, 0, 4],  # 사용자 4의 평점
    [0, 1, 5, 4],  # 사용자 5의 평점
])

cf = CollaborativeFilter()
cf.fit(ratings)

# 사용자 0의 아이템 2에 대한 예측 평점
predicted = cf.predict_rating(0, 2)
print(f"사용자 1의 아이템 3에 대한 예측 평점: {predicted:.2f}")

 

  • 사용자-아이템 평점 행렬 사용
  • 사용자 간 유사도 계산
  • K-최근접 이웃 방식으로 평점 예측

 

 

 

 

[하이브리드 추천]

  • 정의: 여러 추천 방식을 결합 (협업 필터링+콘텐츠 기반 필터링)
  • 작동 원리: 각 방식의 장점을 활용하여 보완
  • 특징: 정확도 향상, 콜드 스타트 문제 해결
  • 예시: 유튜브 추천 시스템
import pandas as pd
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.feature_extraction.text import TfidfVectorizer

class HybridRecommender:
    def __init__(self, content_weight=0.5):
        self.content_weight = content_weight
        self.collab_weight = 1 - content_weight
        self.tfidf = TfidfVectorizer(stop_words='english')
        
    def fit(self, ratings_matrix, item_features):
        """
        ratings_matrix: 사용자-아이템 평점 행렬
        item_features: 아이템의 특성 정보
        """
        # 콘텐츠 기반 필터링 준비
        self.tfidf_matrix = self.tfidf.fit_transform(item_features)
        self.content_sim = cosine_similarity(self.tfidf_matrix)
        
        # 협업 필터링 준비
        self.ratings = ratings_matrix
        self.user_sim = cosine_similarity(ratings_matrix)
        
    def get_recommendations(self, user_id, n=5):
        """
        사용자에게 n개의 추천 아이템 제공
        """
        # 협업 필터링 점수 계산
        collab_scores = np.zeros(self.ratings.shape[1])
        similar_users = np.argsort(self.user_sim[user_id])[::-1][1:6]
        
        for similar_user in similar_users:
            collab_scores += (self.ratings[similar_user] * 
                            self.user_sim[user_id][similar_user])
            
        # 콘텐츠 기반 점수 계산
        user_rated_items = np.where(self.ratings[user_id] > 0)[0]
        content_scores = np.zeros(self.ratings.shape[1])
        
        for item in user_rated_items:
            content_scores += (self.content_sim[item] * 
                             self.ratings[user_id][item])
            
        # 최종 점수 계산
        final_scores = (self.content_weight * content_scores + 
                       self.collab_weight * collab_scores)
        
        # 이미 평가한 아이템 제외
        final_scores[user_rated_items] = -1
        
        # 상위 n개 아이템 추천
        top_items = np.argsort(final_scores)[::-1][:n]
        return top_items

# 사용 예시
# 데이터 준비
ratings = np.array([
    [5, 3, 0, 1, 2],
    [4, 0, 0, 1, 1],
    [1, 1, 0, 5, 0],
    [1, 0, 0, 4, 4],
    [0, 1, 5, 4, 0],
])

item_features = [
    "액션 어드벤처 영화",
    "로맨틱 코미디 영화",
    "공포 스릴러 영화",
    "SF 판타지 영화",
    "다큐멘터리 영화"
]

# 추천 시스템 실행
recommender = HybridRecommender(content_weight=0.3)
recommender.fit(ratings, item_features)
recommendations = recommender.get_recommendations(0, n=3)
print("추천 아이템:", recommendations)

 

  • 콘텐츠 기반과 협업 필터링 결합
  • 가중치를 통한 두 방식의 균형
  • 최종 추천 점수 계산 및 추천 제공

 

3. 비교 분석표

구분 콘텐츠 기반 협업 필터링 하이브리드
특징 아이템 속성 분석 사용자 행동 분석 두 방식 결합
장점 새 아이템 추천 가능 의외의 발견 가능 높은 정확도
단점 과도한 특정화 콜드 스타트 문제 구현 복잡성
활용 전문 콘텐츠 추천 일반 상품 추천 대형 플랫폼

 

 


 

추천 시스템을 구현해 볼 수 있는 학습을 해보았다.

728x90