協同過濾演算法 預測和推薦
- 2020 年 5 月 2 日
- 筆記
1 協同過濾演算法介紹
1.什麼是協同過濾演算法
1. 協同過濾推薦演算法是誕生最早,並且較為著名的推薦演算法,主要的功能是預測和推薦。
2. 演算法通過對用戶歷史行為數據的挖掘發現用戶的偏好,基於不同的偏好對用戶進行群組劃分並推薦品味相似的商品。
3. 協同過濾推薦演算法分為兩類,分別是基於用戶的協同過濾演算法(user-based collaboratIve filtering),和基於物品的協同過濾演算法(item-based collaborative filtering)。
4. 簡單的說就是:人以類聚,物以群分。下面我們將分別說明這兩類推薦演算法的原理和實現方法。
2.基於用戶的協同過濾演算法
2. 假設有甲和乙兩名用戶,有a、b、c三款產品。
3. 如果甲和乙都購買了a和b這兩種產品,我們可以假定甲和乙有近似的購物品味。
4. 當甲購買了產品c而乙還沒有購買c的時候,我們就可以把c也推薦給乙。
舉例:
3.基於物品的協同過濾演算法
舉例:
1)物品組合(A,D)被同時偏好出現的次數最多,因而可以認為A/D兩件物品的相似度最高
2)從而,可以為選擇了A物品的用戶推薦D物品
2 歐幾里德距離評價
1.歐幾里得度量 是什麼?
1. 歐幾里得度量(euclidean metric)(也稱歐氏距離)是一個通常採用的距離定義
2. 指在m維空間中兩個點之間的真實距離,或者向量的自然長度(即該點到原點的距離)。
3. 在二維和三維空間中的歐氏距離就是兩點之間的實際距離
4. n維空間的公式
2. 藉助「歐幾里得度量」 尋找偏好相似的用戶原理
1)在示例中,5個用戶分別對兩件商品進行了評分。
2)這裡的分值可能表示真實的購買,也可以是用戶對商品不同行為的量化指標。
3)例如,瀏覽商品的次數,向朋友推薦商品,收藏,分享,或評論等等。
4)這些行為都可以表示用戶對商品的態度和偏好程度。
5)在散點圖中,Y軸是商品1的評分,X軸是商品2的評分,通過用戶的分布情況可以發現,A,C,D三個用戶距離較近。
6)用戶A(3.3 6.5)和用戶C(3.6 6.3),用戶D(3.4 5.8)對兩件商品的評分較為接近。而用戶E和用戶B則形成了另一個群體。
7)散點圖雖然直觀,但無法投入實際的應用,也不能準確的度量用戶間的關係。
8)因此我們需要通過數字對用戶的關係進行準確的度量,並依據這些關係完成商品的推薦。
1. 通過公式我們獲得了5個用戶相互間的歐幾里德係數,也就是用戶間的距離。
2. 係數越小表示兩個用戶間的距離越近,偏好也越是接近。
3. 不過這裡有個問題,太小的數值可能無法準確的表現出不同用戶間距離的差異,因此我們對求得的係數取倒數,使用戶間的距離約接近,數值越大。
4. 在下面的表格中,可以發現,用戶A&C用戶A&D和用戶C&D距離較近。同時用戶B&E的距離也較為接近。與我們前面在散點圖中看到的情況一致。
3 使用協同過濾演算法簡單測試
第一步,將數據讀取並格式化為字典形式,便於解析
第二步:藉助”歐幾里德”演算法計算用戶相似度
第三步:計算某個用戶與其他用戶的相似度
第四步:根據相似度最高的用戶喜好商品排序,把相似度最高用戶的喜好推薦給當前用戶
#photo.txt 1,華為p30,2.0 1,三星s10,5.0 1,小米9,2.6 2,華為p30,1.0 2,vivo,5.0 2,htc,4.6 3,魅族,2.0 3,iphone,5.0 3,pixel2,2.6 --------------------------------------------------------- with open('./phone.txt', 'r', encoding='utf-8') as fp: content = fp.readlines() # 第一步,將數據讀取並格式化為字典形式,便於解析 def parse_data(): with open('./phone.txt','r',encoding='utf-8') as fp: content = fp.readlines() # 將用戶、評分、和手機寫入字典data data = {} for line in content: line = line.strip().split(',') #如果字典中沒有某位用戶,則使用用戶ID來創建這位用戶 if not line[0] in data.keys(): data[line[0]] = {line[1]:line[2]} #否則直接添加以該用戶ID為key字典中 else: data[line[0]][line[1]] = line[2] return data data = parse_data() ''' { "1":{ "華為p30":"2.0", "三星s10":"5.0", "小米9":"2.6" }, "2":{ "華為p30":"1.0", "vivo":"5.0", "htc":"4.6" }, "3":{ "魅族":"2.0", "iphone":"5.0", "pixel2":"2.6" } } ''' # 第二步:藉助"歐幾里德"演算法計算用戶相似度 from math import * def Euclid(user1, user2): # 取出兩位用戶購買過的手機和評分 user1_data = data[user1] user2_data = data[user2] distance = 0 # 找到兩位用戶都購買過的手機,並計算歐式距離 for key in user1_data.keys(): if key in user2_data.keys(): # 注意,distance越大表示兩者越相似 distance += pow(float(user1_data[key]) - float(user2_data[key]), 2) return 1 / (1 + sqrt(distance)) # 這裡返回值越小,相似度越大 # 第三步:計算某個用戶與其他用戶的相似度 def top_simliar(userID): res = [] for userid in data.keys(): #排除與自己計算相似度 if not userid == userID: simliar = Euclid(userID,userid) res.append((userid,simliar)) # res = # [('2', 0.5), ('3', 1.0)] res.sort(key=lambda val:val[1]) return res # 第四步:根據相似度最高的用戶喜好商品排序,把相似度最高用戶的喜好推薦給當前用戶 def recommend(userid): #相似度最高的用戶 top_sim_user = top_simliar(userid)[0][0] # top_sim_user=2 找到相似度最高的用戶ID #相似度最高的用戶的購買記錄 items = data[top_sim_user] # items = {'華為p30': '1.0', 'vivo': '5.0', 'htc': '4.6'} recommendations = [] #篩選出該用戶未購買的手機並添加到列表中 for item in items.keys(): if item not in data[userid].keys(): recommendations.append((item,items[item])) recommendations.sort(key=lambda val:val[1],reverse=True)#按照評分排序 return recommendations if __name__ == '__main__': # 找到與用戶id為1的用戶相似度最高的用戶 print(recommend('1')) # [('vivo', '5.0'), ('htc', '4.6')]