基於傳統機器學習的推薦系統
推薦演算法具有非常多的應用場景和商業價值,種類很多,但是目前使用最廣泛的是以下兩種:
1. 基於內容的推薦。通過NLP的一些技術,挖掘文字內容,進而做推薦。
2. 基於協同過濾演算法的推薦。
#協同過濾
協同過濾(Collaborative Filtering),假設我們有m個使用者,n個商品,還有一大堆使用者對商品的行為資料(瀏覽、點贊、點踩、評論、分享等),每一種行為可以通過領域知識對映為分值,那麼我們就可以得到如下所示的一張使用者對商品的打分二維表,只有部分使用者和部分商品之間是有評分資料的,其它部分評分是空白,因此這是個稀疏矩陣,此時我們要用已有的部分打分資料來預測那些空白的使用者與商品之間的評分關係,找到最高評分的物品推薦給使用者。這就是協同過濾。
item1 item2 itemm
user1 2.5
user2
...... 6.5
usern 5.0
一般來說,協同過濾推薦分為兩種型別。第一種是基於使用者(user-based)的協同過濾,第二種是基於專案(item-based)的協同過濾。
基於使用者(user-based)的協同過濾主要考慮的是使用者和使用者之間的相似度,只要找出相似使用者喜歡的物品,並預測目標使用者對對應物品的評分,就可以找到評分最高的若干個物品推薦給使用者。(矩陣的行向量可以用來計算使用者相似度)。
基於專案(item-based)的協同過濾主要考慮的是物品和物品之間的相似度,只有找到了目標使用者對某些物品的評分,那麼我們就可以對相似度高的類似物品進行預測,將評分最高的若干個相似物品推薦給使用者。(矩陣的列向量可以用來計算物品相似度)。比如你在網上買了一本機器學習相關的書,網站馬上會推薦一堆機器學習,大資料相關的書給你,這裡就明顯用到了基於專案的協同過濾推薦思想。
我們簡單比較下基於使用者的協同過濾和基於專案的協同過濾:基於使用者的協同過濾需要線上找使用者和使用者之間的相似度關係(實時變動),計算複雜度肯定會比基於基於專案的協同過濾高,但是可以幫助使用者找到新類別的有驚喜的物品。而基於專案的協同過濾,由於考慮的物品的相似性一段時間不會改變,因此可以很容易的離線計算,準確度一般也可以接受,但是推薦的多樣性來說,就很難帶給使用者驚喜了。一般對於小型的推薦系統來說,基於專案的協同過濾肯定是主流,但是如果是大型的推薦系統來說,則可以考慮基於使用者的協同過濾,或者兩者結合。
程式碼參見 協同過濾推薦系統實戰
#推薦系統模型
#頻繁項集挖掘
我們可以找出使用者購買的所有物品裡,經常在一起出現的物品,來做頻繁項集挖掘,如果使用者購買了頻繁N項集或者序列裡的部分物品,那麼我們可以將頻繁項集或序列裡的其他物品按一定的評分準則推薦給使用者。 推薦閱讀 Apriori演算法
#聚類挖掘
1. 基於使用者聚類,將使用者聚類成不同的目標人群,將同樣目標人群評分高的物品推薦給目標使用者。
2. 基於物品聚類,將使用者評分高物品的相似同類物品推薦給使用者。
#分類挖掘
根據使用者評分的高低,設定一份評分閾值,評分高於閾值的就是推薦,評分低於閾值就是不推薦,我們將問題變成了一個二分類問題。
特徵可以選擇使用者畫像特徵、物品畫像特徵以及物品內容特徵(詞頻、TF-IDF),然後做concat。
#基於PageRank的推薦
搜尋引擎的搜尋結果的排名主要取決於兩組資訊:一是網頁本身的質量(PageRank演算法);而是該查詢與網頁的相關性(TF-IDF)。
如何確定搜尋內容與網頁的相關性,假設一個使用者的查詢有N個關鍵詞,可以計算這N個關鍵詞在該網頁的TF-IDF值之和作為相關性score,即:
#基於NMF的推薦
NMF(Non-negative
Matrix Factorization,非負矩陣分解),將一個大矩陣分解為兩個矩陣的乘積:
NMF可以用於提取文字主題,假設我們有m個文字,n個詞,Aij表示第i個文字的第j個詞的特徵值(詞頻或TF-IDF)。k是我們假設的主題數,一般要比文字數少。
NMF分解後,Wik對應第i個文字的和第k個主題的概率相關度,而Hkj對應第j個詞和第k個主題的概率相關度。當然也可以反過來去理解:我們輸入的有m個詞,n個文字,而Aij對應第i個詞在第j個文字的特徵值。NMF分解後,Wik對應第i個詞的和第k個主題的概率相關度,而Hkj對應第j個文字和第k個主題的概率相關度。
注意到這裡我們使用的是”概率相關度”,這是因為我們使用的是”非負”的矩陣分解,這樣我們的W,H矩陣值的大小可以用概率值的角度去看,從而可以得到文字和主題的概率分佈關係。
利用文字與主題的相關程度,可以將文字聚類;利用詞和主題的相關程度,可以提取每個主題的關鍵詞。
import numpy as np
from sklearn.decomposition import NMF
# 假設我們有4個詞,5個文字組成的特徵值矩陣
X = np.array([[1,1,5,2,3], [0,6,2,1,1], [3, 4,0,3,1], [4, 1,5,6,3]])
# n_components即我們的主題數k,確定它需要一些對於要分析文字主題大概的先驗知識
model = NMF(n_components=2, alpha=0.01)
# 單詞話題矩陣
W = model.fit_transform(X)
# 文字話題矩陣
H = model.components_
print(W)
print(H)
執行結果:
[[1.67371185 0.02013017] [0.40564826 2.17004352] [0.77627836 1.5179425 ] [2.66991709 0.00940262]][[1.32014421 0.40901559 2.10322743 1.99087019 1.29852389] [0.25859086 2.59911791 0.00488947 0.37089193 0.14622829]]
分析H矩陣可以看到,第1,3,4,5個文字和第一個隱含主題更相關,而第二個文字與第二個隱含主題更加相關。 分析W矩陣可以看到,第1,4個詞和第一個隱含主題更相關,而第2,3個詞與第二個隱含主題更加相關。
基於LDA的推薦
LDA(Latent
Dirichlet Allocation,隱含狄利克雷分佈),這是一個被廣泛使用的主題模型。其原理如下:
1. 假設我們有m個文字,n個詞,Aij表示第i個文字的第j個詞的特徵值(詞頻或TF-IDF),當然我們還是需要先假定一個主題數目K;
2. 對於每篇文章,都有各自的主題分佈(為多項分佈,該多項分佈的概率引數服從Dirichlet分佈,該Dirichlet分佈的引數為α);
3. 對於每個主題,都有各自的詞分佈(為多項分佈,該多項分佈的概率引數服從Dirichlet分佈,該Dirichlet分佈的引數為β)。
1. 對於任一文件d,其主題分佈θd為:θd =
Dirichlet(α⃗),其中,α為分佈的超引數,是一個K維向量,K為主題個數;
2. 對於任一主題k, 其詞分佈βk為:βk =
Dirichlet(η⃗),其中,η為分佈的超引數,是一個V維向量,V代表詞彙表裡所有詞的個數;
3. 對於每一篇文件d,它的每一個詞n,我們可以先從他的主題分佈θd中得到它的主題Zd,n = multi(θd);
4. 然後根據該主題,從它的詞分佈βk中得到我們看到的詞Wd,n = multi(βzdn)。
那麼我們應該如何根據訓練樣本求解這個LDA模型的各個引數值呢(即求出每一篇文件的主題分佈和每一個主題中的詞分佈)?
一般有兩種方法:
1. 第一種是基於Gibbs取樣演算法求解。即通過Gibbs取樣得到所有詞的主題,然後統計所有詞的主題計數,就可以得到各個主題的詞分佈;接著統計各個文件對應詞的主題計數,得到各個文件的主題分佈。
2. 第二種是基於變分推斷EM演算法求解。模型的隱變數為θ,β,z,模型的引數是α,η。
import numpy as np
from sklearn.decomposition import NMF,
LatentDirichletAllocation
# 假設我們有4個詞,5個文字組成的特徵值矩陣
X = np.array([[1, 1, 5, 2, 3], [0, 6, 2, 1, 1], [3, 4, 0, 3, 1], [4, 1, 5, 6, 3]])
# n_components即我們的主題數k,確定它需要一些對於要分析文字主題大概的先驗知識
# model = NMF(n_components=2, alpha=0.01)
model = LatentDirichletAllocation(n_components=2, random_state=0, learning_method='batch')
# 單詞話題矩陣
W = model.fit_transform(X)
# 文字話題矩陣
H = model.components_
# 模型的困惑度,代表生成整個訓練集文件的似然估計的負值,perplexity值越小,模型能力越強。可以用來作為選擇超參K的參考。
perplexity = model.perplexity(X)
print(W)
print(H)
print(perplexity)
執行結果:
[[0.90770735 0.09229265] [0.2976618 0.7023382 ] [0.07779857 0.92220143] [0.9318666 0.0681334 ]][[ 5.37754968 1.88301326 12.18651534 8.71274273 6.96941893] [ 3.62245032 11.11698674 0.81348466 4.28725727 2.03058107]]5.96164339425483
#