機器學習項目(五) 電影推薦系統(四)

五、協同過濾

種類

基於記憶:
基於物品
基於用戶

集成:

Combine the Model-based&Memory-based

基於模型:

矩陣分解
深度學習

在這裏插入圖片描述

基於用戶
在這裏插入圖片描述

基於模型
不同算法
在這裏插入圖片描述

特徵值和特徵向量
AX=λXAX = \lambda X
X就是特徵向量
$\lambda $就是特徵值

A=wλw1A = w \lambda w^{-1}

SVD的定義

SVD也是對矩陣進行分解,但是和特徵分解不同,SVD並不要求分解的矩陣爲方陣。假設我們的矩陣A是一個mn的矩陣,那麼我們定義矩陣A的SVD爲
A=UσVTA = U \sigma V^T
其中U是一個m
n的矩陣,σ\sigma是一個mn矩陣,除了主對角線上的元素以外全爲0,主對角線上的每個元素都稱爲奇異值,V是一個nm的矩陣,U和V都是酉矩陣(實正交矩陣),即滿足VTV=I,UTU=IV^T V = I,U^T U = I

右奇異向量求解

如果我們將A的裝置和A做矩陣乘法,那麼會得到n*n的一個方陣ATAA^TA,既然ATAA^TA是方陣,那麼我們就可以進行特徵分解,得到的特徵值和特徵向量滿足下式:
(ATA)vi=λvi(A^TA)v_i = \lambda v_i
得到:矩陣ATAA^TA的n個特徵值和對應的n個特徵向量v。
A=UΣVTAV=UΣVTVAV=UΣAvi=σiμiσi=Avi/μi\mathbf{A}=\mathbf{U} \Sigma V^{T} \Rightarrow \mathbf{A} \mathbf{V}=\mathbf{U} \Sigma V^{T} \mathbf{V} \Rightarrow \mathbf{A} \mathbf{V}=\mathbf{U} \mathbf{\Sigma} \Rightarrow \mathbf{A} \boldsymbol{v}_{i}=\boldsymbol{\sigma}_{i} \boldsymbol{\mu}_{i} \Rightarrow \boldsymbol{\sigma}_{i}=\mathbf{A} \boldsymbol{v}_{i} / \boldsymbol{\mu}_{i}
這樣我們可以求出我們的每個奇異值,進而求出奇異值矩陣Σ\Sigma
A=UΣVTAT=VΣTUTATA=VΣTUTUΣVT=VΣ2VT\mathrm{A}=\mathrm{U} \Sigma \mathrm{V}^{\mathrm{T}} \Rightarrow \mathrm{A}^{\mathrm{T}}=\mathrm{V} \Sigma^{\mathrm{T}} \mathrm{U}^{\mathrm{T}} \Rightarrow \mathrm{A}^{\mathrm{T}} \mathrm{A}=\mathrm{V} \Sigma^{\mathrm{T}} \mathrm{U}^{\mathrm{T}} \mathrm{U} \Sigma \mathrm{V}^{\mathrm{T}}=\mathrm{V} \Sigma^{2} \mathrm{V}^{\mathrm{T}}

SVD的一些性質

大矩陣分解
Amn=UmnΣmnVmnTUmkΣkkVknTA_{m * n}=U_{m * n} \Sigma_{m * n} V_{m * n}^{T} \cong U_{m * k} \Sigma_{k * k} V_{k * n}^{T}

SVD用於PCA降維
假設樣本時mn的矩陣X,如果我們通過SVD找到了矩陣XTXX^TX最大的d個特徵向量張成的md維矩陣U,則做如下處理
Xdn=UdmTXmnX_{\mathrm{d} * n}^{\prime}=U_{\mathrm{d} * m}^{T} X_{\mathrm{m} * n}
可以得到一個dn的矩陣xx^{\prime},這個矩陣和我們原來的mn維樣本矩陣X相比,行數從m減到了d,可見對行數進行了壓縮
做奇異矩陣可以用於行數的壓縮,相對的,右奇異矩陣可以用於列數即特徵維度的壓縮,也就是我們的PCA降維

數據壓縮
ρ=n2k(2n+1)\rho=\frac{n^{2}}{k(2 n+1)}

推薦系統

當給定一個打分矩陣時,矩陣中行代表用戶user,列代表物品item,其中的值代表用戶對物品的打分
基於svd的優勢在於:用戶的評分數據是稀疏矩陣,可以用SVD將原始數據映射到低維空間中,然後計算物品item之間的相似度,可以節省計算資源
整體思路:找到用戶沒有評分的物品,然後再經過SVD"壓縮"後的低維空間中,計算未評分物品與其他物品的相似性,得到一個預測打分,再對這些物品的評分從高到低進行排序,返回前N個物品推薦給用戶

推薦系統實現

一、用戶未評分的商品列表,對打分矩陣A做SVD,得到三個矩陣U,Σ,VTU,\Sigma,V^T
二、選定留下k個特徵值、特徵向量,取u矩陣的前k列,得到μk\mu_k,取sigma的前k個值,得到sigmaksigma_k
三、R=ATμksigmakR = A^T * \mu_k *sigma_k,遍歷未評分的商品列表

import pandas as pd
from surprise import Reader, Dataset, SVD, evaluate
import numpy as np


reader = Reader()

ratings = pd.read_csv('../input/ratings_small.csv')
ratings.head()

data = Dataset.load_from_df(ratings[['userId', 'movieId', 'rating']], reader)
data.split(n_folds=5)

svd = SVD()
evaluate(svd, data, measures=['RMSE', 'MAE'])

trainset = data.build_full_trainset()
svd.train(trainset)

ratings[ratings['userId'] == 1]

svd.predict(1, 302, 3)

def convert_int(x):
    try:
        return int(x)
    except:
        return np.nan

id_map = pd.read_csv('../input/links_small.csv')[['movieId', 'tmdbId']]
id_map['tmdbId'] = id_map['tmdbId'].apply(convert_int)
id_map.columns = ['movieId', 'id']
id_map = id_map.merge(smd[['title', 'id']], on='id').set_index('title')
#id_map = id_map.set_index('tmdbId')

indices_map = id_map.set_index('id')


def hybrid(userId, title):
    idx = indices[title]
    tmdbId = id_map.loc[title]['id']
    # print(idx)
    movie_id = id_map.loc[title]['movieId']

    sim_scores = list(enumerate(cosine_sim[int(idx)]))
    sim_scores = sorted(sim_scores, key=lambda x: x[1], reverse=True)
    sim_scores = sim_scores[1:26]
    movie_indices = [i[0] for i in sim_scores]

    movies = smd.iloc[movie_indices][['title', 'vote_count', 'vote_average', 'year', 'id']]
    movies['est'] = movies['id'].apply(lambda x: svd.predict(userId, indices_map.loc[x]['movieId']).est)
    movies = movies.sort_values('est', ascending=False)
    return movies.head(10)



hybrid(1, 'Avatar')


hybrid(500, 'Avatar')

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章