基于协同过滤算法的在线鲜花店推荐系统详解及GitHub下载
[[TOC]]
基于協(xié)同過(guò)濾的在線鮮花店推薦系統(tǒng)
項(xiàng)目需求:
-
基于店鋪的客戶訂單記錄,實(shí)現(xiàn)店鋪的推薦需求:
- 基于RFM模型,得到客戶的價(jià)值分類,對(duì)高價(jià)值客戶進(jìn)行重點(diǎn)跟蹤,推薦其潛在的商品列表,即實(shí)現(xiàn):給定用戶編號(hào),返回10個(gè)推薦商品列表。
- 對(duì)店鋪滯銷商品,進(jìn)行有針對(duì)性的促銷活動(dòng),推薦給最有可能購(gòu)買的10個(gè)用戶,結(jié)合一些針對(duì)性的促銷優(yōu)惠活動(dòng),向10個(gè)用戶推薦。即實(shí)現(xiàn):給定物品編號(hào),返回10個(gè)推薦用戶列表。
-
店鋪尚未搭建Spark大數(shù)據(jù)環(huán)境,可搭建TensorFlow2的環(huán)境,因此使用TensorFlow2實(shí)現(xiàn)協(xié)同過(guò)濾算法中的矩陣分解。現(xiàn)有資料絕大部分是基于一個(gè)模板復(fù)制出來(lái)的,且基于TensorFlow1,因此需要親自動(dòng)手,用TensorFlow2實(shí)現(xiàn)。
-
若搭建好了Spark環(huán)境,可在Spark中,直接調(diào)用spark.mllib.recommendation.ALS() ,可實(shí)現(xiàn)相同功能。
推薦算法原理:
在推薦系統(tǒng)中,協(xié)同過(guò)濾算法是很常用的推薦算法。中心思想:物以類聚(以物品相似度推薦物品),人以群分(以用戶相似度推薦類似用戶的商品列表)。也就是口味相同的人,把他喜歡的物品或者電影歌曲推薦給你;或者是將你喜歡的物品,類似的物品推薦給你。
- 整體流程:
1、 獲取用戶對(duì)商品的評(píng)分、購(gòu)買記錄等
2、 構(gòu)造協(xié)同矩陣M
3、 基于矩陣進(jìn)行分解M=U*V
4、 利用要推薦的物品或者用戶,和U或者V計(jì)算相似度
計(jì)算相似度:
TensorFlow2可以自動(dòng)幫你求導(dǎo)更新參數(shù),太方便了,你要做的就是構(gòu)造損失函數(shù)loss而已。
loss函數(shù)可以理解為,我們分解得到U*V得到預(yù)測(cè)的M_pre,用M和M_pre求歐式距離:即歐幾里得距離(Euclidean Distance)
公式具體為:
大致意思就是分解一個(gè)大矩陣為兩個(gè)小矩陣相乘。
-
注意事項(xiàng):
- 歐氏距離能夠體現(xiàn)個(gè)體數(shù)值特征的絕對(duì)差異,所以更多的用于需要從維度的數(shù)值大小中體現(xiàn)差異的分析,如使用用戶行為指標(biāo)分析用戶價(jià)值的相似度或差異。
- 余弦距離更多的是從方向上區(qū)分差異,而對(duì)絕對(duì)的數(shù)值不敏感,更多的用于使用用戶對(duì)內(nèi)容評(píng)分來(lái)區(qū)分興趣的相似度和差異,同時(shí)修正了用戶間可能存在的度量標(biāo)準(zhǔn)不統(tǒng)一的問(wèn)題(因?yàn)橛嘞揖嚯x對(duì)絕對(duì)數(shù)值不敏感)。
- 用戶對(duì)內(nèi)容評(píng)分,按5分制,X和Y兩個(gè)用戶對(duì)兩個(gè)內(nèi)容的評(píng)分分別為(1,2)和(4,5),使用余弦相似度得到的結(jié)果是0.98,兩者極為相似。但從評(píng)分上看X似乎不喜歡2這個(gè) 內(nèi)容,而Y則比較喜歡,余弦相似度對(duì)數(shù)值的不敏感導(dǎo)致了結(jié)果的誤差,需要修正這種不合理性就出現(xiàn)了調(diào)整余弦相似度,即所有維度上的數(shù)值都減去一個(gè)均值,比如X和Y的評(píng)分均值都是3,那么調(diào)整后為(-2,-1)和(1,2),再用余弦相似度計(jì)算,得到-0.8,相似度為負(fù)值并且差異不小,但顯然更加符合現(xiàn)實(shí)。
-
*余弦相似度的python實(shí)現(xiàn)*
-
python原生代碼:
import numpy as npdef cosine_similarity(x, y, norm=False):""" 計(jì)算兩個(gè)向量x和y的余弦相似度 """assert len(x) == len(y), "len(x) != len(y)"zero_list = [0] * len(x)if x == zero_list or y == zero_list:return float(1) if x == y else float(0)# method 1res = np.array([[x[i] * y[i], x[i] * x[i], y[i] * y[i]] for i in range(len(x))])cos = sum(res[:, 0]) / (np.sqrt(sum(res[:, 1])) * np.sqrt(sum(res[:, 2])))return 0.5 * cos + 0.5 if norm else cos # 歸一化到[0, 1]區(qū)間內(nèi)if __name__ == '__main__':print cosine_similarity([0, 0], [0, 0]) # 1.0print cosine_similarity([1, 1], [0, 0]) # 0.0print cosine_similarity([1, 1], [-1, -1]) # -1.0print cosine_similarity([1, 1], [2, 2]) # 1.0print cosine_similarity([3, 3], [4, 4]) # 1.0print cosine_similarity([1, 2, 2, 1, 1, 1, 0], [1, 2, 2, 1, 1, 2, 1]) # 0.938194187433
-
矩陣分解TensorFlow2代碼:
TensorFlow2可以自動(dòng)幫你求導(dǎo)更新參數(shù),太方便了,你要做的就是構(gòu)造損失函數(shù)loss而已。
具體代碼為:
'''================================================= @Function -> 用TensorFlow2實(shí)現(xiàn)協(xié)同過(guò)濾矩陣的分解 @Author :luoji @Date :2021-10-19 =================================================='''def matrixDecomposition(alike_matrix,rank=10,num_epoch= 5000,learning_rate=0.001,reg=0.01):row,column = len(alike_matrix),len(alike_matrix[0])avg = np.average(alike_matrix)matrix_avged = alike_matrix-avg# 這里解釋一下為什么要減去平均值進(jìn)行歸一化# 因?yàn)橛嘞蚁嗨贫仍跀?shù)值上的不敏感,會(huì)導(dǎo)致這樣一種情況存在:## 用戶對(duì)內(nèi)容評(píng)分,按5分制,X和Y兩個(gè)用戶對(duì)A,B兩個(gè)內(nèi)容的評(píng)分分別為(1, 2)和(2, 4),使用余弦相似度得到的結(jié)果是1# ,兩者極為相似。但從評(píng)分上看X似乎不喜歡B這個(gè)內(nèi)容,而Y則比較喜歡,余弦相似度對(duì)數(shù)值的不敏感導(dǎo)致了結(jié)果的誤差,需要修正這種不合理性就出現(xiàn)了調(diào)整余弦相似度,# 即所有維度上的數(shù)值都減去一個(gè)均值,比如X和Y的評(píng)分均值都是3,那么調(diào)整后為(-1.25,-0.25)和(0.25, 1.25),再用余弦相似度計(jì)算,得到 -0.38,相似度為負(fù)值并且差異不小,但顯然更加符合現(xiàn)實(shí)。# 那么是否可以在(用戶 - 商品 - 行為數(shù)值)矩陣的基礎(chǔ)上進(jìn)行調(diào)整,使用余弦相似度計(jì)算比普通余弦?jiàn)A角算法要強(qiáng)。## 歐氏距離能夠體現(xiàn)個(gè)體數(shù)值特征的絕對(duì)差異,所以更多的用于需要從維度的數(shù)值大小中體現(xiàn)差異的分析,如使用用戶行為指標(biāo)分析用戶價(jià)值的相似度或差異。y_true = tf.constant(matrix_avged, dtype=tf.float32) # 構(gòu)建y_trueU = tf.Variable(shape=(row, rank), initial_value=np.random.random(size=(row, rank)),dtype=tf.float32) # 構(gòu)建一個(gè)變量U,代表user權(quán)重矩陣V = tf.Variable(shape=(rank, column), initial_value=np.random.random(size=(rank, column)),dtype=tf.float32) # 構(gòu)建一個(gè)變量,代表權(quán)重矩陣,初始化為0variables = [U,V]optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate)for batch_index in range(num_epoch):with tf.GradientTape() as tape:y_pre = tf.matmul(U, V)loss = tf.reduce_sum(tf.norm(y_true-y_pre, ord='euclidean')+ reg*(tf.norm(U,ord='euclidean')+tf.norm(V,ord='euclidean'))) #正則化項(xiàng)print("batch %d : loss %f" %(batch_index,loss.numpy()))grads = tape.gradient(loss,variables)optimizer.apply_gradients(grads_and_vars=zip(grads,variables))return U,V,tf.matmul(U, V)+avgif __name__ == "__main__":# 把矩陣分解為 M=U*V ,U和V由用戶指定秩rankalike_matrix = [[1.0, 2.0, 3.0],[4.5, 5.0, 3.1],[1.0, 2.0, 3.0],[4.5, 5.0, 5.1],[1.0, 2.0, 3.0]]U,V,preMatrix = matrixDecomposition(alike_matrix,rank=2,reg=0.5,num_epoch=2000) # reg 減小則num_epoch需增大print(U)print(V)print(alike_matrix)print(preMatrix)print("this difference between alike_matrix and preMatrix is :")print(alike_matrix-preMatrix)print('loss is :',sum(sum(abs(alike_matrix - preMatrix))))待分解的矩陣:
[[1.0, 2.0, 3.0],
[4.5, 5.0, 3.1],
[1.0, 2.0, 3.0],
[4.5, 5.0, 5.1],
[1.0, 2.0, 3.0]]
分解后,相乘的到的矩陣:
[[1.0647349 1.929376 2.9957888]
[4.6015587 4.7999315 3.1697667]
[1.0643657 1.9290545 2.9957101]
[4.287443 5.211667 4.996485 ]
[1.0647217 1.9293401 2.9957187]],
可以看出兩者還是很相似的,證明我們用TensorFlow2進(jìn)行的矩陣分解是正確的。
注意,正則化項(xiàng)reg需要和num_epoch配套,reg越大,收斂越快,但效果不一定最好。
項(xiàng)目產(chǎn)出和亮點(diǎn):
利用TensorFlow2,實(shí)現(xiàn)協(xié)同過(guò)濾算法中的矩陣分解,而且該模塊可以直接復(fù)用。滿足需求。
- 給定用戶編號(hào),返回10個(gè)推薦商品列表。
- 給定物品編號(hào),返回10個(gè)推薦用戶列表。
亮點(diǎn):
- TensorFlow2太神奇了,只要找到損失函數(shù)loss,模型就可以訓(xùn)練。Amazing!
- 利用TensorFlow2進(jìn)行的矩陣分解,目前是所有分解算法中誤差最小的。
- 全網(wǎng)找不到第二家基于TensorFlow2實(shí)現(xiàn)的。在Spark中,直接調(diào)用spark.mllib.recommendation.ALS() 就好了。
代碼下載地址github:
-
源碼地址:
GitHub -
CSDN 技術(shù)博客地址:
CSDN
1、TensorFlow2太神奇了,只要找到損失函數(shù)loss,模型就可以訓(xùn)練。Amazing!
2、CSDN 技術(shù)博客1 篇,全網(wǎng)找不到第二個(gè)基于TensorFlow2實(shí)現(xiàn)的。好奇為什么TensorFlow2不幫我們實(shí)現(xiàn)了,在Spark中,直接調(diào)用spark.mllib.recommendation.ALS() 就好了
總結(jié)
以上是生活随笔為你收集整理的基于协同过滤算法的在线鲜花店推荐系统详解及GitHub下载的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: TensorFlow2实现协同过滤算法中
- 下一篇: 协同过滤进化版本NeuralCF及ten