추천 시스템 실습#

데이터셋 준비#

Surprise 라이브러리 소개#

Surprise는 다양한 추천 알고리즘과 유사도 지표를 제공하는 Python SciKit입니다. 이를 통해 추천 시스템을 쉽게 구축하고 분석할 수 있습니다. 주요 기능은 데이터 로딩, 알고리즘 적용, 결과 평가 등을 포함합니다.

%%capture

# 필요한 패키지 설치 
%pip install aibasics scikit-surprise

Note: 구글 Colab에서는 위의 패키지 설치 명령어를 실행한 후에 세션을 재시작해야 합니다. 메뉴에서 런타임 > 런타임 다시 시작을 선택하세요.

데이터셋 로딩#

Surprise 라이브러리를 사용하여 데이터셋을 로딩하는 방법에는 여러 가지가 있습니다. 파일에서 로딩, Pandas dataframe에서 로딩, 또는 Surprise가 제공하는 내장 데이터셋을 사용하는 방법 등이 있습니다.

내장 데이터셋 로딩#

from surprise import Dataset

# 내장 데이터셋 로딩
data = Dataset.load_builtin("ml-100k")

파일에서 데이터셋 로딩#

from surprise import Dataset
from surprise import Reader

# Reader 객체 생성
reader = Reader(line_format='user item rating', sep='\t', rating_scale=(1, 5))

# 파일에서 데이터셋 로딩
data = Dataset.load_from_file('파일 경로', reader=reader)

Pandas dataframe에서 데이터셋 로딩#

import pandas as pd
from surprise import Dataset
from surprise import Reader

# 데이터 딕셔너리 생성
ratings_dict = {
    "item": [1, 2, 3, 1, 2, 3, 2],
    "user": ["A", "A", "B", "B", "C", "C", "D"],
    "rating": [1, 2, 3, 1, 2, 3, 4],
}

# Pandas dataframe으로 변환
df = pd.DataFrame(ratings_dict)

# Reader 객체 생성
reader = Reader(rating_scale=(1, 5))

# 데이터셋 로딩
data = Dataset.load_from_df(df[["user", "item", "rating"]], reader)

데이터 전처리#

데이터 전처리 과정에서는 결측치 처리, 데이터 정규화, 범주형 데이터의 수치화 등 데이터를 분석에 적합한 형태로 가공합니다. Surprise 라이브러리는 데이터 로딩 시 다양한 옵션을 제공하여 이러한 전처리 과정을 용이하게 합니다.

데이터셋 준비 중요성#

추천 시스템 구축에서 데이터셋 준비는 매우 중요한 단계입니다. 데이터의 품질과 정제 정도는 추천 시스템의 성능에 직접적인 영향을 미치기 때문에, 데이터 로딩과 전처리 과정에 주의를 기울여야 합니다.

이 실습에서는 Surprise 라이브러리를 사용하여 데이터셋을 준비하는 방법을 배웠습니다. 이후 단계에서는 이 데이터를 사용하여 실제 추천 모델을 구축하고 평가하는 과정을 진행할 예정입니다.

K-최근접 이웃(k-NN) 기반 알고리즘#

k-NN 알고리즘 소개#

k-최근접 이웃(k-NN) 알고리즘은 사용자 또는 아이템 간의 유사도를 계산하여 추천을 생성하는 메모리 기반 접근 방식입니다. 이 알고리즘은 특히 유사도를 중심으로 한 추천 시스템에서 널리 사용됩니다.

Centered k-NN#

  • Centered k-NN 설명: 중심화된 코사인 유사도 공식에 기반한 알고리즘으로, Surprise 라이브러리에서는 KNNWithMeans로 구현되어 있습니다.

  • 특징: 사용자 또는 아이템 기반 접근법을 선택할 수 있으며, 유사도 계산 시 평균 평점을 고려하여 정확도를 높입니다.

유사도 계산 설정#

k-NN 알고리즘을 구성하기 위해서는 다음과 같은 설정이 필요합니다:

  • 유사도 지표: cosine, msd, pearson, pearson_baseline 중 선택할 수 있으며, 기본값은 msd입니다.

  • 접근법 선택: user_based는 Boolean 값으로, 사용자 기반 또는 아이템 기반 접근법을 결정합니다. 기본값은 True(사용자 기반)입니다.

  • 최소 공통 요소: min_support는 유사도를 계산할 때 필요한 최소 공통 아이템(또는 사용자)의 수를 지정합니다.

추천 함수 구성 예시#

from surprise import KNNWithMeans

# 아이템 기반 코사인 유사도 사용 설정
sim_options = {
    "name": "cosine",
    "user_based": False  # 아이템 기반 유사도 계산
}
algo = KNNWithMeans(sim_options=sim_options)

