-
[scikit-surprise] SVD Model 알아보기 ( Singular Value Decomposition )AI-ML 2024. 5. 7. 05:37728x90반응형
- 목차
키워드.
- scikit-surprise
- Matrix Factorization
- SVD
- Latent Space
함께 보면 좋은 글.
https://westlife0615.tistory.com/851
들어가며.
이번 글에서는 scikit-surprise 의 SVD 모델에 대해서 살펴보려고 합니다.
SVD 는 Singular Value Decomposition 의 약자이며, 하나의 행렬을 분해할 수 있는 수학적인 기법입니다.
사실상 추천 시스템에서 사용하는 SVD 는 수학적인 정의에 100% 상응하지는 않습니다.
그래서 SVD 의 수학적인 정의에 집착하기 보다는 머신러닝에서 사용하는 하나의 Matrix Factorization 기법이라고 생각하시면 좋을 것 같습니다.
Matrix Factorization.
추천시스템에서 Matrix Factorization 에 대해서 간단히 살펴보겠습니다.
하나의 거대한 Matrix 가 존재할 때, 이 Matrix 를 2개의 Matrix 로 분해할 수 있습니다.
보통 Collaborative Filtering 분야에서 User, Item, Rating 의 값들로 표현되는 Matrix 를 사용하는데요.
아래와 같은 형태의 데이터들이 사용됩니다.
왼쪽의 사진은 user - item - rating 으로 표현되는 데이터셋이구요.
오른쪽 사진은 user, item 을 두 축으로 삼는 Pivot Table 입니다.
Matrix Factorization 은 user - item 을 두 축으로 삼는 Pivot Table 에서 수행됩니다.
Matrix Factorization 의 결과는 User-Item Matrix 을 두개의 Matrix 로 분해하는 것이고,
하나의 User Latent Matrix, Item Latent Matrix 로 분해되게 됩니다.
이는 수식으로 아래와 같이 표현되게 됩니다.
$$ R = U \cdot I $$
$$ 또는 R_{ij} = \sum U_{i} \cdot I^{T}_{j} $$
(R, U, I 는 각각 Ratings, Users, Items 에 관한 Matrix 입니다.)
Matrix Factorization 의 결과로서 아래와 같은 2개의 Matrix 로 분해가 되구요.
분해 방법에 대해서는 이어지는 글에서 다루어보도록 하겠습니다.
Latent Space.
Matrix Factorization 에서 중요한 키워드는 "Latent Space" 입니다.
Latent Space 의 의미가 "잠재적 공간" 이라는 뜻인데요. 이 의미를 이해하는 것이 중요합니다.
User - Item 으로 구성된 Matrix 는 N x M 행렬이라고 가정하겠습니다.
그리고 이 N x M 행렬을 N x K 행렬과 K x M 인 행렬로 분해하였다고 가정하겠습니다.
$ R_{N \times M} = U_{N \times K} \cdot I_{K \times M} $
이때 User Matrix 와 Item Matrix 는 K 라는 Dimension 을 가지게 되는데요.
K Dimensionality 가 User 와 Item 에 대한 잠재적 공간의 크기 또는 차원을 제공합니다.
이를 다른 관점에서 표현하면 user1, user2, ..., userN 은 K 개의 특징을 가지게 된 것이고,
item1, item2, ..., itemM 에 해당하는 상품들 또한 K 개의 특징을 가지게 됩니다.
즉 아래 이미지와 같이 구성된 User - Item Matrix 가 존재할 때,
K 가 6 개인 User Latent Matrix 와 Item Latent Matrix 를 구할 수 있습니다. (K 를 6으로 설정할 때의 예시)
이는 다음과 같이 해석할 수 있습니다.
K 개의 알 수 없는 잠재적인 Dimension 들이 추가되었지만, 이는 마치 아래와 같은 특징처럼 여겨질 수 있다는 점입니다.
즉, 의도한건 아니지만 어떠한 잠재적인 기능을 수행하는 K 개의 Feature 들로 새로운 Matrix 가 생성되었고
이를 Matrix Factorization 이라고 부릅니다.
SVD 는 어떤 방식으로 학습될까 ?
SVD 알고리즘은 지도학습의 방식으로 학습을 진행합니다.
SVD 의 입력 데이터는 Ratings Dataset 과 같은 모습이구요.
< 입력 데이터 예시 >
Output 결과는 아래의 이미지와 같은 Item Latent Matrix, User Latent Matrix 로 분해된 결과입니다.
즉, 요약하자면 Rating Dataset -> SVD -> User & Item Latent Matrix 의 과정을 수행합니다.
이를 간단하게 파이썬 코드로 구현해보도록 하겠습니다.
from surprise import Dataset import pandas as pd import numpy as np import statistics mv_dataset = Dataset.load_builtin("ml-100k") raw_dataset = mv_dataset.raw_ratings dataset = pd.DataFrame(raw_dataset, columns=["user", "item", "rating", "timestamp"]) """ user item rating timestamp 0 196 242 3.0 881250949 1 186 302 3.0 891717742 2 22 377 1.0 878887116 3 244 51 2.0 880606923 4 166 346 1.0 886397596 ... """ n_users = len(dataset["user"].unique()) n_items = len(dataset["item"].unique()) n_factors = 500 n_epochs = 100 learning_rate = 0.001 """ 모든 user 의 수는 943, item 의 수는 1684 n_users : 943 n_items : 1682 n_factors : 500 """ user_latent_matrix = np.random.randn(n_users, n_factors) item_latent_matrix = np.random.randn(n_items, n_factors) """ user_latent_matrix.shape : (943, 500) item_latent_matrix.shape : (1682, 500) """ # Training Dataset 의 user id, item id 는 실제 사용하는 id 값이며, # 이들을 0 부터 시작하는 Index 에 매핑시키기 위한 4개의 Dict # 예를 들어, user id '101' -> 0, '1001' -> 1 과 같이 Mapping 합니다. user_mapper_from_raw_to_index = dict(zip(sorted(dataset["user"].unique()), list(range(n_users)))) item_mapper_from_raw_to_index = dict(zip(sorted(dataset["item"].unique()), list(range(n_items)))) user_mapper_from_index_to_raw = dict(zip(list(range(n_users)), sorted(dataset["user"].unique()))) item_mapper_from_index_to_raw = dict(zip(list(range(n_items)), sorted(dataset["item"].unique()))) for epoch in range(n_epochs): errors = [] for _, row in dataset.iterrows(): user_raw_id = row["user"] item_raw_id = row["item"] rating = row["rating"] user_index = user_mapper_from_raw_to_index[user_raw_id] item_index = item_mapper_from_raw_to_index[item_raw_id] # User Latent Matrix 에서 특정 user 의 vector 를 조회 user_latent_vector = user_latent_matrix[user_index, :] item_latent_vector = item_latent_matrix[item_index, :] predicted_rating = np.dot(user_latent_vector, item_latent_vector) error = (rating - predicted_rating) user_latent_matrix[user_index, :] = user_latent_matrix[user_index, :] + learning_rate * error item_latent_matrix[item_index, :] = item_latent_matrix[item_index, :] + learning_rate * error errors.append(abs(error)) print(f"eooch : {epoch}, error : {statistics.mean(errors)}")
eooch : 0, error : 18.47654656785462 eooch : 1, error : 18.417382199915714 eooch : 2, error : 18.419961094404563 eooch : 3, error : 18.424237719888783 eooch : 4, error : 18.428607881834083 eooch : 5, error : 18.432241449984453 eooch : 6, error : 18.435334219476438 eooch : 7, error : 18.437911053078878 eooch : 8, error : 18.44022820551849 eooch : 9, error : 18.44231429394892 eooch : 10, error : 18.444225599985696 eooch : 11, error : 18.44595749464332
최대한 주석을 작성하긴 하였는데, 혹시나 이해가 어려우시거나 문제가 있다면 피드백주시면 좋을 것 같습니다.
SVD 알고리즘의 핵심은 지도학습의 하나로써 User, Item 의 Latent Matrix 를 튜닝시키는 과정입니다.
아래의 코드예시처럼 User 와 Item 의 Latent Vector 들을 실제 Rating 값에 가깝게 변화시키면서
온전한 Latent Matrix 들을 완성합니다.
predicted_rating = np.dot(user_latent_vector, item_latent_vector) error = (rating - predicted_rating)
이렇게 Latent Matrix 들이 완성되게 된다면, 사용자가 평가하지 않은 상품 혹은 한번도 본적이 없는 상품에 대해서 얼마의 선호도를 가지는지를 예측할 수 있습니다.
예를 들어, "k" User 는 "n" Item 에 대해서 평가를 한적이 없습니다.
하지만 완성된 User Latent Matrix 의 "k" Vector 와 Item Latent Matrix 의 "n" Vector 를 dot Product 한 결과를 "k" User 의 "n" Item 에 대한 평가로써 예측할 수 있습니다.
마치며.
이번 글에서는 SVD 의 컨셉에 대해서 알아보았는데요.
이어지는 글에서 SVD 의 구체적인 사용법에 대해서 알아보도록 하겠습니다.
https://westlife0615.tistory.com/858
반응형'AI-ML' 카테고리의 다른 글
[scikit-surprise] Dataset 이해하기 (0) 2024.05.14 [seaborn] Violin Plot 알아보기 (0) 2024.05.07 [seaborn] Count Plot 그리기 ( sns.countplot, sns.catplot ) (0) 2024.05.06 [scikit-learn] KFold 알아보기 ( cross validation ) (1) 2024.04.28 [torchvision] datasets.MNIST 데이터 내려받기 (0) 2024.04.24