一文深入理解協同過濾 寫在之前… 從這篇文章開始,我的下一個算法職業生涯方向將專注于推薦算法…
看了那么多書和代碼,還是peter 的那本<<機器學習實戰>>最為經典,說實話很多中國人寫的書確實不怎么樣… 那么,開始吧.本文代碼從趙志勇的那本書上修改而來,估計趙志勇的那篇文章也是從<<機器學習實戰>>那本書修改而來,反正總是修改修改… 那就上代碼吧!,talk is cheap ,show me the code .
# coding:UTF-8
'''
Date:20180624
@author: luogan
'''import numpy as np
import pandasfrom numpy import mat,eyefrom numpy import linalgdef fetch_data():dat=mat([[4., 3., 0., 5., 0.],[5., 0., 4., 4., 0.],[4., 0., 5., 0., 3.],[2., 3., 0., 1., 0.],[0., 4., 2., 0., 5.]])return datdef cos_sim(x, y):'''余弦相似性input: x(mat):以行向量的形式存儲,可以是用戶或者商品y(mat):以行向量的形式存儲,可以是用戶或者商品output: x和y之間的余弦相似度'''numerator = x * y.T # x和y之間的額內積denominator = np.sqrt(x * x.T) * np.sqrt(y * y.T) return (numerator / denominator)[0, 0]def similarity(data):'''計算矩陣中任意兩行之間的相似度input: data(mat):任意矩陣output: w(mat):任意兩行之間的相似度'''m = np.shape(data)[0] # 用戶的數量# 初始化相似度矩陣w = np.mat(np.zeros((m, m)))for i in range(m):for j in range(i, m):if j != i:# 計算任意兩行之間的相似度w[i, j] = cos_sim(data[i, ], data[j, ])w[j, i] = w[i, j]else:w[i, j] = 0return wdef user_based_recommend(data, w, user):'''基于用戶相似性為用戶user推薦商品input: data(mat):用戶商品矩陣w(mat):用戶之間的相似度user(int):用戶的編號output: predict(list):推薦列表'''m, n = np.shape(data)interaction = data[user, ] # 用戶user與商品信息# 1、找到用戶user沒有互動過的商品not_inter = []for i in range(n):if interaction[0, i] == 0: # 沒有互動的商品not_inter.append(i)# 2、對沒有互動過的商品進行預測#print('not_inter=',not_inter)predict={}dd=np.array(data)ww=np.array(w) if len(not_inter)>0:for i in not_inter:#print('ww[:,user]=',ww[:,user])#print('dd[:,i].T',dd[:,i].T)predict[i]=ww[:,user]@dd[:,i].T#print(predict)return predictdef top_k(predict, k):'''為用戶推薦前k個商品input: predict(list):排好序的商品列表k(int):推薦的商品個數output: top_recom(list):top_k個商品'''pp=pandas.Series(predict)pp1=pp.sort_values(ascending=False)#top_recom = []len_result = len(predict)if k>=len_result:return pp1.iloc[:k]else:return pp1def svd(data):u,sigma,vt=linalg.svd(data)sig3=mat(eye(3)*sigma[:3])fea_mat=data.T*u[:,:3]*sig3.Ireturn fea_matdef normalize(w):w=np.array(w)#print(w)dim=len(w)ww=[]for i in range(dim):d=w[i]m=[]for k in range(len(d)):m.append(abs(d[k]))ssm=sum(m)#print('ssm=',ssm)for j in range(len(m)):m[j]=d[j]/ssmww.append(m)return mat(ww)data = fetch_data()print('僅僅采用協同過濾算法')print('only use collaborative')w_initial=similarity(data)
# 3、利用用戶之間的相似性進行推薦
#print ("------------ 3. predict ------------" )
predict = user_based_recommend(data, w_initial, 0)
# 4、進行Top-K推薦
#print ("------------ 4. top_k recommendation ------------")
top_recom = top_k(predict, 1)
print ('top_recom=',top_recom)print('采用協同過濾算法+相似度矩陣的歸一化')print(' use collaborative and normalize')w_initial=similarity(data) w_initial_normal=normalize(w_initial)predict = user_based_recommend(data, w_initial_normal, 0)
top_recom = top_k(predict, 1)
print ('top_recom=',top_recom)print('采用協同過濾算法+svd矩陣分解')
print('use collaborative and svd')data1=svd(data)
w_svd= similarity(data1)predict = user_based_recommend(data, w_svd, 0)
top_recom = top_k(predict, 1)
print ('top_recom=',top_recom)print('采用協同過濾算法+svd矩陣分解'+'相似度矩陣的歸一化')
print('use collaborative and svd and normalize')data1=svd(data)
w_svd= similarity(data1)w_svd_normal=normalize(w_svd)predict = user_based_recommend(data, w_svd_normal, 0)
top_recom = top_k(predict, 1)
print ('top_recom=',top_recom) 僅僅采用協同過濾算法
top_recom= 2 5.103039
4 2.224911
dtype: float64
采用協同過濾算法+相似度矩陣的歸一化
top_recom= 2 2.592621
4 1.398861
dtype: float64
采用協同過濾算法+svd矩陣分解
top_recom= 2 2.555181
4 1.241427
dtype: float64
采用協同過濾算法+svd矩陣分解相似度矩陣的歸一化
top_recom= 2 1.687669
4 0.818257
dtype: float64
當我們僅僅采用協同過濾,不對結果采用任何處理時,第一個用戶的第三的商品的推薦,結果是5.1,對比其他三種算法,可以看出這個結果是有問題的,其他三種算法的推薦值都在2左右.
svd 和相似度矩陣歸一化,在某種意義上是等價的,這段時間看了30多篇文獻, 協同過濾的變種和技巧方面還有很多種.下次繼續更....
結論: 在用協同過濾做推薦時,必須采用歸一化或svd,或其他技巧…
總結
以上是生活随笔 為你收集整理的一文深入理解协同过滤 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。