用python寫一個簡單的推薦系統

前言


在上篇文章豆瓣電影,電視劇DM實戰中提及到,我和室友們產生了劇荒,萌生出要做一個個人用的推薦系統,解決劇荒的問題的想法,經過一輪的死纏爛打,這個個人推薦系統終于成型了。

今天來分享一下心得,對此感興趣的朋友可以自己對著寫一個。

傳統推薦系統算法


首先介紹一下傳統的推薦系統方法,之所以叫它傳統,是因為大部分學習資料上都是用這一個方法。

我們來假設有這么一個矩陣(用python的列表表示):

  [# A B C D E
    [2,0,0,4,4], #1
    [5,5,5,3,3], #2
    [2,4,2,1,2]  #3
    ......
  ]

矩陣的行代表用戶,列表示物品,其交點表示用戶對該物品的評分。

假設現在用戶1需要選商品,推薦系統則假設其會選擇并未選擇過的商品,因此,系統會在第一行中尋找評分為0的物品,顯然會找到B和C。這時,該怎么知道是推薦B還是C呢?(假設用戶只需推薦一個),這時則需要計算B、C和用戶以前選擇過的物品(已評分)的相似度。

僅僅算出相似度還不夠,因為你不能判斷這到底是好的那一部分相似還是壞的部分相似。所以這時,我們需要引入用戶的評分作為相似度計算的權重,評分X相似度得到最后的得分(該得分會一直累加,則B的推薦得分會是B與A,D,E的相似得分的累加和)。這樣一來,評分低物品的最后得分自然就低,評分高的物品自然得分就高,這時問題就簡化成排序問題了。

顯然,上述問題的核心在于如何計算相似度。

這里給出計算相似度的兩種方法:

歐式距離法

  • 以B和A的相似度為例:
    similar = 1/sqrt((0-2)^2 + (5-5)^2 + (4-2)^2 ……)最后B與A的相似得分還得乘上評分,score = similar * 2
  • 余弦相似度
    costheta=fracAcdotB||A||||B||

AB為兩列向量,||A||表示A的2范數
特別注意一點的是,cos的取值是-11,我們需要將其歸一化,即把范圍弄成在01上。于是相似度計算公司變成0.5 + 0.5*cos

少用戶推薦系統的創新


在上述的內容中,我們可以發現傳統的方法有一個特出的問題,傳統的算法需要大量的用戶評分,即矩陣的行數需要較多才能得出的結果才值得參考。這一個需求咋看起來是沒什么問題,也符合我們的邏輯,唯有數據量足夠,我們才能找到較為準確的規律嘛。

但回到我的需求上來說,這可是一個明顯的缺點,在前言我說明的需求上說過這是一個給宿舍甚至是個人使用的推薦系統。

也就是說:

  • 我們無法提供大量數據。

  • 我們很懶,我們最可能是告訴系統我從它的推薦中采納了哪一部的電影,而不會去評分,我們可能告訴它質量是否可以接受,但不會像豆瓣用戶那樣給出0~10的準確分數。
    因此,傳統的推薦算法有很多不適合我需求的地方,但是看問題要看本質。無非就是根據用戶的特性,或者根據商品特性,進行與訓練好的模型進行相似性比較。抓住這些特點,我做了少少的"創新"

  • 不基于用戶的評分作相似度,而是用商品的label做標準
    現在很多商品尤其是音樂或者電影,都會具有自己的label,比如說喜劇,懸疑,其次還有主演,導演等可以作為其特征。電商平臺上也有諸如商品種類衣服,女鞋,包包,等,而某些物品,例如衣服,那么衣服的品牌,size,都可以作為用戶的一個選擇的特征。

  • 用戶模型是動態更新的
    這一點不難理解,如果一個用戶長期使用使用該系統,那么他的選擇中很可能已經覆蓋了大量的label,這時基于label的推薦系統則很難區分該用戶的喜好。這時我們有兩個解決方法。第一個是允許用戶自定義label,比如SF就可以自定義問題或文章的標簽,這樣增大了label的多樣性。當然,這個解決方案只能算一個緩解的方案,要想徹底解決,我覺得需要給特征選定有效期。
    增加有效期后,用戶的選擇可以反應出一個時間段內的需求。假設這樣一個場景,一名用戶準備去旅游了,他可能會大量瀏覽旅游用品的出售頁面,例如一次性牙膏等,這時,就可以向該用戶推薦出售旅行用品的網站了。而超過了特征的有效期,例如一周,這時用戶已經旅游回來,因為特征已經無效,推薦系統不再推薦旅游用品(這樣用戶不會覺得莫名其妙。個人經歷,現在某些網站就往往會出現明顯已經超過我感興趣時限的推薦),而是開始重新收集用戶新一周瀏覽的特征,動態構建用戶模型,推薦用戶下一階段他可能需要的物品
    實現上述想法,在python中,我們可以這么做,實現如下字典

record = {
    "labelName":(weight,time),
    "labelName2":(weight,time)
    ……
}
#labelName是標簽名稱,在該標簽下有一個元組,元組的第一個字段是這個標簽的權重。
#權重越大,表示用戶越喜歡這個標簽。
#第二個字段是創建該標簽的起始時間

在實現推薦時,則較為容易實現,給定testList。這時需要:

  • 創建名res的空字典
  • 遍歷testList,每一個對象命名為t
  • 遍歷t具有的label,根據label從record上獲取信息。
  • 同時獲取當前時間time2,如果time2-time超出了規定時限,則該標簽的信息無效,忽略該label,同時刪除record里面的對應的字段。
  • 若該標簽有效,則t的得分加1,并將t的下標index作為key假如到一個res中
  • 遍歷完成后,對res字典按value排序
  • 最后,可以根據需要對排序結果進行訪問。比如只獲取最高的前5名。
    這樣,一個適合少用戶的推薦系統就弄出來啦~

現在正在宿舍投入運行,至于效果如何可能要一段時間才知道了

后話


github 地址

說明一下,github上只是提供了一個實現了上述改進后思路的類recommend.py,并不是一個成型的推薦系統,你可以下載后,根據這個類進行二次開發,比如:

  • 利用flask框架包裝成一個web應用
  • 結合該類并利用SMTP協議,弄一個自動往郵箱發信息的腳本,推薦的電影信息
  • 將類實例化,弄出簡單的命令行應用

遲下我會上傳一個使用falsk封裝的一個簡單的webserver去github,可以通過web API請求,返回json格式的電影信息。

如有錯誤,望指正。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,563評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,694評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,672評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,965評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,690評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,019評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,013評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,188評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,718評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,438評論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,667評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,149評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,845評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,252評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,590評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,384評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,635評論 2 380

推薦閱讀更多精彩內容