一、簡介
繼上一篇基於用戶的推薦算法,這一篇是要基於商品的,基於用戶的好處是可以根據用戶的評價記錄找出跟他興趣相似的用戶,再推薦這些用戶也喜歡的電影,但是萬一這個用戶是新用戶呢?或是他還沒有對任何電影做評價,那我們要怎么去推薦他可能會有興趣的東西呢?這邊就是要介紹基於商品的相似度,我們打開豆瓣隨便查看一部電影,會看到下面有一個欄位是喜歡這部電影的人也喜歡哪些電影,就是利用了商品相似度的概念。商品相似度還有一個好處,就是可以“事先”計算好,由於商品相似度每個用戶看到的結果都會是一樣的,他可以事先就先算好放在那,等有一批新商品進入時再計算,比較不需要為每個用戶都計算一遍,這是他的一個很大的優勢。原理也很簡單,就是找出喜歡這個電影的用戶,他們也喜歡哪些電影,下面就是利用pyhton來做示范。
二、數據預處理
這次我們還是沿用之前在movielens下載的數據,但由於我們的“目標”變了,所以數據預處理的方式也要做些調整,之前我們是以人為鍵值(key),后面跟了他評價的電影和評分,現在我們要改成以電影為鍵值,后面跟了評價他的人和給出的評分,這樣做是方便到時候算法代碼比較好寫,下面是數據讀取和預處理的代碼。
def load_data(): f = open('u.data') movie_list={} for line in f: (user,movie,rating,ts) = line.split('\t') movie_list.setdefault(movie,{}) movie_list[movie][user] = float(rating) return movie_list
用print查看movie_list的樣子

可以看到,與前面以人為主的相比,很多電影的評分人數都只有一個,所以數據量的不足也會影響到最后算出來的結果。
三、數據分析
這邊跟前面以人為主的推薦有點不一樣,上一篇我挑了7號用戶作為我們的推薦對象,但商品我要對‘’所有商品‘’都找出他們的相似商品,計算量就會大很多,下面為代碼
def calculate(): list = load_data() movie_diff = {} for movie1 in list.keys(): movie_diff.setdefault(movie1,{}) for movie2 in list.keys(): if movie1 != movie2: a = 0 b=0 for name1 in list[movie1].keys(): for name2 in list[movie2].keys(): if name1 == name2: diff = sqrt(pow(list[movie1][name1] -list[movie2][name2],2)) b += 1 a += diff if b != 0: movie_diff[movie1][movie2] = 1/(1+(a/b)) print(movie_diff)
這次跑的時間長了很多,因為要拿所有電影跟其他所有電影進行比較,而且是要比評價電影的所有人,所以計算量大很多,以下是跑完出來的結果,可以看到其實很多的相關性都是1,代表其實由於數據量太少,所以出來的結果參考價值並不大。

四、后續改進
以下是經過這兩次的演練的心得
1、歐幾里得雖然簡單快速,但他出來的結果並不好,下次可以試試其他的算法
2、for循環可以用矩陣來代替,效率會更好
3、可以嘗試跑數據量大數據,出來的效果會比較好
