RecBole: 추천 시스템 구축을 위한 종합 가이드
1. RecBole 소개
RecBole 개요
RecBole은 파이토치(PyTorch) 기반의 오픈 소스 추천 시스템 라이브러리입니다. 이 프레임워크는 연구자와 개발자들이 최신 추천 알고리즘을 쉽게 구현하고 실험할 수 있도록 설계되었으며, 다양한 추천 시스템 모델을 통합하고, 표준화된 방식으로 이들을 평가하고 비교할 수 있는 플랫폼을 제공합니다.
최근 추천 시스템 개발에서는 다양한 접근 방식과 알고리즘을 실험하고 비교하는 것이 필수적입니다. RecBole은 이러한 요구사항을 충족시키기 위해 개발되었다고 할 수 있으며, 학계와 산업계 모두에서 널리 사용되고 있습니다.
왜 RecBole을 추천 시스템에 사용할까?
RecBole은 여러 가지 독특한 장점을 제공합니다. 첫째, 광범위한 알고리즘 라이브러리를 제공하여 사용자가 다양한 추천 접근 방식을 쉽게 실험할 수 있습니다. 일반적인 협업 필터링부터 최신 딥러닝 기반 모델까지, RecBole은 폭넓은 알고리즘을 지원합니다.
둘째, RecBole은 표준화된 데이터 처리 파이프라인을 제공합니다. 이는 데이터 전처리, 모델 학습, 평가에 이르는 전체 과정을 일관된 방식으로 처리할 수 있게 해줍니다. 이러한 표준화는 실험의 재현성을 높이고, 다른 연구자들과의 결과 비교를 용이하게 합니다.
마지막으로, RecBole은 다양한 확장성을 제공합니다. 대규모 데이터셋에서도 효율적으로 동작하며, 사용자 정의 모델과 평가 메트릭을 쉽게 추가할 수 있습니다.
RecBole의 주요 기능과 장점
RecBole의 핵심 기능은 크게 네 가지 범주로 나눌 수 있습니다:
- 통합된 데이터 처리:
from recbole.data import create_dataset, data_preparation
# 데이터셋 생성
dataset = create_dataset('ml-100k')
# 데이터 준비
train_data, valid_data, test_data = data_preparation(dataset)
- 다양한 모델 지원:
from recbole.model.general_recommender import BPR
# BPR 모델 초기화
model = BPR(config, dataset)
- 유연한 학습 프로세스:
from recbole.trainer import Trainer
# 트레이너 초기화 및 학습
trainer = Trainer(config, model)
trainer.fit(train_data)
2. 설치 및 환경 설정
시스템 요구사항
RecBole을 설치하기 전에 다음과 같은 기본 요구사항을 확인해야 합니다:
- Python 3.7 이상
- PyTorch 1.7.0 이상
- CUDA 지원 (GPU 사용 시)
- 최소 8GB RAM (데이터셋 크기에 따라 다름)
이러한 요구사항은 다음 코드로 확인할 수 있습니다:
import sys
import torch
print(f"Python 버전: {sys.version}")
print(f"PyTorch 버전: {torch.__version__}")
print(f"CUDA 사용 가능: {torch.cuda.is_available()}")
pip을 통한 RecBole 설치
RecBole은 pip를 통해 쉽게 설치할 수 있습니다:
pip install recbole
<참고> 개발 환경 설정하기
개발 환경을 효율적으로 설정하기 위해서는 가상 환경을 사용하는 것이 좋습니다.
# 가상환경 생성
python -m venv recbole-env
# 가상환경 활성화 (Windows)
recbole-env\Scripts\activate
# 가상환경 활성화 (Linux/Mac)
source recbole-env/bin/activate
# 필요한 패키지 설치
pip install recbole torch numpy pandas scikit-learn
권장 프로젝트 구조:
recbole-project/
├── data/
│ ├── raw/
│ └── processed/
├── models/
│ └── saved/
├── configs/
│ └── model_config.yaml
├── src/
│ ├── train.py
│ └── evaluate.py
└── requirements.txt
설치 확인 및 자주 발생하는 문제 해결
설치가 정상적으로 완료되었는지 확인하기 위해 다음 테스트 코드를 실행해볼 수 있습니다:
import recbole
from recbole.quick_start import run_recbole
# 설치 버전 확인
print(f"RecBole 버전: {recbole.__version__}")
# 간단한 모델 실행 테스트
try:
run_recbole(model='BPR', dataset='ml-100k')
print("RecBole 설치 및 실행 성공!")
except Exception as e:
print(f"오류 발생: {str(e)}")
3. RecBole 프레임워크 이해하기
RecBole의 핵심 아키텍처
RecBole은 모듈화된 설계를 통해 확장성과 유연성을 제공합니다. 주요 컴포넌트는 다음과 같습니다:
- 데이터 레이어: 데이터 로딩, 전처리, 샘플링을 담당
- 모델 레이어: 다양한 추천 알고리즘 구현
- 트레이닝 레이어: 모델 학습 및 검증 프로세스 관리
- 평가 레이어: 다양한 평가 메트릭 계산
import torch
from recbole.data import create_dataset, data_preparation
from recbole.model.general_recommender import BPR
from recbole.trainer import Trainer
from recbole.config import Config
# 설정 파일 로드 및 데이터셋 설정
config = Config(model='BPR', dataset='ml-100k')
# GPU 사용 여부를 확인하여 장치를 설정합니다.
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
config['device'] = device # RecBole 설정에 장치를 명시적으로 지정합니다.
# 데이터셋을 생성합니다.
dataset = create_dataset(config)
# 데이터셋의 기본 정보와 interaction features 출력 (데이터가 제대로 로드되었는지 확인)
print("Dataset Info:")
print(dataset)
# interaction features의 첫 5개 데이터 확인
print("\nInteraction Features (First 5 rows):")
print(dataset.inter_feat.head())
# 데이터셋을 학습/검증/테스트 데이터로 나눕니다.
train_data, valid_data, test_data = data_preparation(config, dataset)
# 모델 초기화 및 장치로 이동
model = BPR(config, train_data.dataset).to(device)
# 트레이너 초기화
trainer = Trainer(config, model)
# 학습 및 평가
trainer.fit(train_data, valid_data)
지원되는 모델 및 알고리즘
RecBole은 다양한 일반 추천 모델을 지원합니다:
from recbole.model.general_recommender import (
BPR, # Bayesian Personalized Ranking
LightGCN, # Light Graph Convolution Network
EASE, # Embarrassingly Shallow AutoEncoder
)
# BPR 모델 예제
config['model'] = 'BPR'
bpr_model = BPR(config, dataset)
# NCF 모델 예제
config['model'] = 'NNCF'
ncf_model = NCF(config, dataset)
1. ADMMSLIM (Alternating Direction Method of Multipliers for SLIM)
- SLIM(Sparse Linear Method) 모델의 확장판으로, ADMMSLIM은 추천 행렬의 희소성(sparsity)을 최적화하는 방법으로 ADM(Alternating Direction Method)을 사용하여 추천 성능을 개선합니다.
2. BPR (Bayesian Personalized Ranking)
- 사용자-아이템 상호작용 데이터를 순위 학습 방식으로 최적화하는 모델로, 사용자에게 선호될 가능성이 높은 아이템을 랭킹하도록 학습합니다. 협업 필터링에 최적화된 방식입니다.
3. CDAE (Collaborative Denoising AutoEncoder)
- Denoising AutoEncoder를 기반으로 하는 협업 필터링 모델로, 입력 데이터의 노이즈를 제거하여 사용자와 아이템 간의 관계를 학습합니다.
4. ConvNCF (Convolutional Neural Collaborative Filtering)
- 협업 필터링에 CNN(Convolutional Neural Network)을 결합하여, 사용자와 아이템의 잠재 표현을 더 깊이 있게 학습하는 모델입니다.
5. DGCF (Disentangled Graph Collaborative Filtering)
- 그래프 기반 협업 필터링으로, 사용자와 아이템 간의 관계를 다양한 측면으로 나누어 학습해 더 정교한 추천을 수행합니다.
6. DMF (Deep Matrix Factorization)
- Deep Learning을 활용한 Matrix Factorization 모델로, 사용자와 아이템의 잠재 표현을 깊이 있게 학습하여 협업 필터링 성능을 향상시킵니다.
7. DiffRec (Differentiable Recommendation)
- 추천 시스템의 차분 가능성을 활용하여, 더 효과적으로 추천 행렬을 최적화하는 모델입니다.
8. EASE (Embarrassingly Shallow AutoEncoder)
- 매우 단순한 구조의 선형 오토인코더 기반 모델로, 높은 계산 효율성과 간결함을 추구하면서도 뛰어난 성능을 보입니다.
9. ENMF (Explicit Non-negative Matrix Factorization)
- 명시적인 비음수 제약을 추가하여 사용자와 아이템 간의 관계를 학습하는 Matrix Factorization 모델입니다.
10. FISM (Factored Item Similarity Models)
- 아이템 기반 협업 필터링 모델로, 각 아이템의 유사성을 학습하여 사용자에게 관련된 아이템을 추천합니다.
11. GCMC (Graph Convolutional Matrix Completion)
- 그래프 신경망(GCN)을 사용하여 사용자와 아이템 간의 관계를 그래프 구조로 학습하고 이를 통해 추천을 수행하는 모델입니다.
12. ItemKNN (Item-based k-Nearest Neighbors)
- 아이템 간의 유사성을 기반으로 추천하는 모델로, 각 사용자에게 가장 유사한 아이템을 추천합니다. 단순하면서도 효과적인 방식입니다.
13. DiffRec (Differentiable Recommendation)
- 연속적 미분 가능성을 기반으로 추천 행렬을 최적화하는 모델로, 높은 표현력을 갖춘 추천 시스템입니다.
14. LightGCN (Light Graph Convolutional Networks)
- GCN 기반 협업 필터링의 경량화 버전으로, 더 단순한 그래프 구조를 사용하여 효율성을 높인 모델입니다.
15. LINE (Large-scale Information Network Embedding)
- 대규모 그래프 데이터를 효율적으로 학습하기 위해 설계된 모델로, 사용자와 아이템 간의 관계를 그래프 임베딩으로 표현합니다.
16. MacridVAE (Macroscopic Regularized VAE)
- 사용자 그룹 수준의 정보와 개별 사용자 정보를 동시에 학습하여 정밀한 추천을 수행하는 변분 오토인코더(VAE) 기반 모델입니다.
17. MultiDAE (Denoising AutoEncoder for Multimodal Data)
- 변분 오토인코더 구조를 사용해 사용자-아이템 상호작용 데이터의 노이즈를 제거하여 더 정교한 추천을 가능하게 합니다.
18. MultiVAE (Variational Autoencoder for Collaborative Filtering)
- VAE를 사용하여 사용자와 아이템 간의 복잡한 분포를 학습하며, 추천 성능을 높이는 변분 오토인코더 기반 모델입니다.
19. NAIS (Neural Attentive Item Similarity Model)
- 사용자와 아이템 간의 유사도를 Neural Attention 메커니즘을 사용해 학습하는 모델로, 협업 필터링의 성능을 향상시킵니다.
20. NCE-PLRec (Noise Contrastive Estimation Personalized Ranking)
- 노이즈 대조 추정(NCE)을 활용해 사용자에게 맞춤화된 아이템 순위를 예측하는 모델입니다.
21. NCL (Neural Collaborative Learning)
- 협업 필터링과 신경망 구조를 결합하여 사용자와 아이템 간의 비선형 상호작용을 학습하는 모델입니다.
22. NeuMF (Neural Matrix Factorization)
- MF와 MLP(Multi-Layer Perceptron)를 결합하여 선형과 비선형 상호작용을 모두 학습하는 신경망 기반의 협업 필터링 모델입니다.
23. NGCF (Neural Graph Collaborative Filtering)
- GCN을 활용해 사용자와 아이템 간의 관계를 학습하며, 사용자-아이템 그래프 구조를 통해 더욱 정교한 추천을 수행하는 모델입니다.
24. NNCF (Neural Network Collaborative Filtering)
- 신경망 기반의 협업 필터링 모델로, 사용자와 아이템 간의 상호작용을 심층 신경망을 통해 학습합니다.
25. Pop (Popularity-based Recommendation)
- 가장 인기가 많은 아이템을 추천하는 단순한 모델로, 추가적인 학습 없이 아이템의 인기도를 기반으로 추천을 수행합니다.
26. RaCT (Ranking-based Collaborative Training)
- 순위 기반 학습 방식을 사용하여 추천 행렬을 최적화하는 모델로, 사용자 선호도에 맞춘 랭킹 학습에 최적화되어 있습니다.
27. Random (Random Recommendation)
- 임의의 아이템을 사용자에게 추천하는 모델로, 성능은 낮지만 기본 베이스라인 모델로 사용될 수 있습니다.
28. RecVAE (Recommender Variational AutoEncoder)
- 변분 오토인코더를 사용하여 추천 시스템을 최적화하는 모델로, 사용자와 아이템 간의 상호작용의 복잡한 분포를 학습합니다.
29. SGL (Self-supervised Graph Learning for Recommendation)
- 자가 지도 학습과 그래프 신경망을 결합하여 그래프 기반 추천을 수행하며, 일반화 성능을 높이는 모델입니다.
30. SimpleX (Simple and Explainable Model)
- 단순하고 해석 가능한 추천 모델로, 가벼운 계산량과 해석 가능성을 갖추고 있습니다.
31. SLIMElastic (Sparse Linear Methods with Elastic Net Regularization)
- SLIM의 확장 모델로, Elastic Net 정규화를 사용하여 희소성(sparsity)과 일반화 성능을 동시에 높이는 모델입니다.
32. SpectralCF (Spectral Collaborative Filtering)
- 사용자-아이템 그래프의 스펙트럼 정보를 활용해 협업 필터링을 수행하는 모델로, 고유값 분해 등을 통해 그래프의 구조를 학습합니다.
순차 추천 모델
순차적 패턴을 고려하는 모델들도 지원됩니다:
from recbole.model.sequential_recommender import (
GRU4Rec, # GRU for Sequential Recommendation
BERT4Rec, # BERT for Sequential Recommendation
SASRec, # Self-Attention based Sequential Recommendation
)
# 순차 추천 모델 설정
config['model'] = 'GRU4Rec'
sequential_model = GRU4Rec(config, dataset)
BERT4Rec
- BERT의 Transformer 아키텍처를 사용하여 시퀀스 데이터에서 다음 아이템을 예측하는 모델입니다.
Caser
- CNN(Convolutional Neural Network)을 사용해 시퀀스 데이터를 학습하며, 사용자의 최근 상호작용을 기반으로 다음 아이템을 예측합니다.
CORE (Contextual Recurrent Model)
- 시퀀스 데이터에서 컨텍스트 정보를 결합하여 사용자의 행동을 예측하는 모델입니다.
DIN (Deep Interest Network)
- 사용자의 최근 상호작용을 동적으로 가중치를 부여해 사용자의 관심사를 학습하고, 이를 바탕으로 추천을 수행합니다.
FDSA (Feature Diversified Self-Attention)
- Self-Attention 메커니즘을 통해 사용자의 다양한 관심사를 반영하는 추천 모델입니다.
FOSSIL (Factored Sequential Prediction Model)
- Markov Chain과 MF(Matrix Factorization)를 결합하여 시퀀스 기반의 예측을 수행합니다.
FPMC (Factorized Personalized Markov Chains)
- 사용자-아이템 간의 관계를 Markov Chain과 MF를 결합해 모델링한 시퀀스 추천 모델입니다.
GCSAN (Gated Collaborative Self-Attention Network)
- Self-Attention과 Gated Mechanism을 결합하여 시퀀스 데이터를 학습하고, 중요도를 반영한 예측을 수행합니다.
GRU4Rec
- GRU(Recurrent Neural Network)를 사용해 시퀀스 데이터를 학습하며, 사용자의 다음 행동을 예측합니다.
GRU4RecF
- GRU4Rec의 확장판으로, 추가적인 기능과 정교한 학습 메커니즘을 통해 성능을 개선한 모델입니다.
GRU4RecKG
- GRU4Rec에 지식 그래프를 결합하여 사용자 행동 예측에 추가적인 컨텍스트 정보를 반영합니다.
HGN (Hierarchical Gating Network)
- 계층적 게이팅 메커니즘을 통해 사용자의 행동 패턴을 학습하며, 다중 수준의 정보를 활용해 추천을 수행합니다.
HRM (Hierarchical Representation Model)
- 계층적 표현 학습을 통해 사용자의 행동을 예측하며, 최근 및 장기 상호작용을 동시에 고려합니다.
KSR (Knowledge-enhanced Sequential Recommendation)
- 시퀀스 기반 추천에 지식 정보를 결합하여, 더 정교한 사용자 행동 예측을 수행합니다.
NARM (Neural Attentive Recommendation Machine)
- 시퀀스 데이터에 Attention 메커니즘을 적용하여 사용자의 최근 행동에 기반한 추천을 수행합니다.
NextItNet
- CNN을 기반으로 시퀀스 데이터를 학습하며, 사용자의 다음 행동을 예측하는 구조를 가집니다.
NPE (Neural Personalized Embedding)
- 사용자의 시퀀스 데이터를 Embedding 방식으로 학습하여, 다음 아이템을 예측합니다.
RepeatNet
- 사용자의 반복 행동 패턴을 학습하여, 반복된 구매 또는 상호작용을 예측하는 모델입니다.
S3Rec (Self-Supervised Sequential Recommendation)
- 자가 지도 학습 방식을 사용해 사용자의 행동 시퀀스에서 의미 있는 표현을 학습하는 모델입니다.
SASRec (Self-Attentive Sequential Recommendation)
- Self-Attention 메커니즘을 통해 사용자의 시퀀스 행동을 학습하여, 다음 행동을 예측하는 모델입니다.
SASRecF
- SASRec의 확장판으로, 더 많은 기능을 추가해 시퀀스 기반 예측 성능을 개선한 모델입니다.
SHAN (Short-term and Long-term Attention Network)
- 사용자의 단기 및 장기 행동을 모두 반영하여, 두 가지 수준의 관심사를 통합한 추천을 수행합니다.
SRGNN (Session-based Recommendation with Graph Neural Network)
- GNN을 사용해 사용자의 세션 데이터에서 그래프 구조를 학습하며, 이를 통해 추천 성능을 향상시킵니다.
STAMP (Short-term Attention/Memory Priority)
- 사용자 행동 시퀀스에서 단기 메모리와 주의 메커니즘을 사용해 사용자 행동을 예측하는 모델입니다.
TransRec (Translation-based Recommendation)
- 시퀀스 데이터에서 Translation 메커니즘을 사용해 사용자 행동의 변화와 이동을 모델링합니다.
FEARec (Feature-Enriched Attentive Sequential Recommendation)
- 시퀀스 데이터에서 Self-Attention과 피처 정보를 결합해 더 풍부한 정보를 활용하여 예측하는 모델입니다.
컨텍스트 기반 및 지식 기반 모델
컨텍스트 정보와 지식 그래프를 활용하는 모델들:
from recbole.model.context_aware_recommender import (
FM, # Factorization Machine
DeepFM, # Deep Factorization Machine
)
# FM 모델 설정
config['model'] = 'FM'
context_model = FM(config, dataset)
# 지식 그래프 기반 설정
config['model'] = 'KGAT'
kg_model = KGAT(config, dataset)
AFM (Attentional Factorization Machine)
- Factorization Machine(FM) 기반 모델로, 사용자와 아이템의 상호작용에 대한 중요도를 학습하기 위해 Attention 메커니즘을 도입한 모델입니다.
AutoInt
- 자동으로 피처 간의 상호작용을 학습하고, Self-Attention 메커니즘을 활용해 다양한 상호작용을 효과적으로 캡처하는 모델입니다.
DCN (Deep & Cross Network)
- 깊은 신경망과 교차 네트워크 구조를 결합하여, 피처 간의 복잡한 상호작용을 학습하고 효율적인 예측을 가능하게 합니다.
DCN V2
- DCN의 개선된 버전으로, 더 많은 피처 상호작용을 학습할 수 있도록 구조가 확장된 모델입니다.
DeepFM
- FM과 심층 신경망을 결합하여, 선형 상호작용과 비선형 상호작용을 동시에 학습하는 추천 모델입니다.
DSSM (Deep Structured Semantic Model)
- 사용자와 아이템의 특징을 각각 학습하고, 유사도를 계산하여 추천을 수행하는 심층 신경망 기반 모델입니다.
EulerNet
- 비선형 특성 간의 상호작용을 학습하기 위한 구조로, 더 깊고 복잡한 피처 관계를 캡처하는 모델입니다.
FFM (Field-aware Factorization Machine)
- FM의 확장 버전으로, 각 피처 필드(field) 간의 관계를 학습하여 더 정교한 예측을 가능하게 합니다.
FiGNN (Field-aware Graph Neural Network)
- FFM과 GNN(Graph Neural Network)을 결합하여, 피처 필드 간의 관계를 그래프 구조로 학습하는 모델입니다.
FM (Factorization Machine)
- 피처 간의 2차 상호작용을 학습하여 예측하는 모델로, 간단하면서도 효과적인 성능을 보입니다.
FNN (Factorization-supported Neural Network)
- FM의 출력을 신경망의 입력으로 사용하여, 선형 및 비선형 상호작용을 동시에 학습하는 구조를 갖춘 모델입니다.
FwFM (Field-weighted Factorization Machine)
- 각 피처 필드의 중요도를 가중치로 부여하여, 필드 간의 관계를 효과적으로 학습하는 FM 기반 모델입니다.
KD_DAGFM (Knowledge Distillation Directed Acyclic Graph FM)
- 지식 증류(Knowledge Distillation)와 DAG 구조를 결합하여, FM을 확장하고 예측 성능을 향상시킨 모델입니다.
LR (Logistic Regression)
- 가장 기본적인 회귀 모델로, 피처와 타겟 간의 관계를 선형 함수로 학습하여 예측합니다.
NFM (Neural Factorization Machine)
- FM에 신경망 구조를 추가하여, 피처 간의 비선형 상호작용을 학습할 수 있는 확장된 모델입니다.
PNN (Product-based Neural Network)
- 피처 간의 곱셈(product) 연산을 신경망 구조에 결합하여, 피처 간의 복잡한 관계를 학습합니다.
WideDeep
- 선형 모델(Wide)과 심층 신경망(Deep)을 결합하여, 선형성과 비선형성을 동시에 학습하는 추천 모델입니다.
xDeepFM
- DeepFM의 확장 버전으로, 피처 간의 상호작용을 압축된 구조로 학습하여 더 복잡한 관계를 캡처합니다.
4. RecBole을 위한 데이터 준비
지원되는 데이터셋 형식
RecBole은 다양한 형식의 데이터를 지원합니다. 기본적으로 다음과 같은 파일 형식을 처리할 수 있습니다:
- Atomic Files: 기본적인 상호작용 데이터
- Token-based Files: 토큰화된 시퀀스 데이터
- Knowledge-based Files: 지식 그래프 데이터
# 데이터셋 설정 예제
config = {
'load_col': {
'inter': ['user_id', 'item_id', 'rating', 'timestamp'],
'user': ['user_id', 'age', 'gender', 'occupation'],
'item': ['item_id', 'category', 'title', 'genre']
},
'USER_ID_FIELD': 'user_id',
'ITEM_ID_FIELD': 'item_id',
'RATING_FIELD': 'rating',
'TIME_FIELD': 'timestamp'
}
# 데이터셋 생성
dataset = create_dataset('custom_dataset', config=config)
사용자 데이터 준비 및 가져오기
RecBole에서 커스텀 데이터셋을 사용하기 위해서는 적절한 형식으로 데이터를 준비해야 합니다. 일반적으로 다음과 같은 형식이 사용됩니다:
import pandas as pd
# 상호작용 데이터 예시
inter_df = pd.DataFrame({
'user_id': [1, 1, 2, 2, 3],
'item_id': [101, 102, 102, 103, 101],
'rating': [4.0, 3.5, 5.0, 2.0, 3.0],
'timestamp': [1624243200, 1624329600, 1624416000, 1624502400, 1624588800]
})
# 사용자 정보 데이터 예시
user_df = pd.DataFrame({
'user_id': [1, 2, 3],
'age': [25, 30, 35],
'gender': ['M', 'F', 'M']
})
# 아이템 정보 데이터 예시
item_df = pd.DataFrame({
'item_id': [101, 102, 103],
'category': ['electronics', 'books', 'fashion'],
'price': [199.99, 29.99, 49.99]
})
# CSV 파일로 저장
inter_df.to_csv('data/inter.csv', index=False)
user_df.to_csv('data/user.csv', index=False)
item_df.to_csv('data/item.csv', index=False)
데이터 전처리 기법
결측치 처리
RecBole은 다양한 결측치 처리 방법을 제공합니다:
# 설정 파일에서 결측치 처리 방법 정의
config = {
'fill_nan': True,
'numeric_fill_na_strategy': 'mean', # 수치형 데이터 평균값으로 채우기
'categorical_fill_na_strategy': 'most_frequent', # 범주형 데이터 최빈값으로 채우기
'fill_nan_value': {
'price': 0, # 특정 필드 커스텀 값으로 채우기
'category': 'unknown'
}
}
# 데이터셋 생성 시 결측치 처리
dataset = create_dataset('custom_dataset', config=config)
범주형 특성 인코딩
범주형 데이터는 자동으로 인코딩됩니다:
# 범주형 특성 인코딩 설정
config = {
'alias_of_user_id': ['user'], # user_id의 별칭 설정
'alias_of_item_id': ['item'], # item_id의 별칭 설정
'encoding_field': ['gender', 'category'], # 인코딩할 필드 지정
'token_delimiter': ' ' # 토큰 구분자 설정
}
# 인코딩된 데이터 확인
dataset = create_dataset('custom_dataset', config=config)
print(dataset.fields_encoding_map) # 인코딩 매핑 확인
정규화 및 스케일링
수치형 특성의 정규화와 스케일링:
# 정규화 설정
config = {
'normalize_field': ['price', 'age'], # 정규화할 필드
'normalize_type': 'min-max', # 정규화 방식 (min-max 또는 z-score)
}
# 데이터 정규화 적용
dataset = create_dataset('custom_dataset', config=config)
Config Parameters
일반 설정 (General Settings)
- model: 사용하고자 하는 추천 모델의 이름입니다. 예:
'BPR','MF','LightGCN'등.- dataset: 사용할 데이터셋의 이름입니다. RecBole에서 제공하는 내장 데이터셋 또는 사용자 지정 데이터셋 이름을 지정합니다.
- data_path: 데이터셋 파일이 위치한 디렉토리의 경로입니다.
- checkpoint_dir: 모델 체크포인트를 저장할 디렉토리입니다.
- save_model: 학습된 모델을 저장할지 여부를 결정하는 불리언 값입니다.
- load_model: 저장된 모델 체크포인트를 로드할지 여부를 결정하는 불리언 값입니다.
- seed: 재현성을 위한 랜덤 시드 값입니다.
- device: 학습 및 평가에 사용할 장치입니다.
'cpu'또는'cuda'로 설정합니다.
데이터 설정 (Data Settings)
- field_separator: 데이터셋 파일에서 필드를 구분하는 구분자입니다. 예:
'\t',','등.- seq_separator: 시퀀스 필드에서 아이템을 구분하는 구분자입니다.
- USER_ID_FIELD: 데이터셋에서 사용자 ID를 나타내는 필드 이름입니다.
- ITEM_ID_FIELD: 데이터셋에서 아이템 ID를 나타내는 필드 이름입니다.
- TIME_FIELD: 타임스탬프를 나타내는 필드 이름입니다.
- RATING_FIELD: 평점 점수를 나타내는 필드 이름입니다.
- LABEL_FIELD: 레이블을 나타내는 필드 이름입니다. 분류 작업 등에 사용됩니다.
- NEG_PREFIX: 부정적 샘플의 필드 이름에 사용되는 접두사입니다.
- LIST_SUFFIX: 리스트 타입 필드의 접미사입니다.
- MAX_USER_INTER_NUM: 사용자당 최대 상호작용 수입니다. 이 값을 초과하는 상호작용은 잘립니다.
- MIN_USER_INTER_NUM: 사용자당 최소 상호작용 수입니다. 이 값보다 적은 상호작용을 가진 사용자는 제거됩니다.
- MAX_ITEM_INTER_NUM: 아이템당 최대 상호작용 수입니다.
- MIN_ITEM_INTER_NUM: 아이템당 최소 상호작용 수입니다.
- lowest_val: 평점 데이터셋에서 가능한 최저 평점 값입니다.
- highest_val: 가능한 최고 평점 값입니다.
- sparse_features: 희소 특성 필드의 이름 목록입니다.
- dense_features: 밀집 특성 필드의 이름 목록입니다.
- interactions_order: 상호작용 데이터를 정렬하는 기준입니다.
'user','time'등으로 설정합니다.
데이터 전처리 설정 (Data Preprocessing Settings)
- normalize_field: 정규화할 필드의 목록입니다.
- normalize_all: 모든 밀집 필드를 정규화할지 여부를 결정하는 불리언 값입니다.
- fill_na: 결측치를 처리하는 방법입니다.
'mean','median','zero'등으로 설정합니다.- benchmark_filename: 벤치마크 데이터셋의 파일 이름 목록입니다.
- k_core: 사용자와 아이템이 최소 k개의 상호작용을 가지도록 하는 k-core 전처리를 위한 값입니다.
- lowest_val: 평점 정규화를 위한 최소 값입니다.
- highest_val: 평점 정규화를 위한 최대 값입니다.
데이터 분할 설정 (Split Settings)
- split_ratio: 데이터셋을 분할할 비율입니다. 예:
[0.8, 0.1, 0.1]은 학습, 검증, 테스트 세트로 80%, 10%, 10%로 분할합니다.- group_by_user: 데이터를 분할할 때 사용자를 기준으로 그룹화할지 여부입니다.
- leave_one_num: ‘leave-one-out’ 방식으로 각 사용자마다 남겨둘 상호작용 수입니다.
- split_strategy: 데이터셋을 분할하는 전략입니다.
'loo','ratio','by_time'등으로 설정합니다.- shuffle: 분할 전에 데이터를 섞을지 여부입니다.
- user_inter_order: 사용자 상호작용을 정렬하는 순서입니다.
학습 설정 (Training Settings)
- epochs: 학습할 에포크 수입니다.
- train_batch_size: 학습 배치 크기입니다.
- learner: 사용할 옵티마이저의 종류입니다.
'adam','sgd','adagrad'등으로 설정합니다.- learning_rate: 옵티마이저의 학습률입니다.
- weight_decay: 가중치 감쇠(L2 정규화) 계수입니다.
- stopping_step: 개선이 없을 때 조기 종료를 위한 에포크 수입니다.
- clip_grad_norm: 그래디언트 클리핑을 위한 최대 norm 값입니다.
- loss_type: 사용할 손실 함수의 유형입니다. 예:
'BPR','CrossEntropy','MSE'등.- reg_weight: 손실 함수에 대한 정규화 가중치입니다.
- neg_sampling: 부정적 샘플링 전략입니다.
'uniform','adversarial'등으로 설정합니다.- eval_step: 검증 세트에서 평가를 수행할 에포크 간격입니다.
- optimizer_params: 옵티마이저에 대한 추가 파라미터입니다.
평가 설정 (Evaluation Settings)
- eval_batch_size: 평가 시의 배치 크기입니다.
- metrics: 계산할 평가 지표의 목록입니다. 예:
['Recall', 'Precision', 'NDCG', 'MRR'].- topk: 상위 K개 평가 지표를 위한 K 값의 목록입니다. 예:
[5, 10, 20].- eval_args: 평가 설정에 대한 추가 인자입니다.
- valid_metric: 검증 및 조기 종료에 사용할 평가 지표입니다.
- eval_setting: 평가 전략입니다. 예:
'RO_RS','TO_LS','LOO'.- group_by_user: 평가 시 데이터를 사용자별로 그룹화할지 여부입니다.
- metrics_for_early_stop: 조기 종료를 모니터링할 지표입니다.
모델 하이퍼파라미터 (Model Hyperparameters)
모델마다 고유한 하이퍼파라미터가 있을 수 있지만, 일반적인 하이퍼파라미터는 다음과 같습니다:
- embedding_size: 사용자와 아이템 임베딩 벡터의 크기입니다.
- hidden_size: 신경망 모델의 은닉층 크기입니다.
- num_layers: MLP나 GNN과 같은 모델에서의 레이어 수입니다.
- dropout_prob: 드롭아웃을 위한 확률로, 정규화에 사용됩니다.
- activation: 활성화 함수입니다.
'relu','tanh','sigmoid'등으로 설정합니다.- num_heads: 어텐션 메커니즘을 사용하는 모델에서의 헤드 수입니다.
- layers: 심층 신경망 모델에서 각 레이어의 크기를 지정하는 리스트입니다.
- weight_initializer: 모델 가중치를 초기화하는 방법입니다.
- bias_initializer: 모델 편향을 초기화하는 방법입니다.
로깅 및 체크포인트 (Logging and Checkpointing)
- log_wandb: Weights & Biases에 실험을 로깅할지 여부입니다.
- wandb_project: Weights & Biases에서의 프로젝트 이름입니다.
- wandb_entity: Weights & Biases에서의 사용자 이름 또는 팀 이름입니다.
- log_interval: 로깅 메시지 사이의 이터레이션 수입니다.
- checkpoint_interval: 모델 체크포인트를 저장할 에포크 간격입니다.
- tensorboard: TensorBoard를 사용하여 로깅할지 여부입니다.
- log_file: 로그 파일의 경로입니다.
고급 설정 (Advanced Settings)
- max_seq_length: 입력 시퀀스의 최대 길이입니다. 순차 추천 모델에서 사용됩니다.
- mask_ratio:
BERT4Rec과 같은 모델에서 아이템을 마스킹할 비율입니다.- pretrain_path: 사전 학습된 모델 가중치의 경로입니다.
- use_pretrain: 사전 학습된 가중치를 사용할지 여부입니다.
- load_col: 데이터셋에서 로드할 컬럼의 목록입니다.
- unload_col: 데이터셋에서 제외할 컬럼의 목록입니다.
- repeatable: 데이터셋이 반복 가능한지 여부를 나타내는 불리언 값입니다. 순차 모델에서 사용됩니다.
- model_type: 모델 아키텍처의 유형입니다.
'general','sequential','context-aware'등으로 설정합니다.- fast_dev_run: 빠른 디버깅을 위한 불리언 값으로, 학습 및 평가를 한 번의 배치로 실행합니다.
- kfold: k-폴드 교차 검증을 위한 폴드 수입니다.
- save_dataset: 전처리된 데이터셋을 저장할지 여부입니다.
- load_saved_dataset: 이전에 저장된 데이터셋을 로드할지 여부입니다.
- benchmark_index: 벤치마크 데이터셋의 인덱스입니다.
- step: 순차 모델에서 슬라이딩 윈도의 스텝 크기입니다.
- neg_sampling: 부정적 샘플링 전략 구성입니다.
- metrics_weight: 전체 성능을 계산할 때 각 지표의 가중치입니다.
환경 설정 (Environment Settings)
- num_workers: 데이터 로딩에 사용할 서브프로세스 수입니다.
- pin_memory: 데이터 로딩 시 메모리를 고정할지 여부입니다.
- prefetch_factor: 미리 가져올 배치의 수입니다.
- persistent_workers: 에포크 사이에 워커를 유지할지 여부입니다.
- cudnn_benchmark: cuDNN 벤치마크를 활성화할지 여부입니다.
5. RecBole로 첫 추천 모델 만들기
기본 추천 모델 생성 단계별 가이드
- 설정 파일 생성:
from recbole.config import Config
config = {
# 데이터 관련 설정
'data_path': './data',
'dataset': 'custom_dataset',
# 모델 관련 설정
'model': 'BPR',
'embedding_size': 64,
'learning_rate': 0.001,
# 학습 관련 설정
'train_batch_size': 256,
'eval_batch_size': 256,
'epochs': 500,
'eval_step': 1,
# GPU 사용 설정
'device': 'cuda' if torch.cuda.is_available() else 'cpu'
}
config = Config(config)
- 모델 초기화 및 학습:
from recbole.data import create_dataset, data_preparation
from recbole.model.general_recommender import BPR
from recbole.trainer import Trainer
# 데이터셋 생성
dataset = create_dataset(config)
train_data, valid_data, test_data = data_preparation(config, dataset)
# 모델 초기화
model = BPR(config, train_data.dataset)
# 트레이너 초기화 및 학습
trainer = Trainer(config, model)
best_valid_score, best_valid_result = trainer.fit(
train_data, valid_data, saved=True, show_progress=True
)
- 모델 평가 및 예측:
# 테스트 데이터로 평가
test_result = trainer.evaluate(test_data)
print('Test Result:', test_result)
# 특정 사용자에 대한 추천 생성
uid_series = dataset.token2id(config['USER_ID_FIELD'], ['1', '2'])
topk_items = model.predict(uid_series, dataset.item_feat)
print('Recommended items:', dataset.id2token(config['ITEM_ID_FIELD'], topk_items.cpu()))
적절한 모델 선택
RecBole에서 제공하는 다양한 모델 중 사용 사례에 맞는 모델을 선택할 수 있습니다:
# 협업 필터링 모델 (BPR)
from recbole.model.general_recommender import BPR
# 신경망 기반 모델 (NCF)
from recbole.model.general_recommender import NCF
# 순차 추천 모델 (GRU4Rec)
from recbole.model.sequential_recommender import GRU4Rec
# 선택한 모델에 따른 설정 예시
model_config = {
'BPR': {
'embedding_size': 64,
'learning_rate': 0.001
},
'NCF': {
'embedding_size': 64,
'mlp_hidden_size': [128, 64, 32],
'learning_rate': 0.001
},
'GRU4Rec': {
'embedding_size': 64,
'hidden_size': 128,
'learning_rate': 0.001
}
}
# 선택한 모델 초기화
selected_model = 'BPR'
config.update(model_config[selected_model])
model = eval(selected_model)(config, train_data.dataset)
6. 고급 기능 및 맞춤 설정
RecBole을 이용한 하이퍼파라미터 튜닝
하이퍼파라미터 최적화는 모델의 성능을 향상시키는 핵심 과정입니다. RecBole은 다양한 하이퍼파라미터 튜닝 방법을 제공합니다:
from recbole.trainer import HyperTuning
from recbole.quick_start import objective_function
# 하이퍼파라미터 탐색 공간 정의
hyper_settings = {
'learning_rate': [0.0001, 0.001, 0.01],
'embedding_size': [32, 64, 128],
'n_layers': [1, 2, 3],
'dropout_prob': [0.0, 0.1, 0.2]
}
# HyperTuning 설정
hp = HyperTuning(
objective_function=objective_function,
params_file='model.yaml',
fixed_config_file_list=['dataset.yaml'],
hyper_config_dict=hyper_settings
)
# 그리드 서치 실행
hp.run()
print('최적의 하이퍼파라미터:', hp.best_params)
print('최고 성능:', hp.best_score)
모델 튜닝 도구 사용
그리드 서치 구현
def grid_search_tuning(config, dataset):
best_score = float('-inf')
best_params = None
# 그리드 서치를 위한 파라미터 조합 생성
param_combinations = [
{'learning_rate': lr, 'embedding_size': es}
for lr in [0.0001, 0.001, 0.01]
for es in [32, 64, 128]
]
for params in param_combinations:
# 현재 파라미터로 설정 업데이트
current_config = config.copy()
current_config.update(params)
# 모델 학습 및 평가
model = BPR(current_config, dataset)
trainer = Trainer(current_config, model)
_, valid_score = trainer.fit(dataset)
# 최고 성능 업데이트
if valid_score > best_score:
best_score = valid_score
best_params = params
return best_params, best_score
랜덤 서치 구현
import random
def random_search_tuning(config, dataset, n_trials=20):
best_score = float('-inf')
best_params = None
for _ in range(n_trials):
# 랜덤 파라미터 생성
params = {
'learning_rate': random.choice([0.0001, 0.001, 0.01]),
'embedding_size': random.choice([32, 64, 128]),
'dropout_prob': random.uniform(0.0, 0.5)
}
# 현재 파라미터로 모델 평가
current_config = config.copy()
current_config.update(params)
model = BPR(current_config, dataset)
trainer = Trainer(current_config, model)
_, valid_score = trainer.fit(dataset)
if valid_score > best_score:
best_score = valid_score
best_params = params
return best_params, best_score
평가를 위한 사용자 정의 메트릭 추가
RecBole은 사용자 정의 평가 메트릭을 추가할 수 있습니다:
from recbole.evaluator.metrics import metrics_dict
from recbole.evaluator.collector import DataStruct
class CustomMetric:
def __init__(self):
pass
def calculate_metric(self, dataobject: DataStruct):
# 예측값과 실제값 가져오기
pred = dataobject.get_pred().numpy()
true = dataobject.get_true().numpy()
# 메트릭 계산 로직 구현
score = custom_calculation(pred, true)
return score
# 메트릭 등록
metrics_dict['custom_metric'] = CustomMetric()
# 설정에 새로운 메트릭 추가
config['metrics'] = ['Recall', 'NDCG', 'custom_metric']
사용자 정의 손실 함수 구현
특정 요구사항에 맞는 커스텀 손실 함수를 구현할 수 있습니다:
import torch.nn as nn
class CustomLoss(nn.Module):
def __init__(self, weight=1.0):
super().__init__()
self.weight = weight
def forward(self, pred, true):
# 손실 함수 계산 로직
basic_loss = nn.BCEWithLogitsLoss()(pred, true)
custom_penalty = self.calculate_custom_penalty(pred)
return basic_loss + self.weight * custom_penalty
def calculate_custom_penalty(self, pred):
# 추가적인 페널티 항 계산
return torch.mean(torch.abs(pred))
# 모델에 커스텀 손실 함수 적용
class CustomBPR(BPR):
def __init__(self, config, dataset):
super().__init__(config, dataset)
self.loss = CustomLoss(weight=0.1)
def calculate_loss(self, interaction):
pred = self.forward(interaction)
true = interaction[self.LABEL]
return self.loss(pred, true)
7. 다양한 추천 모델 유형 다루기
순차 추천 모델
순차 추천은 사용자의 시간에 따른 행동 패턴을 고려합니다:
from recbole.model.sequential_recommender import GRU4Rec, BERT4Rec
# GRU4Rec 모델 설정
gru_config = {
'MAX_ITEM_LIST_LENGTH': 50, # 최대 시퀀스 길이
'hidden_size': 128,
'num_layers': 2,
'dropout_prob': 0.1
}
# BERT4Rec 모델 설정
bert_config = {
'mask_ratio': 0.2, # 마스킹 비율
'n_layers': 2,
'n_heads': 4,
'hidden_size': 256
}
# 순차 추천 모델 초기화 및 학습
config.update(gru_config)
sequential_model = GRU4Rec(config, dataset)
trainer = Trainer(config, sequential_model)
trainer.fit(train_data, valid_data)
컨텍스트 기반 및 지식 기반 모델
컨텍스트 특성 통합
컨텍스트 정보를 활용하여 추천의 정확도를 높일 수 있습니다:
from recbole.model.context_aware_recommender import FM, DeepFM, DCN
# 컨텍스트 특성 정의
context_config = {
'USER_ID_FIELD': 'user_id',
'ITEM_ID_FIELD': 'item_id',
'CONTEXT_FIELD': ['time', 'location', 'device'],
'continuous_feature_columns': ['user_age', 'item_price'],
'categorical_feature_columns': ['user_gender', 'item_category']
}
# DeepFM 모델 설정
deepfm_config = {
'embedding_size': 64,
'mlp_hidden_size': [128, 64, 32],
'dropout_prob': 0.1,
'learning_rate': 0.001
}
# 모델 초기화 및 학습
config.update({**context_config, **deepfm_config})
context_model = DeepFM(config, dataset)
trainer = Trainer(config, context_model)
trainer.fit(train_data, valid_data)
지식 그래프 기반 추천 활용
지식 그래프를 통해 아이템 간의 관계를 모델링할 수 있습니다:
from recbole.model.knowledge_aware_recommender import KGAT, KTUP
# 지식 그래프 데이터 준비
kg_config = {
'entity_field': ['user_id', 'item_id', 'category_id', 'brand_id'],
'relation_field': ['purchase', 'belong_to', 'produced_by'],
'kg_embedding_size': 64,
'layers': [64, 32, 16],
'aggregator_type': 'bi',
'reg_weight': 1e-5
}
# 지식 그래프 기반 모델 초기화
config.update(kg_config)
kg_model = KGAT(config, dataset)
# 학습 및 평가
trainer = Trainer(config, kg_model)
trainer.fit(train_data, valid_data)
8. 추천 모델 평가하기
평가 메트릭 이해하기
from recbole.evaluator.metrics import metrics_dict
from recbole.evaluator import Evaluator
# 다양한 평가 메트릭 설정
eval_config = {
'metrics': ['Precision', 'Recall', 'NDCG', 'MAP', 'MRR'],
'topk': [5, 10, 20],
'valid_metric': 'NDCG@10'
}
# 평가자 초기화
evaluator = Evaluator(config)
# 모델 평가 실행
result = evaluator.evaluate(model, test_data)
# 상세 평가 결과 분석
def analyze_results(result):
for metric in eval_config['metrics']:
for k in eval_config['topk']:
metric_key = f'{metric}@{k}'
print(f'{metric_key}: {result[metric_key]:.4f}')
analyze_results(result)
RecBole에서의 교차 검증 기법
from sklearn.model_selection import KFold
import numpy as np
class CrossValidator:
def __init__(self, config, dataset, n_splits=5):
self.config = config
self.dataset = dataset
self.n_splits = n_splits
self.kf = KFold(n_splits=n_splits, shuffle=True)
def run_cross_validation(self):
results = []
interaction_data = self.dataset.inter_feat.numpy()
for fold, (train_idx, test_idx) in enumerate(self.kf.split(interaction_data)):
print(f'Fold {fold + 1}/{self.n_splits}')
# 데이터 분할
train_data = self.dataset.copy()[train_idx]
test_data = self.dataset.copy()[test_idx]
# 모델 학습 및 평가
model = BPR(self.config, train_data)
trainer = Trainer(self.config, model)
trainer.fit(train_data, valid_data=test_data)
# 결과 저장
result = trainer.evaluate(test_data)
results.append(result)
# 평균 성능 계산
mean_results = {
metric: np.mean([r[metric] for r in results])
for metric in results[0].keys()
}
return mean_results
# 교차 검증 실행
cv = CrossValidator(config, dataset)
cv_results = cv.run_cross_validation()
모델 성능 시각화
import matplotlib.pyplot as plt
import seaborn as sns
def visualize_training_progress(trainer):
# 학습 곡선 시각화
plt.figure(figsize=(12, 4))
# 손실 함수 그래프
plt.subplot(1, 2, 1)
plt.plot(trainer.train_loss_dict['batch_loss'])
plt.title('Training Loss')
plt.xlabel('Batch')
plt.ylabel('Loss')
# 평가 메트릭 그래프
plt.subplot(1, 2, 2)
for metric in trainer.eval_results:
plt.plot(trainer.eval_results[metric], label=metric)
plt.title('Evaluation Metrics')
plt.xlabel('Epoch')
plt.ylabel('Score')
plt.legend()
plt.tight_layout()
plt.show()
# 모델 간 성능 비교 시각화
def compare_models(model_results):
metrics = ['Precision@10', 'Recall@10', 'NDCG@10']
models = list(model_results.keys())
plt.figure(figsize=(10, 6))
x = np.arange(len(metrics))
width = 0.2
for i, model in enumerate(models):
plt.bar(x + i*width,
[model_results[model][m] for m in metrics],
width,
label=model)
plt.xlabel('Metrics')
plt.ylabel('Score')
plt.title('Model Comparison')
plt.xticks(x + width, metrics)
plt.legend()
plt.show()
9. RecBole 추천 시스템 배포하기
훈련된 모델 내보내기 및 저장하기
import torch
import json
import os
class ModelExporter:
def __init__(self, model, config, dataset):
self.model = model
self.config = config
self.dataset = dataset
def save_model(self, path):
# 모델 가중치 저장
torch.save(self.model.state_dict(), f'{path}/model.pth')
# 모델 설정 저장
config_dict = self.config._config_dict
with open(f'{path}/config.json', 'w') as f:
json.dump(config_dict, f, indent=4)
# 특성 매핑 정보 저장
mapping_dict = {
'user_token2id': self.dataset.field2token_id['user_id'],
'item_token2id': self.dataset.field2token_id['item_id']
}
with open(f'{path}/mapping.json', 'w') as f:
json.dump(mapping_dict, f, indent=4)
@staticmethod
def load_model(path, model_class):
# 설정 로드
with open(f'{path}/config.json', 'r') as f:
config_dict = json.load(f)
config = Config(config_dict)
# 매핑 정보 로드
with open(f'{path}/mapping.json', 'r') as f:
mapping_dict = json.load(f)
# 모델 초기화 및 가중치 로드
model = model_class(config, None)
model.load_state_dict(torch.load(f'{path}/model.pth'))
return model, config, mapping_dict
# 모델 저장 예제
exporter = ModelExporter(trained_model, config, dataset)
exporter.save_model('saved_models/bpr_model')
Flask 또는 FastAPI를 이용한 모델 배포
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import torch
import numpy as np
app = FastAPI()
class RecommendRequest(BaseModel):
user_id: str
n_items: int = 10
class ModelService:
def __init__(self, model_path):
# 저장된 모델 로드
self.model, self.config, self.mapping = ModelExporter.load_model(
model_path, BPR
)
self.model.eval()
def get_recommendations(self, user_id: str, n_items: int) -> list:
try:
# 사용자 ID를 모델 입력 형식으로 변환
user_idx = self.mapping['user_token2id'][user_id]
# 추천 생성
with torch.no_grad():
scores = self.model.full_sort_predict(user_idx)
topk_items = torch.topk(scores, n_items)[1].tolist()
# 아이템 ID로 변환
id2token = {v: k for k, v in self.mapping['item_token2id'].items()}
recommendations = [id2token[idx] for idx in topk_items]
return recommendations
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
# 모델 서비스 초기화
model_service = ModelService('saved_models/bpr_model')
@app.post("/recommend")
async def get_recommendations(request: RecommendRequest):
recommendations = model_service.get_recommendations(
request.user_id, request.n_items
)
return {"recommendations": recommendations}
웹 애플리케이션과의 추천 시스템 통합
import requests
from typing import List, Dict
class RecommenderClient:
def __init__(self, api_url: str):
self.api_url = api_url
def get_recommendations(self, user_id: str, n_items: int = 10) -> List[str]:
try:
response = requests.post(
f"{self.api_url}/recommend",
json={"user_id": user_id, "n_items": n_items}
)
response.raise_for_status()
return response.json()["recommendations"]
except requests.exceptions.RequestException as e:
print(f"추천 요청 실패: {e}")
return []
# React 컴포넌트에서 사용 예제
```jsx
import React, { useState, useEffect } from 'react';
const RecommendationList = ({ userId }) => {
const [recommendations, setRecommendations] = useState([]);
const [loading, setLoading] = useState(false);
useEffect(() => {
const fetchRecommendations = async () => {
setLoading(true);
try {
const response = await fetch('/api/recommend', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ user_id: userId, n_items: 10 }),
});
const data = await response.json();
setRecommendations(data.recommendations);
} catch (error) {
console.error('추천 로드 실패:', error);
} finally {
setLoading(false);
}
};
fetchRecommendations();
}, [userId]);
return (
<div>
<h2>추천 아이템</h2>
{loading ? (
<p>로딩 중...</p>
) : (
<ul>
{recommendations.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
)}
</div>
);
};
운영 환경에서 모델 모니터링 및 업데이트
import logging
from datetime import datetime
import pandas as pd
from prometheus_client import Counter, Histogram
class ModelMonitor:
def __init__(self):
# 메트릭 초기화
self.recommendation_count = Counter(
'recommendations_total',
'Total number of recommendations made'
)
self.recommendation_latency = Histogram(
'recommendation_latency_seconds',
'Recommendation generation latency'
)
self.setup_logging()
def setup_logging(self):
logging.basicConfig(
filename=f'logs/recommender_{datetime.now():%Y%m%d}.log',
level=logging.INFO,
format='%(asctime)s %(levelname)s: %(message)s'
)
def log_recommendation(self, user_id, recommendations, latency):
self.recommendation_count.inc()
self.recommendation_latency.observe(latency)
logging.info(
f"User: {user_id}, "
f"Recommendations: {recommendations}, "
f"Latency: {latency:.3f}s"
)
def analyze_performance(self, log_file):
# 로그 분석
df = pd.read_csv(log_file)
# 성능 메트릭 계산
metrics = {
'avg_latency': df['latency'].mean(),
'p95_latency': df['latency'].quantile(0.95),
'success_rate': (df['status'] == 'success').mean(),
'total_requests': len(df)
}
return metrics
# 모니터링 통합
class MonitoredModelService(ModelService):
def __init__(self, model_path):
super().__init__(model_path)
self.monitor = ModelMonitor()
def get_recommendations(self, user_id: str, n_items: int) -> list:
start_time = datetime.now()
try:
recommendations = super().get_recommendations(user_id, n_items)
latency = (datetime.now() - start_time).total_seconds()
self.monitor.log_recommendation(user_id, recommendations, latency)
return recommendations
except Exception as e:
logging.error(f"추천 생성 실패: {str(e)}")
raise
10. RecBole에서 자주 발생하는 문제 해결
설치 관련 오류 해결
import sys
import torch
import recbole
def check_environment():
"""시스템 환경 진단 함수"""
environment_info = {
'Python Version': sys.version,
'PyTorch Version': torch.__version__,
'CUDA Available': torch.cuda.is_available(),
'CUDA Version': torch.version.cuda if torch.cuda.is_available() else 'Not Available',
'RecBole Version': recbole.__version__
}
# CUDA 디바이스 정보
if torch.cuda.is_available():
for i in range(torch.cuda.device_count()):
device = torch.cuda.get_device_properties(i)
environment_info[f'GPU {i}'] = f'{device.name}, {device.total_memory/1024**3:.1f}GB'
return environment_info
def diagnose_installation():
"""설치 문제 진단"""
try:
# 기본 모듈 임포트 테스트
import recbole.data
import recbole.model
import recbole.trainer
print("✅ 기본 모듈 임포트 성공")
# 데이터셋 로드 테스트
from recbole.quick_start import run_recbole
config = {'dataset': 'ml-100k', 'data_path': './dataset/'}
try:
dataset, model, trainer, config = run_recbole('BPR', config)
print("✅ 샘플 데이터셋 로드 성공")
except Exception as e:
print(f"❌ 데이터셋 로드 실패: {str(e)}")
except ImportError as e:
print(f"❌ 모듈 임포트 실패: {str(e)}")
print("💡 해결 방법: pip install --upgrade recbole torch")
# 설치 문제 해결을 위한 유틸리티 클래스
class InstallationTroubleshooter:
@staticmethod
def fix_cuda_issues():
"""CUDA 관련 문제 해결"""
if not torch.cuda.is_available():
print("CUDA를 사용할 수 없습니다. 다음을 확인하세요:")
print("1. NVIDIA GPU가 설치되어 있는지")
print("2. CUDA 드라이버가 설치되어 있는지")
print("3. PyTorch가 CUDA 버전으로 설치되어 있는지")
# PyTorch CUDA 재설치 명령어 생성
cuda_version = '11.8' # 사용자 환경에 맞게 수정
print(f"\n재설치 명령어:")
print(f"pip install torch --index-url https://download.pytorch.org/whl/cu{cuda_version}")
데이터 관련 문제 해결
import pandas as pd
import numpy as np
from recbole.data.dataset import Dataset
class DataTroubleshooter:
def __init__(self, dataset):
self.dataset = dataset
def analyze_data_quality(self):
"""데이터 품질 분석"""
quality_report = {
'missing_values': self._check_missing_values(),
'duplicates': self._check_duplicates(),
'data_distribution': self._analyze_distribution(),
'interaction_patterns': self._analyze_interactions()
}
return quality_report
def _check_missing_values(self):
"""결측치 검사"""
missing_stats = {}
for field in self.dataset.field2type:
field_data = self.dataset.field2tokens[field]
if isinstance(field_data, np.ndarray):
missing_count = np.isnan(field_data).sum()
else:
missing_count = field_data.isnull().sum()
missing_stats[field] = missing_count
return missing_stats
def _check_duplicates(self):
"""중복 데이터 검사"""
interaction_data = self.dataset.inter_feat.numpy()
unique_rows = np.unique(interaction_data, axis=0)
return {
'total_interactions': len(interaction_data),
'unique_interactions': len(unique_rows),
'duplicate_ratio': 1 - len(unique_rows)/len(interaction_data)
}
def fix_data_issues(self):
"""데이터 문제 자동 수정"""
# 결측치 처리
for field in self.dataset.field2type:
if field in self.dataset.field2tokens:
field_data = self.dataset.field2tokens[field]
if isinstance(field_data, np.ndarray):
# 수치형 데이터는 평균값으로 대체
field_data[np.isnan(field_data)] = np.nanmean(field_data)
else:
# 범주형 데이터는 최빈값으로 대체
field_data.fillna(field_data.mode()[0], inplace=True)
# 중복 제거
self.dataset.inter_feat = pd.DataFrame(
np.unique(self.dataset.inter_feat.numpy(), axis=0)
)
모델 수렴 문제 처리
class ConvergenceTroubleshooter:
def __init__(self, model, trainer):
self.model = model
self.trainer = trainer
self.convergence_history = []
def monitor_training(self, epoch, loss):
"""학습 과정 모니터링"""
self.convergence_history.append({
'epoch': epoch,
'loss': loss
})
# 수렴 문제 감지
if self._detect_convergence_issues():
self._adjust_training_parameters()
def _detect_convergence_issues(self):
"""수렴 문제 감지"""
if len(self.convergence_history) < 5:
return False
recent_losses = [h['loss'] for h in self.convergence_history[-5:]]
# 발산 감지
if np.mean(recent_losses) > 1e5:
return 'divergence'
# 느린 수렴 감지
loss_change = np.abs(np.diff(recent_losses))
if np.mean(loss_change) < 1e-6:
return 'slow_convergence'
return False
def _adjust_training_parameters(self, issue_type):
"""학습 파라미터 자동 조정"""
if issue_type == 'divergence':
# 학습률 감소
self.trainer.learning_rate *= 0.5
print(f"학습률을 {self.trainer.learning_rate}로 조정했습니다.")
elif issue_type == 'slow_convergence':
# 배치 크기 증가
self.trainer.batch_size *= 2
print(f"배치 크기를 {self.trainer.batch_size}로 증가했습니다.")
성능 및 메모리 사용 디버깅
import psutil
import gc
import torch.autograd.profiler as profiler
class PerformanceDebugger:
def __init__(self):
self.memory_logs = []
def monitor_memory_usage(self):
"""메모리 사용량 모니터링"""
process = psutil.Process()
memory_info = process.memory_info()
self.memory_logs.append({
'timestamp': datetime.now(),
'rss': memory_info.rss / 1024**2, # MB
'vms': memory_info.vms / 1024**2, # MB
'gpu_memory': torch.cuda.memory_allocated() / 1024**2 if torch.cuda.is_available() else 0
})
def optimize_memory_usage(self, model, dataset):
"""메모리 사용량 최적화"""
# 불필요한 메모리 해제
gc.collect()
torch.cuda.empty_cache()
# 데이터 로더 최적화
dataset.set_prefetch_strategy('dynamic')
# 모델 최적화
for param in model.parameters():
if param.grad is not None:
param.grad.detach_()
param.grad.zero_()
def profile_model_performance(self, model, sample_input):
"""모델 성능 프로파일링"""
with profiler.profile(use_cuda=torch.cuda.is_available()) as prof:
with profiler.record_function("model_inference"):
model(sample_input)
print(prof.key_averages().table(sort_by="cpu_time_total"))
11. RecBole 확장: 사용자 정의 모델 개발
RecBole의 모델 개발 프레임워크 소개
from recbole.model.abstract_recommender import GeneralRecommender
import torch
import torch.nn as nn
import torch.nn.functional as F
class CustomRecommenderBase(GeneralRecommender):
"""사용자 정의 추천 모델을 위한 기본 클래스"""
def __init__(self, config, dataset):
super(CustomRecommenderBase, self).__init__(config, dataset)
# 기본 설정
self.embedding_size = config['embedding_size']
self.n_users = dataset.user_num
self.n_items = dataset.item_num
# 임베딩 레이어 초기화
self.user_embedding = nn.Embedding(self.n_users, self.embedding_size)
self.item_embedding = nn.Embedding(self.n_items, self.embedding_size)
# 가중치 초기화
self.apply(self._init_weights)
def _init_weights(self, module):
"""가중치 초기화 메서드"""
if isinstance(module, nn.Embedding):
nn.init.xavier_normal_(module.weight)
def forward(self, user, item):
raise NotImplementedError
def calculate_loss(self, interaction):
raise NotImplementedError
def predict(self, interaction):
raise NotImplementedError
사용자 정의 추천 모델 생성 및 테스트
class HybridAttentionRecommender(CustomRecommenderBase):
"""하이브리드 어텐션 기반 추천 모델"""
def __init__(self, config, dataset):
super(HybridAttentionRecommender, self).__init__(config, dataset)
# 추가 설정
self.n_heads = config['n_heads']
self.dropout = config['dropout']
# 어텐션 레이어
self.attention = nn.MultiheadAttention(
self.embedding_size,
self.n_heads,
dropout=self.dropout
)
# MLP 레이어
self.mlp = nn.Sequential(
nn.Linear(self.embedding_size * 2, self.embedding_size),
nn.ReLU(),
nn.Dropout(self.dropout),
nn.Linear(self.embedding_size, 1)
)
def forward(self, user, item):
# 사용자와 아이템 임베딩
user_emb = self.user_embedding(user)
item_emb = self.item_embedding(item)
# 어텐션 적용
attn_output, _ = self.attention(
user_emb.unsqueeze(0),
item_emb.unsqueeze(0),
item_emb.unsqueeze(0)
)
# 특성 결합
combined = torch.cat([
attn_output.squeeze(0),
item_emb
], dim=1)
# 최종 예측
return self.mlp(combined)
def calculate_loss(self, interaction):
user = interaction[self.USER_ID]
item = interaction[self.ITEM_ID]
label = interaction[self.LABEL]
output = self.forward(user, item)
return F.binary_cross_entropy_with_logits(
output.view(-1),
label.float()
)
def predict(self, interaction):
user = interaction[self.USER_ID]
item = interaction[self.ITEM_ID]
return self.forward(user, item).sigmoid()
# 모델 테스트 유틸리티
class ModelTester:
def __init__(self, config, dataset):
self.config = config
self.dataset = dataset
def test_model_initialization(self, model_class):
"""모델 초기화 테스트"""
try:
model = model_class(self.config, self.dataset)
print("✅ 모델 초기화 성공")
return model
except Exception as e:
print(f"❌ 모델 초기화 실패: {str(e)}")
return None
def test_forward_pass(self, model):
"""순전파 테스트"""
try:
# 샘플 데이터 생성
batch_size = 32
user = torch.randint(0, self.dataset.user_num, (batch_size,))
item = torch.randint(0, self.dataset.item_num, (batch_size,))
# 순전파 실행
output = model(user, item)
print(f"✅ 순전파 성공: 출력 형태 {output.shape}")
return True
except Exception as e:
print(f"❌ 순전파 실패: {str(e)}")
return False
RecBole과 PyTorch를 활용한 고급 커스터마이징
class CustomLossFunction(nn.Module):
"""사용자 정의 손실 함수"""
def __init__(self, alpha=1.0, beta=0.5):
super(CustomLossFunction, self).__init__()
self.alpha = alpha
self.beta = beta
def forward(self, pred, true, user_emb, item_emb):
# 기본 예측 손실
pred_loss = F.binary_cross_entropy_with_logits(
pred.view(-1),
true.float()
)
# 정규화 항
reg_loss = self.alpha * (
torch.norm(user_emb) +
torch.norm(item_emb)
)
# 대조 손실
contrast_loss = self.beta * self.contrastive_loss(
user_emb,
item_emb
)
return pred_loss + reg_loss + contrast_loss
@staticmethod
def contrastive_loss(user_emb, item_emb):
"""대조 학습 손실"""
sim_matrix = torch.mm(user_emb, item_emb.t())
positive_pairs = torch.diag(sim_matrix)
negative_pairs = sim_matrix.view(-1)
return -torch.log(
torch.exp(positive_pairs) /
torch.exp(negative_pairs).sum()
).mean()
class CustomTrainingCallback:
"""사용자 정의 학습 콜백"""
def __init__(self):
self.best_metric = float('-inf')
self.patience = 0
def on_epoch_end(self, trainer):
"""에폭 종료 시 호출되는 콜백"""
current_metric = trainer.eval_collector.collect()['NDCG@10']
# 성능 향상 체크
if current_metric > self.best_metric:
self.best_metric = current_metric
self.patience = 0
# 모델 저장
trainer.save_checkpoint('best_model.pth')
else:
self.patience += 1
# 조기 종료 체크
if self.patience >= trainer.config['early_stopping_patience']:
trainer.stop_training = True
12. RecBole로 추천 시스템 최적화 사례
모델 선택 전략
class ModelSelector:
"""최적의 모델 선택을 위한 유틸리티"""
def __init__(self, dataset, config):
self.dataset = dataset
self.config = config
self.results = {}
def evaluate_models(self, model_list):
"""여러 모델 평가 및 비교"""
for model_class in model_list:
try:
# 모델 초기화 및 학습
model = model_class(self.config, self.dataset)
trainer = Trainer(self.config, model)
best_valid_score, valid_result = trainer.fit(
self.dataset,
valid_data=None,
show_progress=True
)
# 테스트 결과 저장
test_result = trainer.evaluate(
self.dataset.build_test_dataset()
)
self.results[model_class.__name__] = {
'valid_score': best_valid_score,
'test_results': test_result,
'model_complexity': self._calculate_complexity(model)
}
except Exception as e:
print(f"{model_class.__name__} 평가 실패: {str(e)}")
def _calculate_complexity(self, model):
"""모델 복잡도 계산"""
num_params = sum(
p.numel()
for p in model.parameters()
)
return {
'num_parameters': num_params,
'memory_size': num_params * 4 / 1024 / 1024 # MB
}
def get_recommendation(self, criteria=['accuracy', 'efficiency']):
"""최적 모델 추천"""
scores = {}
for model_name, results in self.results.items():
# 정확도 점수
accuracy_score = results['test_results']['NDCG@10']
# 효율성 점수 (파라미터 수의 역수)
efficiency_score = 1 / np.log(
results['model_complexity']['num_parameters']
)
# 종합 점수 계산
scores[model_name] = {
'accuracy': accuracy_score,
'efficiency': efficiency_score,
'overall': np.mean([accuracy_score, efficiency_score])
}
return scores
특성 엔지니어링 기법
class FeatureEngineer:
"""특성 엔지니어링 도구"""
def __init__(self, dataset):
self.dataset = dataset
self.feature_importance = {}
def create_temporal_features(self, timestamp_field):
"""시간적 특성 생성"""
timestamps = self.dataset.inter_feat[timestamp_field].numpy()
datetime_array = pd.to_datetime(timestamps, unit='s')
# 시간적 특성 추출
temporal_features = {
'hour': datetime_array.hour,
'day_of_week': datetime_array.dayofweek,
'month': datetime_array.month,
'is_weekend': datetime_array.dayofweek >= 5
}
return temporal_features
def create_interaction_features(self):
"""상호작용 기반 특성 생성"""
interactions = self.dataset.inter_feat
# 사용자별 통계
user_stats = {
'user_interaction_count': interactions.groupby('user_id').size(),
'user_avg_rating': interactions.groupby('user_id')['rating'].mean(),
'user_rating_std': interactions.groupby('user_id')['rating'].std()
}
# 아이템별 통계
item_stats = {
'item_interaction_count': interactions.groupby('item_id').size(),
'item_avg_rating': interactions.groupby('item_id')['rating'].mean(),
'item_rating_std': interactions.groupby('item_id')['rating'].std()
}
return user_stats, item_stats
사전 학습된 임베딩을 이용한 성능 향상
class PretrainedEmbeddingEnhancer:
"""사전 학습된 임베딩을 활용한 성능 향상"""
def __init__(self, model, config):
self.model = model
self.config = config
def load_pretrained_embeddings(self, embedding_path):
"""사전 학습된 임베딩 로드"""
pretrained = torch.load(embedding_path)
# 임베딩 크기 확인 및 조정
if pretrained['embedding_dim'] != self.config['embedding_size']:
pretrained_embeddings = self._resize_embeddings(
pretrained['embeddings'],
self.config['embedding_size']
)
else:
pretrained_embeddings = pretrained['embeddings']
return pretrained_embeddings
def initialize_with_pretrained(self, user_embeddings, item_embeddings):
"""사전 학습된 임베딩으로 초기화"""
# 사용자 임베딩 초기화
if hasattr(self.model, 'user_embedding'):
self.model.user_embedding.weight.data.copy_(user_embeddings)
# 아이템 임베딩 초기화
if hasattr(self.model, 'item_embedding'):
self.model.item_embedding.weight.data.copy_(item_embeddings)
지식 그래프 및 외부 데이터 소스 활용
class KnowledgeGraphEnhancer:
"""지식 그래프 통합 도구"""
def __init__(self, dataset):
self.dataset = dataset
self.kg_graph = None
def build_knowledge_graph(self, entity_data, relation_data):
"""지식 그래프 구축"""
import networkx as nx
# 그래프 초기화
self.kg_graph = nx.DiGraph()
# 엔티티 추가
for entity in entity_data:
self.kg_graph.add_node(
entity['id'],
type=entity['type'],
attributes=entity['attributes']
)
# 관계 추가
for relation in relation_data:
self.kg_graph.add_edge(
relation['head'],
relation['tail'],
type=relation['type'],
weight=relation.get('weight', 1.0)
)
def generate_graph_features(self):
"""그래프 기반 특성 생성"""
if self.kg_graph is None:
raise ValueError("지식 그래프가 초기화되지 않았습니다.")
# 중심성 계산
centrality_features = {
'degree': nx.degree_centrality(self.kg_graph),
'betweenness': nx.betweenness_centrality(self.kg_graph),
'pagerank': nx.pagerank(self.kg_graph)
}
return centrality_features
이것으로 RecBole 추천 시스템 구축을 위한 종합 가이드를 마무리합니다. 이 가이드를 통해 RecBole을 활용한 추천 시스템 개발의 전체 과정을 상세히 살펴보았습니다.