輸入
輸入1:包含200部電影的數據集,集合中包含兩列,一列為電影的id,一列為電影的流派集合,如下圖所示:
輸入2:一個用戶的電影興趣記錄,like字段為1表示喜歡,0表示不喜歡,如下圖所示:
輸出
輸出1:輸入1的One-Hot編碼形式,類似下圖所示:
輸出2:根據輸入2和輸出1,從電影數據集中給用戶推薦用戶沒有看過的與用戶相似度最高的k個電影。
前言
基於內容的推薦算法是一種比較經典的推薦算法,應用較廣,可解釋性強,准確率高,尤其是當今社會信息豐富,比如文本、音頻等,有比較多的內容可以利用。但是對於一個一無所知的新用戶而言,無法針對用戶內容進行推薦,只能根據其他算法進行推薦,用戶產生內容后才能很好的利用基於內容的推薦算法,這也就是冷啟動問題,也是該算法的缺點。
原理
一、用戶畫像
做好一個推薦系統,分為以下3步:
- 認識用戶
- 給用戶推薦他感興趣的東西
- 觀察各項業務指標,一直迭代1,2,3循環下去
上面提到的認識用戶就是用戶畫像,用戶畫像是一個比較抽象的概念,推薦系統的用戶畫像是給機器用的。推薦系統要在用戶和物品之間建立連接,一般的連接方式是對用戶和物品之間的匹配進行評分,也就是預測用戶的偏好,我們首先要將用戶和物品都表示成向量,這樣才能讓機器進行計算,用戶向量化后的結果就是用戶畫像。
那么一般情況下怎么構建用戶畫像呢?按照對用戶向量化的手段來分,用戶畫像的構建方法有以下3類:
- 查戶口。直接使用原始的數據作為用戶畫像的內容,比如注冊信息、購買歷史,這種方法實現簡單,尤其對於新用戶有效,適用於冷啟動等場景;
- 堆數據。統計用戶的歷史數據,先給物品打上標簽,然后獲取用戶在這些標簽上的行為,從標簽維度做數據統計,用統計結果作為量化結果,這一類數據貢獻了常見的用戶畫像;
- 機器學習的方法。學習出人類無法理解的稠密向量,比如使用矩陣分解得到的隱因子或者深度學習得到的Embedding向量,這一類用戶畫像數據通常可解釋性較弱。
構建用戶畫像的關鍵因素有哪些呢?主要是以下兩方面:
- 維度。每個維度的名稱都是可理解的,比如對於一個人而言,維度可能有性別、年齡、學歷等,有些維度值是固定的,有些是在不斷變化的。
- 量化。對每個維度進行量化,比如性別男、年齡22、學歷本科等,有一些維度的量化主觀上給不准確,就需要把量化交給機器,根據推薦效果的好壞來繁項優化用戶的畫像,因為用戶的興趣愛好隨着時間是變化的,比如原本喜歡文學的用戶,某一天不喜歡看文學的書了(給他推薦了文學的書而沒有購買或者是購買記錄里沒有文學相關的書籍),而是買了AI相關的書籍,那么推薦系統就可以給他推薦AI相關的書籍,如果用戶發生了相關的購買行為,那么用戶的讀書偏好就要動態進行更新和量化。
二、挖掘標簽
文本數據是互聯網產品中常見的信息,挖掘興趣標簽主要處理的就是用戶的一些操作行為產生的文本數據。
用戶一端的文本數據,主要有:
- 注冊資料中的一些信息;
- 用戶自己產生的一些內容,比如評論、收藏、購買等行為;
- 與用戶發生了聯系的信息,比如閱讀的內容等。
物品一段的文本數據,主要有:
- 物品本身的描述、介紹;
- 物品本身的內容和屬性。
可以利用一些成熟的NLP算法分析物品端的文本信息提取一些關鍵詞作為標簽,常用的方法有TF-IDF等。
三、推薦操作
當我們有了物品的標簽和用戶的一些行為后,就可以根據這些信息給用戶推薦產品,現住的問題是,到底是物品的哪些特性吸引了用戶呢?一種方法是直接把用戶產生過行為的物品標簽累計在一起,作為用戶的用戶畫像,計算用戶與物品的相似度,給用戶推薦最相似的TopN個物品。
python代碼實現
1 import numpy as np 2 import pandas as pd 3 4 movieFile = './movies.csv' 5 movieData = pd.read_csv(movieFile,encoding='gb2312') 6 print('len:{}'.format(len(movieData))) 7 8 # 將genres轉化為One-Hot編碼的形式 9 genre_iter = (set(x.split('|')) for x in movieData.genres) 10 genres = sorted(set.union(*genre_iter)) 11 tmpDF = pd.DataFrame(np.zeros(((len(movieData),len(genres)))), columns=genres) 12 for i , gens in enumerate(movieData.genres): 13 tmpDF.ix[i,gens.split('|')] = 1 14 15 # 把tmpDF合並到movieData 16 movieData = movieData.join(tmpDF) 17 movieData.to_csv('wyb.csv') 18 19 # 讀取樣本數據 20 samplesFile = './samples.csv' 21 samplesData = pd.read_csv(samplesFile,encoding='gb2312') 22 print('len:{}'.format(len(samplesData))) 23 # 把genres得到的One-Hot編碼形式的數據合並到樣本中,為了后面計算用戶的特征向量使用 24 samplesData = samplesData[samplesData['like'] == 1] 25 mergeData = pd.merge(samplesData, movieData, on='movieId', how='left') 26 mergeData.to_csv('ctt.csv') 27 # 計算樣本用戶的特征向量 28 userFeatureVector = [] 29 for label in genres: 30 userFeatureVector.append(mergeData[label].sum()) 31 userFeatureVector = np.array(userFeatureVector) 32 # 在移除用戶已經看過的電影,只推薦用戶沒有看過的 33 movieData = movieData[~movieData['movieId'].isin(mergeData['movieId'])] 34 # 鍵為電影ID,值為電影與用戶的余弦相似度 35 info_recom = {} 36 for row in range(0, len(movieData)): 37 rowData = movieData.iloc[row, 2:21] 38 itemId = movieData.iloc[row, 0] 39 itemFeatureVec = np.array(rowData) 40 similarity = np.dot(itemFeatureVec, userFeatureVector)/(np.linalg.norm(itemFeatureVec) * np.linalg.norm(userFeatureVector)) 41 info_recom[itemId] = similarity 42 43 # 字典元素按值大小從大到小排序 44 result = sorted(info_recom.items(),key=lambda x:x[1], reverse=True) 45 # 推薦最相似的10部電影 46 topTen = 10 47 for index in range(0,topTen): 48 print('recom top[{}]:{}'.format(index, result[index][0]))
代碼運行結果
本文代碼是在已知電影集標簽和一個用戶的興趣記錄的情況下,給一個用戶推薦的相似度前10的電影。推薦的電影id為:
1 recom top[0]:4 2 recom top[1]:11 3 recom top[2]:45 4 recom top[3]:52 5 recom top[4]:58 6 recom top[5]:94 7 recom top[6]:195 8 recom top[7]:224 9 recom top[8]:232 10 recom top[9]:72