본문 바로가기

데이터사이언스

추천 시스템(2) 실습후기

 

🎵 추천 시스템 실습 후기: 암묵적 피드백과 ALS로 음악 취향 찾기!

안녕하세요! 오늘은 추천 시스템 실습을 하며 배운 내용을 정리해보려고 합니다. 특히 암묵적 피드백(Implicit Feedback) 데이터를 활용해 Matrix Factorization을 하고, ALS(Alternating Least Squares) 로 모델을 학습해보는 과정을 직접 코딩해보았습니다.


추천 시스템이란?

추천 시스템은 크게 두 가지로 나뉩니다.

1. 협업 필터링 (Collaborative Filtering)

  • 나와 비슷한 취향을 가진 사람들이 좋아한 아이템을 추천
  • 과거 행동 데이터 기반
  • 단점: 콜드스타트 문제 (신규 사용자, 신규 아이템 추천 어려움)

2. 콘텐츠 기반 필터링 (Content-based Filtering)

  • 아이템의 속성(장르, 키워드 등) 기반
  • 사용자가 좋아했던 아이템과 유사한 것 추천
  • 장점: 신규 아이템 추천 용이

암묵적 피드백 vs 명시적 피드백

구분 명시적 피드백 암묵적 피드백

예시 별점, 좋아요 재생 횟수, 클릭 수
목표 점수 예측 선호 여부 예측

오늘 다룬 데이터는 암묵적 피드백입니다. 예를 들어, 사용자가 어떤 아티스트의 음악을 얼마나 재생했는지를 기록한 데이터인데요. 이 재생 횟수 자체가 “좋아한다”는 직접적인 의사표시는 아니지만, 선호 여부를 추정할 수 있는 힌트가 됩니다.


CSR Matrix로 희소 행렬 처리하기

현실의 추천 데이터는 대부분 희소(Sparse) 합니다. 예를 들어:

  • 유저 수: 수십만 명
  • 아이템 수: 수십만 개
  • 실제 관측된 데이터: 몇 백만 개 뿐

따라서 모든 값을 메모리에 담으면 용량이 폭발하므로, 0이 아닌 값만 저장하는 CSR(Compressed Sparse Row) Matrix 를 사용합니다.


Matrix Factorization (MF)

MF는 아래 식을 근사하는 것이 목표입니다.

R≈P×QTR \approx P \times Q^T

  • RR: 사용자-아이템 행렬
  • PP: 사용자 잠재 요인 행렬
  • QQ: 아이템 잠재 요인 행렬

잠재 요인(latent factor)은 숫자로 표현할 수 없는 취향의 패턴이라고 볼 수 있습니다.


암묵적 피드백 MF의 차이

  • 명시적 피드백 → 점수 자체를 맞추려 함
  • 암묵적 피드백 → 선호 여부를 예측
  • 관측되지 않은 값(0)도 negative signal로 활용
  • confidence 값 사용cui=1+α⋅ruic_{ui} = 1 + \alpha \cdot r_{ui}

ALS(Alternating Least Squares)

MF에서 PPQQ 를 동시에 푸는 것은 어렵습니다.
ALS는 교대로 푸는 방식입니다.

  • Q 고정 → P 계산
  • P 고정 → Q 계산
  • 이 과정을 반복(iteration)

암묵적 피드백에서는 모든 값(관측 안 된 값 포함)을 학습에 사용하되, 관측되지 않은 값은 낮은 confidence를 부여하여 학습에 반영합니다.


ALS 실습 with implicit 라이브러리

오늘 실습에서는 Python의 implicit 라이브러리를 사용했습니다.


1. 라이브러리 설치 및 환경설정

!pip install implicit

환경변수 설정 (멀티스레드 충돌 방지):

import os
os.environ['OPENBLAS_NUM_THREADS'] = '1'
os.environ['MKL_NUM_THREADS'] = '1'
os.environ['KMP_DUPLICATE_LIB_OK'] = 'True'

2. CSR Matrix 생성

from scipy.sparse import csr_matrix

csr_data = csr_matrix(
    (data.play, (data.user_id, data.artist)),
    shape=(num_user, num_artist)
)

csr_data_transpose = csr_data.T
  • implicit ALS는 item-user matrix 를 input으로 사용하므로 transpose 필요!

3. ALS 모델 선언 및 학습

from implicit.als import AlternatingLeastSquares

als_model = AlternatingLeastSquares(
    factors=100,
    regularization=0.01,
    iterations=15,
    use_gpu=False,
    dtype=np.float32
)

als_model.fit(csr_data_transpose)

4. 유사 아티스트 추천

특정 아티스트와 비슷한 아티스트를 찾고 싶다면?

artist_id = artist_to_idx['coldplay']
similar_artist = als_model.similar_items(artist_id, N=10)

idx_to_artist = {v: k for k, v in artist_to_idx.items()}

similar_artist_names = [idx_to_artist[i] for i in similar_artist[0]]
print(similar_artist_names)

결과 예시:

['coldplay', 'maroon5', 'radiohead', ...]

함수로 만들기

def get_similar_artist(artist_name: str):
    artist_id = artist_to_idx[artist_name]
    similar_artist = als_model.similar_items(artist_id, N=10)
    return [idx_to_artist[i] for i in similar_artist[0]]

오늘의 깨달음

✅ 암묵적 피드백은 선호 여부를 맞추는 것이지, 재생 횟수를 맞추는 것이 아님
✅ CSR Matrix로 희소 데이터를 효과적으로 처리 가능
✅ ALS는 implicit data에 매우 잘 맞는다
✅ implicit 라이브러리로 대규모 데이터도 손쉽게 처리 가능!