훈련셋 생성 및 추천 예측#

  • 훈련셋 생성: 데이터로부터 build_full_trainset 메소드를 사용하여 전체 훈련셋을 생성합니다.

  • 알고리즘 적용 및 유사도 계산: algo.fit(trainingSet)을 통해 훈련 데이터에 알고리즘을 적용하고 유사도 행렬을 계산합니다.

  • 추천 예측: algo.predict('사용자ID', 아이템ID)를 통해 특정 사용자의 아이템에 대한 예상 평점을 계산합니다.

다양한 k-NN 알고리즘 실험#

  • 알고리즘 변형 실험: 다양한 k-NN 기반 알고리즘과 유사도 옵션을 실험하여 최적의 추천 결과 도출

  • MovieLens 데이터셋 적용: MovieLens 데이터셋에 대해 실험을 진행하며, 벤치마크를 넘어서는 결과를 목표로 합니다.

  • 최적 파라미터 탐색: Surprise 라이브러리를 활용하여 데이터에 최적화된 파라미터를 찾습니다.

아래 예시는 사용자 ‘D’를 위한 추천을 생성하는 과정을 보여줍니다. 우선, 주어진 데이터를 사용하여 Surprise 라이브러리를 활용한 추천 시스템 구축 과정부터 시작하겠습니다.

import pandas as pd
from surprise import Dataset, Reader, KNNWithMeans
from surprise.model_selection import train_test_split
from surprise import accuracy

# 주어진 데이터를 Pandas DataFrame으로 변환
ratings_dict = {
    "item": [1, 2, 3, 1, 2, 3, 2],
    "user": ["A", "A", "B", "B", "C", "C", "D"],
    "rating": [1, 2, 3, 1, 2, 3, 4],
}
df = pd.DataFrame(ratings_dict)

# Surprise의 Reader 객체 생성
reader = Reader(rating_scale=(1, 5))

# DataFrame을 Surprise의 Dataset으로 변환
data = Dataset.load_from_df(df[["user", "item", "rating"]], reader)

# 데이터를 훈련 세트와 테스트 세트로 분리
trainset, testset = train_test_split(data, test_size=0.25)

# KNNWithMeans 알고리즘을 사용하여 아이템 기반 협업 필터링 모델을 생성
sim_options = {
    "name": "cosine",
    "user_based": False,  # 아이템 기반 유사도 계산
}
algo = KNNWithMeans(sim_options=sim_options)

# 훈련 데이터에 모델을 적용
algo.fit(trainset)

# 사용자 'D'가 아이템 1에 대해 어떤 평점을 줄지 예측
prediction = algo.predict("D", 1)

# 예측 결과 출력
print(f"사용자 'D'의 아이템 1에 대한 예상 평점: {prediction.est}")
Computing the cosine similarity matrix...
Done computing similarity matrix.
사용자 'D'의 아이템 1에 대한 예상 평점: 1

위 코드는 사용자 ‘D’가 아이템 1에 어떤 평점을 줄 것인지 예측하는 과정을 보여줍니다. 여기서는 KNNWithMeans 알고리즘을 사용하여 아이템 기반 협업 필터링을 수행하고 있습니다. sim_options에서 "user_based": False로 설정함으로써 아이템 기반 추천을 활성화했습니다. 이 예측 과정은 사용자 ‘D’의 기존 평점 데이터와 다른 아이템들 간의 유사도를 바탕으로 계산됩니다.

실제 코드 실행 결과는 prediction.est를 통해 확인할 수 있으며, 이 값은 사용자 ‘D’가 아이템 1에 어떤 평점을 줄 것으로 예상되는지를 나타냅니다. 이 예측값은 추천 시스템이 사용자에게 새로운 아이템을 추천할 때 참고할 수 있는 유용한 정보를 제공합니다.

알고리즘 파라미터 튜닝#

알고리즘 파라미터 튜닝의 중요성#

추천 시스템에서 알고리즘의 성능을 최적화하기 위해서는 파라미터 튜닝이 필수적입니다. 올바른 파라미터 설정은 추천의 정확도와 효율성을 크게 향상시킬 수 있습니다.

Surprise의 GridSearchCV 사용법#

Surprise 라이브러리는 scikit-learn의 GridSearchCV와 유사한 GridSearchCV 클래스를 제공합니다. 이를 통해 다양한 파라미터 조합을 실험하고, 주어진 정확도 측정 기준에 대해 최적의 파라미터를 찾을 수 있습니다.

유사도 지표 최적화 예시#

메모리 기반 접근 방식에서 어떤 유사도 지표가 데이터에 가장 적합한지 확인하는 예시입니다:

from surprise import KNNWithMeans
from surprise import Dataset
from surprise.model_selection import GridSearchCV

# "ml-100k" 내장 데이터셋 로딩
data = Dataset.load_builtin("ml-100k")

