一、FunkSVD算法原理
FunkSVD 算法是一種基於矩陣分解模型的協同過濾算法,其核心思想是基於用戶和物品之間的關聯關係,將用戶-物品矩陣分解為用戶和物品兩個矩陣的乘積,再通過矩陣乘法計算出每個用戶對每個物品的評分得分,從而實現推薦系統的效果。
假設有 m 個用戶 u1, u2, … , um,n 個物品 i1, i2, … , in,用戶-物品矩陣為 R(mxn),其中 R[i][j] 表示用戶 i 對物品 j 的評分得分,分值為 1~5 分。FunkSVD 算法採用矩陣分解模型,通過分解用戶-物品矩陣,得到兩個分解矩陣:用戶特徵矩陣 P(mxr) 和物品特徵矩陣 Q(nxr),其中 r 為低維特徵向量的個數,P 矩陣表示用戶對各個特徵的喜好程度,Q 矩陣表示各個物品在不同的特徵上的得分表現。則用戶 i 對物品 j 的預測得分可以通過式子計算:R[i][j] ≈ P[i,:]Q[j,:].T
二、FunkSVD 算法優劣性分析
FunkSVD 算法是一種有效的協同過濾推薦算法,具有如下優劣性:
1、優點:
(1)可用於處理高維、稀疏的用戶數據,能夠處理較大規模的用戶-物品評分矩陣,適用於大數據場景;
(2)和其他算法相比,FunkSVD 算法在準確性上有一定優勢,可以提供較為精確的推薦結果;
2、缺點:
(1)需要對矩陣分解中的超參數進行調整,才能夠獲得最佳的分解效果;
(2)FunkSVD 算法在處理冷啟動問題(新物品和新用戶)時,表現較差。
三、基於 Python 實現 FunkSVD 算法
import pandas as pd
import numpy as np
class FunkSVD:
def __init__(self, learning_rate=0.01, reg_rate=0.1, n_epochs=100, n_factors=15, verbose=True):
"""
FunkSVD算法的初始化方法
:param learning_rate: 學習率
:param reg_rate: 正則化係數
:param n_epochs: 迭代次數
:param n_factors: 隱特徵向量維度
:param verbose: 是否打印訓練過程log
"""
self.learning_rate = learning_rate
self.reg_rate = reg_rate
self.n_epochs = n_epochs
self.n_factors = n_factors
self.verbose = verbose
def fit(self, X, val_data=None):
"""
FunkSVD算法的訓練方法
:param X: 用戶-物品評分矩陣
:param val_data: 驗證數據,用於退出訓練
:return: 用戶特徵矩陣P和物品特徵矩陣Q的乘積
"""
# 初始化變量
n_users, n_items = X.shape
self.P = np.random.normal(size=(n_users, self.n_factors))
self.Q = np.random.normal(size=(n_items, self.n_factors))
# 訓練模型
for epoch in range(self.n_epochs):
for i in range(n_users):
for j in range(n_items):
if X[i][j] > 0:
error = X[i][j] - np.dot(self.P[i, :], self.Q[j, :].T)
self.P[i, :] += self.learning_rate * (error * self.Q[j, :] - self.reg_rate * self.P[i, :])
self.Q[j, :] += self.learning_rate * (error * self.P[i, :] - self.reg_rate * self.Q[j, :])
# 計算驗證集誤差
if val_data is not None:
y_true, y_pred = self.evaluate(val_data)
val_loss = np.sqrt(np.mean(np.power(y_true - y_pred, 2)))
if self.verbose:
print('epoch %d, val_loss=%.4f' % (epoch + 1, val_loss))
return np.dot(self.P, self.Q.T)
def predict(self, u, i):
"""
預測用戶對物品的評分
:param u: 用戶ID
:param i: 物品ID
:return: 預測評分得分
"""
return np.dot(self.P[u, :], self.Q[i, :].T)
def evaluate(self, test_data):
"""
評估算法效果
:param test_data: 測試數據
:return: 真實值和預測值
"""
y_true = test_data['rating']
y_pred = [self.predict(row['userId'], row['movieId']) for i, row in test_data.iterrows()]
return y_true, y_pred
四、FunkSVD 算法在電影推薦系統中應用實例
FunkSVD 算法可以應用於電影推薦系統中,根據用戶對電影的評分得分,建立用戶-電影評分矩陣,然後使用 FunkSVD 算法對評分矩陣進行分解,得到用戶和電影的特徵矩陣 P 和 Q,進而計算出每個用戶對未評價電影的評分得分,根據得分得齣電影推薦結果。以下是基於 FunkSVD 算法實現的推薦系統代碼示例:
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from FunkSVD import FunkSVD
# 讀取數據
ratings = pd.read_csv('ratings.csv')
# 將評分矩陣轉換為二維矩陣形式
R = ratings.pivot_table(values='rating', index='userId', columns='movieId').fillna(0)
# 劃分訓練集和測試集
train, test = train_test_split(ratings, test_size=0.2)
# 初始化 FunkSVD 模型
funk_svd = FunkSVD(n_epochs=50, n_factors=30, verbose=True)
# 訓練模型
funk_svd.fit(train.pivot_table(values='rating', index='userId', columns='movieId').fillna(0), val_data=test)
# 電影推薦
user_id = 1
user_ratings = ratings[ratings['userId'] == user_id]
user_unseen_movies = ratings[~ratings['movieId'].isin(user_ratings['movieId'])]['movieId'].unique()
recommendations = []
for movie_id in user_unseen_movies:
rating = funk_svd.predict(user_id - 1, movie_id - 1)
recommendations.append((movie_id, rating))
# 推薦電影排序並輸出
recommendations = sorted(recommendations, key=lambda x: x[1], reverse=True)[:10]
recommended_movie_ids = [rec[0] for rec in recommendations]
recommended_movies = ratings[ratings['movieId'].isin(recommended_movie_ids)]['title'].unique()
print('為用戶推薦的電影有:')
for movie in recommended_movies:
print(movie)
五、小結
FunkSVD 算法是一種有效的協同過濾推薦算法,能夠對稀疏高維的用戶-物品評分矩陣進行分解,得到用戶和物品的特徵矩陣,進而計算出每個用戶對所有物品的評分得分,用於電影推薦、商品推薦等領域。通過 Python 實現 FunkSVD 算法,並結合電影推薦應用案例,進一步深化了該算法的理解,有助於進一步掌握協同過濾算法的基本原理和應用。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/286496.html
微信掃一掃
支付寶掃一掃