Datawhale十月組隊學習 推薦系統3

2021-10-25 05:43:55 字數 4405 閱讀 7742

1.核心思想

2.基本原理

3.程式設計實現

談到矩陣分解, 最常用的方法是特徵值分解(evd)或者奇異值分解(svd)。

(1)首先是evd, 它要求分解的矩陣是方陣, 顯然使用者-物品矩陣不滿足這個要求, 而傳統的svd分解, 會要求原始矩陣是稠密的, 而我們這裡的這種矩陣一般情況下是非常稀疏的, 如果想用奇異值分解, 就必須對缺失的元素進行填充, 而一旦補全, 空間複雜度就會非常高, 且補的不一定對。 然後就是svd分解計算複雜度非常高, 而我們的使用者-物品矩陣非常大, 所以基本上無法使用。

(2)2023年的netflix prize之後, simon funk公布了乙個矩陣分解演算法叫做funk-svd, 後來被netflix prize的冠軍koren稱為latent factor model(lfm)。 funk-svd的思想很簡單: 把求解上面兩個矩陣的引數問題轉換成乙個最優化問題,可以通過訓練集裡面的觀察值利用最小化來學習使用者矩陣和物品矩陣。

2.使用者偏差係數,可以使用使用者 給出的所有評分的均值,也可以當做訓練引數。這一項表示了使用者的評分習慣中和物品沒有關係的那種因素。比如有些使用者比較苛刻,對什麼東西要求很高,那麼他評分就會偏低,而有些使用者比較寬容, 對什麼東西都覺得不錯,那麼評分就偏高

3.物品偏差係數,可以使用物品 收到的所有評分的均值,也可以當做訓練引數。這一項表示了物品接受的評分中和使用者沒有關係的因素。比如有些物品本身質量就很高,因此獲得的評分相對比較高,有的物品本身質量很差,因此獲得的評分相對較低。

1.首先,它會先初始化使用者矩陣p和物品矩陣q,p的維度是 [users_num, f] , q的維度是 [item_nums, f],這個f是隱向量的維度。也就是把通過隱向量的方式把使用者的興趣和f的特點關聯了起來。初始化這兩個矩陣的方式很多,但根據經驗,隨機數需要和1/sqrt(f)成正比。下面**中會發現。

2.有了兩個矩陣之後,我就可以根據使用者已經打分的資料去更新引數,這就是訓練模型的過程,方法很簡單,就是遍歷使用者,對於每個使用者,遍歷它打分的物品,這樣就拿到了該使用者和物品的隱向量,然後兩者相乘加上偏置就是**的評分,這時候與真實評分有個差距,根據上面的梯度下降就可以進行引數的更新。

這樣訓練完之後,我們就可以得到使用者alice和物品5的隱向量,根據這個就可以**alice對物品5的打分。下面的**的邏輯就是上面這兩步,這裡使用帶有偏置項和正則項的那個svd演算法

import math

import random

class svd:

def __init__

(self,rating_data,f =

5,alpha =

0.1,lmbda =

0.1,max_iter =

100)

:# self.變數 好像可以將變數變為全域性變數

self.f = f # 表示隱向量的維度

self.p =

dict

() # 使用者矩陣p 大小是[users_num,f]

self.q =

dict

() # 物品矩陣q 大小是[item_num, f]

self.bu =

dict

() # 使用者偏差係數

self.bi =

dict

() # 物品偏差係數

self.mu =

0.0 # 全域性平均數

self.alpha = alpha # 學習率

self.lmbda = lmbda # 正則項係數

self.max_iter = max_iter # 最大迭代次數

self.rating_data = rating_data # 評分矩陣

'''初始化矩陣p和q的方法很多,一般用隨機數填充,但隨機數的大小有講究,

根據經驗,隨機數需要和 1

/sqrt

(f)成正比

'''cnt =

0 # 統計總的打分數,初始化mu用

for user,items in self.rating_data.

items()

: self.p[user]

=[random.

random()

/ math.

sqrt

(self.f)

for x in range(0

,f)]

self.bu[user]=0

cnt +

=len

(items)

for item,rating in items.

items()

:if item not in self.q:

self.q[item]

=[random.

random()

/ math.

sqrt

(self.f)

for x in range(0

,f)]

self.bi[item]=0

self.mu /

= cnt

'''有了矩陣之後,就可以進行訓練,使用隨機梯度下降的方法訓練引數p和q

'''def train

(self)

:for step in range

(self.max_iter)

:for user,items in self.rating_data.

items()

:for item,rui in items.

items()

: rhat_ui = self.

predict

(user,item) # 得到**評分

# 計算誤差

e_ui = rui - rhat_ui

self.bu[user]

+= self.alpha *

(e_ui - self.lmbda * self.bu[user]

) self.bi[item]

+= self.alpha *

(e_ui - self.lmbda * self.bi[item]

) # 計算梯度下降更新梯度

for k in range(0

,self.f)

: self.p[user]

[k]+

= self.alpha *

(e_ui*self.q[item]

[k]- self.lmbda*self.p[user]

[k])

self.q[item]

[k]+

= self.alpha *

(e_ui*self.p[user]

[k]- self.lmbda*self.p[item]

[k])

self.alpha *

=0.1 # 每次迭代步長要逐步縮小

'''**user對item的評分,這裡沒有使用向量的形式

'''def predict

(self,user,item)

: # 計算所得評分 + 使用者偏差係數 + 物品偏差係數 + 全域性平均數

return

sum(self.p[user]

[f]*self.q[item]

[f]for f in range(0

,self.f)

)+ self.bu[user]

+ self.bi[item]

+ self.mu

# 採用字典的形式定義資料集,實際資料非常稀疏,因此使用字典形式而不是dataframe形式

def loaddata()

: rating_data =,2

:,3:

,4:,

5:}return rating_data

# 接下來是訓練和**

rating_data =

loaddata()

basi_svd =

svd(rating_data)

basi_svd.

train()

for item in [

'e']

:print

(item,basi_svd.

predict(1

,item)

)

Datawhale十月組隊學習 推薦系統4

1.基本概念和思想 2.實戰 memorization 和 generalization是推薦系統很常見的兩個概念,其中memorization指的是通過使用者與商品的互動資訊矩陣學習規則,而generalization則是泛化規則。memorization趨向於更加保守,推薦使用者之前有過行為的i...

十月十日學習心得

今天主要學習了運算子和dom模型。今天學習的也都屬於基礎性質的內容,一些簡單的算數 賦值 運算。對於dom這一塊,特別是特徵相關屬性聽得有點迷,還需要進一步的去了解學習,這應該就是我今天課後主要需要攻克的東西了。今天進行了周測,主要內容是近一周內學習的html和css的基礎概念和應用的檢查。測試下來...

2023年十月第三週學習

2020年十月第三週學習 tb6612電機驅動模組 引腳作用 pwma 輸入a的pwm波 ain1 a的輸入腳,與ain2一起設定正轉反轉 ain2 a的輸入腳,與ain1一起設定正轉反轉 stby 相當於晶元的開關,置1的時候晶元工作 bin1 b的輸入腳,與bin2一起設定正轉反轉 bin2 b...