# 시도할 파라미터의 조합을 사전 형태로 설정
sim_options = {
    "name": ["msd", "cosine"],
    "min_support": [3, 4, 5],
    "user_based": [False, True],
}
param_grid = {"sim_options": sim_options}

# GridSearchCV를 통한 최적 파라미터 탐색
gs = GridSearchCV(KNNWithMeans, param_grid, measures=["rmse", "mae"], cv=3)
gs.fit(data)
# 최적의 RMSE 점수와 해당 파라미터 출력
print(gs.best_score["rmse"])
print(gs.best_params["rmse"])
0.9431275349252738
{'sim_options': {'name': 'msd', 'min_support': 3, 'user_based': False}}

튜닝 과정 해석#

  • 데이터셋 준비: “ml-100k”와 같은 내장 데이터셋 또는 사용자 정의 데이터셋을 로딩합니다.

  • 파라미터 조합 설정: sim_options에서 유사도 지표(msd, cosine), 최소 공통 요소(min_support), 사용자 기반/아이템 기반(user_based) 등을 다양하게 설정합니다.

  • GridSearchCV 실행: 설정된 파라미터 그리드에 대해 GridSearchCV를 실행하여 RMSE, MAE와 같은 성능 지표를 기준으로 최적의 조합을 찾습니다.

  • 결과 해석: 최적의 RMSE 점수와 해당하는 파라미터 조합을 확인함으로써, 알고리즘 성능을 개선할 수 있는 방향을 알 수 있습니다.

위의 결과 해석은 다음과 같습니다:

최적의 RMSE 점수#

  • 위 코드 실행 결과, 최적의 RMSE(Root Mean Square Error, 평균 제곱근 오차) 점수는 약 0.943입니다. 이 점수는 추천 시스템이 사용자의 선호도를 예측하는 데 있어 평균적으로 약 0.943의 오차를 가지고 있음을 나타냅니다. RMSE 점수가 낮을수록 알고리즘의 예측 정확도가 높다는 것을 의미하므로, 이 추천 시스템은 상대적으로 높은 예측 정확도를 보여주고 있습니다.

최적의 파라미터 조합#

  • 최적의 파라미터 조합은 유사도 측정 방식으로 ‘msd’(Mean Squared Difference, 평균 제곱 차이)를 사용하며, 최소 공통 요소(min_support)는 3, 그리고 추천 방식은 아이템 기반(user_based: False)으로 설정되어 있습니다.

    • ‘msd’ 유사도 측정 방식: 사용자 또는 아이템 간의 유사도를 평가할 때 평균 제곱 차이를 사용합니다. 이 방식은 계산이 간단하고 효율적이며, 해당 데이터셋에서 높은 성능을 보였습니다.

    • 최소 공통 요소 3: 두 사용자(또는 아이템) 간의 유사도를 계산할 때, 최소한 3개의 공통 아이템(또는 사용자)이 있어야 합니다. 이는 유사도 계산의 신뢰성을 보장합니다.

    • 아이템 기반 추천 방식: 추천을 생성할 때 아이템 간의 유사도를 기반으로 하여, 사용자에게 아이템을 추천합니다. 이 방식은 특히 아이템의 특성이 잘 정의되어 있고, 사용자 간의 상호작용 데이터보다 아이템의 속성 데이터가 더 풍부한 경우 효과적입니다.

이 결과는 ‘msd’ 유사도 측정 방식을 사용하고, 최소 공통 요소를 3으로 설정하며, 아이템 기반 추천을 사용할 때, MovieLens 100k 데이터셋에 대해 가장 낮은 RMSE 점수를 달성할 수 있음을 보여줍니다. 이는 추천 시스템의 성능을 최적화하기 위한 중요한 지침을 제공합니다. 따라서, 이 파라미터 조합을 사용하면 사용자에게 더 정확한 추천을 제공할 수 있을 것입니다.

알고리즘 파라미터 튜닝: 모델 기반 접근 방식#

모델 기반 접근 방식의 파라미터 튜닝#

모델 기반 추천 시스템에서는 사용자나 아이템 간의 잠재적인 관계를 모델링하여 추천을 생성합니다. 이 과정에서 중요한 파라미터들을 최적화하는 것이 성능에 큰 영향을 미칩니다.

SVD 알고리즘과 파라미터#

  • SVD 알고리즘: 특이값 분해(Singular Value Decomposition)를 이용한 행렬 분해 기법으로, 사용자의 잠재적인 선호도와 아이템의 특성을 분석하여 추천을 생성합니다.

  • n_epochs: 확률적 경사 하강법(SGD)의 반복 횟수로, 모델이 학습 데이터를 몇 번 반복하여 학습할지 결정합니다.

  • lr_all: 모든 파라미터에 대한 학습률로, 각 반복에서 파라미터가 얼마나 조정될지 결정합니다.

  • reg_all: 모든 파라미터에 대한 정규화 항으로, 과적합을 방지하기 위해 추가됩니다.

