2018-04-26python
1.協同過濾算法
協同過濾(Collaborative Filtering)字面上的解釋就是在別人的幫助下來過濾篩選,協同過濾通常是在海量的用戶中發現一小部分和你品味比較相近的,在協同過濾中,這些用戶稱爲鄰居,而後根據他們喜歡的東西組織成一個排序的目錄來推薦給你。問題的重點就是怎樣去尋找和你比較類似的用戶,怎麼將那些鄰居的喜愛組織成一個排序的目錄給你,要實現一個協同過濾的系統,須要如下幾個步驟:機器學習
1.收集用戶的愛好ide
2.找到類似的用戶或者物品函數
3.計算推薦學習
在收集用戶的喜歡方面,通常的方式有評分,投票,轉發,保存書籤,點擊鏈接等等 ,有了用戶的喜愛以後,就能夠經過這些共同的喜愛來計算用戶之間的類似度了。測試
2.類似度計算spa
類似度的計算通常是基於向量的,能夠將一個用戶對全部的物品的偏好做爲一個向量來計算用戶之間的類似度,或者將全部用戶對於某一個物品的偏好做爲一個向量計算物品之間的類似度,類似度的計算有下列幾種方式:3d
計算歐幾里得距離:code
利用歐幾里得距離計算類似度時,將類似度定義以下:
皮爾遜相關係數:
其中sx,sy表示x和y的標準差。
Cosine類似度:
Tanimoto係數,也稱做Jaccard係數:
基於用戶的協同過濾:不考慮用戶、物品的屬性(特徵)信息,它主要是根據用戶對物品的偏好(Preference)信息,發掘不一樣用戶之間口味(Taste)的類似性,使用這種用戶類似性來進行個性化推薦。基於用戶的協同過濾推薦,它是以用戶爲中心,觀察與該用戶興趣類似的一個用戶的羣體,將這個興趣類似的用戶羣體所感興趣的其餘物品,推薦給該用戶。
基於物品的協同過濾:也不考慮用戶、物品的屬性(特徵)信息,它也是根據用戶對物品的偏好(Preference)信息,發掘不一樣物品之間的類似性。基於物品的協同過濾推薦,是以物品爲中心,經過觀察用戶對物品的偏好行爲,將類似的物品計算出來,能夠認爲這些類似的物品屬於特定的一組類別,而後根據某個用戶的歷史興趣計算其所屬的類別,而後看該類別是否屬於這些成組類別中的一個,最後將屬於成組類別所對應的物品推薦給該用戶。
基於模型的協同過濾:基於模型的協同過濾推薦,是採用機器學習的方法,經過離線計算實現推薦的,一般它會首先根據歷史數據,將數據集分紅訓練集和測試集兩個數據集,使用訓練集進行訓練生成推薦模型,而後將推薦模型應用到測試集上,評估模型的優劣,若是模型到達實際所須要的精度,最後可使用訓練獲得的推薦模型進行推薦(預測)。可見,這種方法使用離線的歷史數據,進行模型訓練和評估,須要耗費較長的時間,依賴於實際的數據集規模、機器學習算法計算複雜度。
對於咱們的用戶歷史行爲數據,咱們關注的是用戶與物品之間的關係,能夠生成一個用戶-物品矩陣,矩陣元素表示用戶對物品的偏好行爲(或者是評分),若是用戶和物品的數量都很大,那麼可見這是一個超大稀疏矩陣,由於並非每用戶都對全部的物品感興趣,只有每一個用戶感興趣的物品纔會有存在對應的偏好值,沒有感興趣的都爲空缺值,最終咱們是要從這些空缺值對應的物品中選擇出一些用戶可能會感興趣的,推薦給用戶,這樣才能實現個性化推薦。
下面,咱們假設使用用戶-物品的評分矩陣來實現推薦,定義評分矩陣爲R,那麼經過將R分解爲另外兩個低秩矩陣U和M,因爲R是稀疏矩陣,不少位置沒有值,只能經過計算使用U與M的乘積近似矩陣R,那麼只要最終獲得的偏差儘可能小,能知足實際須要便可,通常使用均方根偏差(Root mean square error,RMSE)來衡量,那麼就要計算一個目標函數的最小值,以下函數公式所示:
√[∑di^2/n]=Re,式中:n爲測量次數;di爲一組測量值與真值的誤差。
具體代碼以下:
# -*- coding: utf-8 -*- """ Spyder Editor This is a temporary script file. """ import os import codecs import numpy as np import pandas as pd from sklearn import cross_validation as cv from sklearn.metrics.pairwise import pairwise_distances #計算餘弦類似性 os.getcwd() os.chdir("C:/Users/admin/Desktop/ml-100k/ml-100k") f=codecs.open('u.data', 'r') print (f.read()) header = ['user_id', 'item_id', 'rating', 'timestamp'] df = pd.read_csv('u.data', sep='\t', names=header) #計算惟一用戶和電影的數量 n_users = df.user_id.unique().shape[0] n_items = df.item_id.unique().shape[0] print ('Number of users = ' + str(n_users) + ' | Number of movies = ' + str(n_items) ) #使用scikit-learn庫將數據集分割成測試和訓練,根據測試樣本的比例(test_size),取0.25 train_data, test_data = cv.train_test_split(df, test_size=0.25) #基於內存的協同過濾 #建立用戶-產品矩陣 #Create two user-item matrices, one for training and another for testing train_data_matrix = np.zeros((n_users, n_items)) for line in train_data.itertuples(): train_data_matrix[line[1]-1, line[2]-1] = line[3] test_data_matrix = np.zeros((n_users, n_items)) for line in test_data.itertuples(): test_data_matrix[line[1]-1, line[2]-1] = line[3] #計算餘弦類似性,輸出從0到1,由於打分都是正的 user_similarity = pairwise_distances(train_data_matrix, metric='cosine') item_similarity = pairwise_distances(train_data_matrix.T, metric='cosine') #預測 def predict(ratings, similarity, type='user'): if type == 'user': mean_user_rating = ratings.mean(axis=1) #You use np.newaxis so that mean_user_rating has same format as ratings ratings_diff = (ratings - mean_user_rating[:, np.newaxis]) pred = mean_user_rating[:, np.newaxis] + similarity.dot(ratings_diff) / np.array([np.abs(similarity).sum(axis=1)]).T elif type == 'item': pred = ratings.dot(similarity) / np.array([np.abs(similarity).sum(axis=1)]) return pred item_prediction = predict(train_data_matrix, item_similarity, type='item') user_prediction = predict(train_data_matrix, user_similarity, type='user') #評估 使用均方根偏差(RMSE) from sklearn.metrics import mean_squared_error from math import sqrt def rmse(prediction, ground_truth): prediction = prediction[ground_truth.nonzero()].flatten() ground_truth = ground_truth[ground_truth.nonzero()].flatten() return sqrt(mean_squared_error(prediction, ground_truth)) print ('User-based CF RMSE: ' + str(rmse(user_prediction, test_data_matrix))) print ('Item-based CF RMSE: ' + str(rmse(item_prediction, test_data_matrix))) #基於模型的協同過濾 #計算稀疏度 sparsity=round(1.0-len(df)/float(n_users*n_items),3) print ('The sparsity level of MovieLens100K is ' + str(sparsity*100) + '%') import scipy.sparse as sp from scipy.sparse.linalg import svds #get SVD components from train matrix. Choose k. u, s, vt = svds(train_data_matrix, k = 20) s_diag_matrix=np.diag(s) X_pred = np.dot(np.dot(u, s_diag_matrix), vt) print ('User-based CF MSE: ' + str(rmse(X_pred, test_data_matrix)))
參考地址:http://python.jobbole.com/85516/