최적 파라미터 탐색 프로그램#

from surprise import SVD
from surprise import Dataset
from surprise.model_selection import GridSearchCV

# "ml-100k" 데이터셋 로딩
data = Dataset.load_builtin("ml-100k")

# 탐색할 파라미터 그리드 설정
param_grid = {"n_epochs": [5, 10], "lr_all": [0.002, 0.005], "reg_all": [0.4, 0.6]}

# GridSearchCV를 이용한 최적 파라미터 탐색
gs = GridSearchCV(SVD, param_grid, measures=["rmse", "mae"], cv=3)
gs.fit(data)

# 최적의 RMSE 점수와 파라미터 출력
print(gs.best_score["rmse"])
print(gs.best_params["rmse"])
0.9643786102115461
{'n_epochs': 10, 'lr_all': 0.005, 'reg_all': 0.4}

최적 파라미터 탐색 결과 해석#

  • 위 코드는 SVD 알고리즘을 사용하여 “ml-100k” 데이터셋에 대한 최적의 파라미터 조합을 탐색합니다.

  • gs.best_score["rmse"]는 탐색한 파라미터 조합 중 RMSE(Root Mean Square Error)가 가장 낮은 조합의 점수를 보여줍니다. RMSE가 낮을수록 예측 정확도가 높다는 것을 의미합니다.

  • gs.best_params["rmse"]는 가장 낮은 RMSE를 달성한 파라미터 조합을 나타냅니다. 이 조합을 사용하여 SVD 모델을 구성하고 학습시키면, 데이터셋에 대해 최적의 성능을 기대할 수 있습니다.

위 결과는 SVD 알고리즘의 파라미터 튜닝 과정에서 얻은 최적의 파라미터 조합과 해당 조합으로 달성한 RMSE 점수에 대한 정보를 제공합니다.

최적의 RMSE 점수#

  • 탐색된 파라미터 조합 중 RMSE(Root Mean Square Error, 평균 제곱근 오차) 점수가 가장 낮은 조합은 약 0.9641입니다. 이 점수는 알고리즘이 사용자의 선호도를 예측하는 데 평균적으로 약 0.9641의 오차를 가진다는 것을 의미합니다. RMSE 점수가 낮을수록 모델의 예측 정확도가 높다는 것을 나타냅니다.

최적의 파라미터 조합#

  • 최적의 파라미터 조합은 다음과 같습니다:

    • n_epochs: 10

    • lr_all: 0.005

    • reg_all: 0.4

  • 이는 SVD 알고리즘을 사용할 때, SGD(확률적 경사 하강법)의 반복 횟수를 10회로 설정하고, 모든 파라미터에 대한 학습률을 0.005로, 그리고 모든 파라미터에 대한 정규화 항을 0.4로 설정하는 것이 “ml-100k” 데이터셋에 대해 가장 효과적인 성능을 제공한다는 것을 의미합니다.

해석 및 적용#

  • 이 결과는 특정 데이터셋에 대해 SVD 알고리즘의 성능을 최적화하기 위한 구체적인 지침을 제공합니다. 추천 시스템 개발자는 이 파라미터 조합을 사용하여 사용자의 영화 선호도를 더 정확하게 예측할 수 있는 모델을 구축할 수 있습니다.

  • 또한, 이러한 최적화 과정을 통해 추천 시스템의 일반적인 성능 향상 방법에 대한 이해를 높일 수 있으며, 다른 유형의 데이터셋이나 추천 시나리오에도 유사한 접근 방식을 적용할 수 있습니다.

종합적으로, GridSearchCV를 활용한 파라미터 튜닝은 추천 시스템의 예측 정확도를 최대화하는 데 중요한 단계입니다. 이를 통해 사용자에게 더 만족스러운 추천을 제공할 수 있습니다.

결론#

이번 추천 시스템 실습을 통해 우리는 다양한 추천 알고리즘과 파라미터 튜닝 방법에 이르기까지, 추천 시스템 개발의 전체적인 프로세스를 경험했습니다.

중요 포인트#

  • 추천 시스템의 기본 개념: 사용자의 선호도를 예측하여 관련성 높은 아이템을 추천하는 시스템

  • 다양한 추천 알고리즘: 콘텐츠 기반 추천, 메모리 기반 협업 필터링, 모델 기반 접근 방식 등

  • 파라미터 튜닝의 중요성: 알고리즘의 성능을 최적화하기 위해 파라미터 튜닝이 필수적임

  • 실습을 통한 이해 증진: 코드를 직접 작성하고 결과를 분석함으로써 이론적 지식을 실제 상황에 적용하는 능력 향상