如何用深度學習推薦電影?教你做自己的推薦系統!
簡介
幾乎所有人都喜歡與家人、朋友一起觀看電影度過閑暇時光。大家可能都有過這樣的體驗:本想在接下來的兩個小時里看一個電影,卻坐在沙發上坐了20分鐘不知道看什麼,選擇困難症又犯了,結果好心情也變得沮喪。所以,我們很需要一個電腦代理,在做挑選電影的時候提供推薦。
現在,電影智能推薦系統已經成為日常生活中的一部分。
Data Science Central 曾表示:
「雖然硬數據很難獲得,但知情人士估計,對亞馬遜和Netflix這樣的大型電商平台,推薦系統為它們帶來高達10%至25%的收入增長」。
在這個項目中,我研究了一些針對電影推薦的基本演算法,並嘗試將深度學習融入到電影推薦系統中。
把娛樂與視覺藝術相結合,電影是一個很好的例子。電影海報可以直接、快速地把電影信息傳達給觀眾。Design Mantic表示:「不論上映前後,電影海報都是創造噱頭的主要因素。多半的人(目標觀眾)都根據海報來決定買不買票,看不看電影。」我們甚至可以僅僅根據海報字體,來推測這個電影的情緒。
這聽起來有點像魔術——但看一眼海報就預測齣電影的類型,的確是可能的。就拿我來說,瞟一眼海報就知道我想不想看這個電影了。舉個例子,我不是卡通迷,一看到有卡通主題海報,就知道不是我的菜。這個決策的過程很直接,並不需要閱讀電影評論(不確定誰真的有時間讀那些評論)。因此,除了標準的電影推薦演算法,我還用了深度學習來處理海報,並將相似的電影推薦給用戶。最終目標是模仿人類視覺,並僅僅通過觀察海報,就能用深度學習創建一個直觀的電影推薦系統。該項目是受到Ethan Rosenthal博客啟發。我對他博客里的代碼進行了修改,以適應這個項目的演算法。
我們用的是從 MovieLens 下載的電影數據集。他包含9066個電影和671名用戶,分成了100000個打分和1300個標籤。這個數據集最後更新於10/2016.
協同過濾
粗略地說,有三種類型的推薦系統(不包括簡單的評級方法)
基於內容的推薦
協同過濾
混合模型
「基於內容的推薦」是一個回歸問題,我們把電影內容作為特徵,對用戶對電影的評分做預測。
而在「協同過濾」推薦系統中,一般無法提前獲得內容特徵。是通過用戶之間的相似度(用戶們給了用一個電影相同的評級)和電影之間的相似度(有相似用戶評級的電影),來學習潛在特徵,同時預測用戶對電影的評分。此外,學習了電影的特徵之後,我們便可以衡量電影之間的相似度,並根據用戶歷史觀影信息,向他/她推薦最相似的電影。
「基於內容的推薦」和「協同過濾」是10多年前最先進的技術。很顯然,現在有很多模型和演算法可以提高預測效果。比如,針對事先缺乏用戶電影評分信息的情況,可以使用隱式矩陣分解,用偏好和置信度取代用戶電影打分——比如用戶對電影推薦有多少次點擊,以此進行協同過濾。另外,我們還可以將「內容推薦」與「協同過濾」的方法結合起來,將內容作為側面信息來提高預測精度。這種混合方法,可以用「學習進行排序」("Learning to Rank" )演算法來實現。
該項目中,我會聚焦於「協同過濾」方法。首先,我將討論如何不使用回歸,而是電影(用戶)相似度來預測評分,並基於相似度做電影推薦。然後,我將討論如何使用回歸同時學習潛在特徵、做電影推薦。最後會談談如何在推薦系統中使用深度學習。
電影相似性
對於基於協作過濾的推薦系統,首先要建立評分矩陣。其中,每一行表示一個用戶,每一列對應其對某一電影的打分。建立的評分矩陣如下:
df = pd.read_csv( ratings.csv , sep= , )
df_id = pd.read_csv( links.csv , sep= , )
df = pd.merge(df, df_id, on=[ movieId ])
rating_matrix = np.zeros((df.userId.unique().shape[0], max(df.movieId)))
for row in df.itertuples():
rating_matrix[row[1]-1, row[2]-1] = row[3]
rating_matrix = rating_matrix[:,:9000]
這裡「ratings.csv」包含用戶id,電影id, 評級,和時間信息;"link.csv"包括電影id, IMDB id,和TMDB id。每一個電影利用 API 從 Movie Databasewebsite 獲得海報,都需要 IMDB id——因此,我們將兩個表格結合到一起。我們檢驗了評分矩陣的稀疏性,如下:
sparsity = float(len(ratings.nonzero()[0]))
sparsity /= (ratings.shape[0] * ratings.shape[1])
sparsity *= 100
當非零項(entry)只有1.40%的時候評級矩陣是稀疏的。現在,為了訓練和測試,我們將評分矩陣分解成兩個較小的矩陣。我們從評分矩陣中刪除了10個評分,把它們放入測試集。
train_matrix = rating_matrix.copy()
test_matrix = np.zeros(ratings_matrix.shape)
for i in xrange(rating_matrix.shape[0]):
rating_matrix[i, :].nonzero()[0],
size=10,
replace=True)
train_matrix[i, rating_idx] = 0.0
test_matrix[i, rating_idx] = rating_matrix[i, rating_idx]
根據以下公式計算用戶/電影中的(餘弦Cosine) 相似性
這裡s(u,v)是用戶u和v之間的餘弦相似度。
similarity_user = train_matrix.dot(train_matrix.T) + 1e-9
norms = np.array([np.sqrt(np.diagonal(similarity_user))])
similarity_user = ( similarity_user / (norms * norms.T) )
similarity_movie = train_matrix.T.dot(train_matrix) + 1e-9
norms = np.array([np.sqrt(np.diagonal(similarity_movie))])
similarity_movie = ( similarity_movie / (norms * norms.T) )
利用用戶之間的相似性,我們能預測每個用戶對電影的評級,並計算出相應的MSE。該預測基於相似用戶的評分。特別地,可以根據以下公式進行打分預測:
用戶u對電影i的預測,是用戶v對電影的評分的(標準化的)加權和。權重為用戶u和v的相似度。
from sklearn.metrics import mean_squared_error
prediction = similarity_user.dot(train_matrix) / np.array([np.abs(similarity_user).sum(axis=1)]).T
prediction = prediction[test_matrix.nonzero()].flatten()
test_vector = test_matrix[test_matrix.nonzero()].flatten()
mse = mean_squared_error(prediction, test_vector)
print MSE = + str(mse)
預測的MSE為9.8252。這個數字意味著什麼?這個推薦系統是好是壞?僅僅看著MSE結果來評估預測效果不是很符合直覺。因此,我們直接檢查電影推薦來評估。我們將搜索一個感興趣的電影,並讓電腦代理來推薦幾部電影。首先要得到相應的電影海報,這樣就能看到都有什麼電影被推薦。我們使用IMDB id,使用它的API從Movie Database 網站獲取海報。
import requests
import json
from IPython.display import Image
from IPython.display import display
from IPython.display import HTML
idx_to_movie = {}
for row in df_id.itertuples():
idx_to_movie[row[1]-1] = row[2]
idx_to_movie
k = 6
idx = 0
movies = [ idx_to_movie[x] for x in np.argsort(similarity_movie[idx,:])[:-k-1:-1] ]
movies = filter(lambda imdb: len(str(imdb)) == 6, movies)
n_display = 5
URL = [0]*n_display
IMDB = [0]*n_display
i = 0
for movie in movies:
(URL[i], IMDB[i]) = get_poster(movie, base_url)
i += 1
images =
for i in range(n_display):
images += "
float: left; border: 1px solid black; src= %s />"
% URL[i]
display(HTML(images))
好玩的來了!讓我們來搜索一個電影並看看四個最相似的推薦。讓我們試著搜索《盜火線》,在左手邊第一個,後面是四部推薦的電影。
《盜火線》是1995年上映的一部美國犯罪電影,由羅伯特·德·尼羅、阿爾·帕西諾主演。搜索結果看起來不錯。但《離開拉斯維加斯》可能不是一個好的建議,我猜原因是因為電影《勇闖奪命島》里有尼古拉斯·凱奇,《The Rock》,以及對喜歡 《盜火線》的觀眾而言,它是一個不錯的推薦。這可能是相似性矩陣和協同過濾的缺點之一。讓我們試試更多的例子。
這個看起還好。《玩具總動員2》絕對是應該推薦給喜歡《玩具總動員》的觀眾。但是《阿甘正傳》在我看來不合適。顯然,因為湯姆·漢克斯的聲音出現在《玩具總動員》里,所以《阿甘正傳》也被推薦了。值得注意的是,我們可以只看一眼海報就分辨出《玩具總動員》與 《阿甘正傳》的區別,比如電影類型、情緒等。假設每一個小孩都喜歡《玩具總動員》,他們可能會忽略《阿甘正傳》。
交替隨機梯度下降
在前面的討論中,我們簡單地計算了用戶和電影的餘弦相似度,並以此來預測用戶對電影的評分,還根據某電影推薦其它電影。現在,我們可以把問題做為一個回歸問題;對所有的電影加入潛在特徵y,對所有用戶加入權重向量x。目標是將評分預測的(在 2-norm 的正則化條件下)MSE最小化。
雷鋒網提醒:權重向量和特徵向量都是決策變數。顯然,這不是一個凸函數問題,現在也不需要過分擔心這個非凸函數的收斂性。有很多方法能解決非凸函數的優化問題。方法之一就是以交替方式()解決權重向量(對用戶)和特徵向量(對電影)。處理權重向量時,假設特徵向量是常向量;處理特徵向量時,假設權重向量是常向量。解決這個回歸問題的另一種方法,是將權重向量與特徵向量的更新結合起來,在同一個迭代中更新它們。另外,還可以藉助隨機梯度下降來加速計算。這裡,我用隨機梯度下降來解決這個回歸問題,我們的MSE預測如下:
這個MSE比用相似性矩陣得到的,要小得多。當然,我們也可以使用網格搜索和交叉驗證對模型、演算法調參。再看看電影搜索的推薦:
看起來並不是很好。我覺得這四部電影不應該通過搜索《盜火線》推薦給我,他們看起來與《盜火線》完全不相關,這四個電影是浪漫、戲劇類。如果我找的是一部有大明星的美國犯罪電影,我憑什麼會想要看戲劇電影? 這讓我很困惑——一個好的MSE的結果可能會給我們一個風馬牛不相及的推薦。
因此,我們討論一下基於協同過濾的推薦系統的弱點。
協同過濾方法通過使用數據,來發現類似的用戶和電影,這將導致熱門電影比小眾電影更容易被推薦。
由於新上映的電影沒有太多的使用數據,指望協同過濾向用戶推薦任何新電影很不現實。
接下來,我們將考慮採用另一種方法來處理協同過濾問題——用深度學習推薦電影。
深度學習
我們將在Keras中用VGG16來訓練神經網路。我們的數據集中沒有目標,只是將倒數第四層作為一個特徵向量。我們用這個特徵向量,來描述數據集中的每一個電影。雷鋒網提醒,在訓練神經網路之前,還需要做一些預處理,訓練過程如下。
df_id = pd.read_csv( links.csv , sep= , )
idx_to_movie = {}
for row in df_id.itertuples():
idx_to_movie[row[1]-1] = row[2]
total_movies = 9000
movies = [0]*total_movies
for i in range(len(movies)):
if i in idx_to_movie.keys() and len(str(idx_to_movie[i])) == 6:
movies[i] = (idx_to_movie[i])
movies = filter(lambda imdb: imdb != 0, movies)
total_movies = len(movies)
URL = [0]*total_movies
IMDB = [0]*total_movies
URL_IMDB = {"url":[],"imdb":[]}
i = 0
for movie in movies:
(URL[i], IMDB[i]) = get_poster(movie, base_url)
if URL[i] != base_url+"":
URL_IMDB["url"].append(URL[i])
URL_IMDB["imdb"].append(IMDB[i])
i += 1
# URL = filter(lambda url: url != base_url+"", URL)
df = pd.DataFrame(data=URL_IMDB)
total_movies = len(df)
import urllib
poster_path = "/Users/wannjiun/Desktop/nycdsa/project_5_recommender/posters/"
for i in range(total_movies):
urllib.urlretrieve(df.url[i], poster_path + str(i) + ".jpg")
from keras.applications import VGG16
from keras.applications.vgg16 import preprocess_input
from keras.preprocessing import image as kimage
image = [0]*total_movies
x = [0]*total_movies
for i in range(total_movies):
image[i] = kimage.load_img(poster_path + str(i) + ".jpg", target_size=(224, 224))
x[i] = kimage.img_to_array(image[i])
x[i] = np.expand_dims(x[i], axis=0)
x[i] = preprocess_input(x[i])
model = VGG16(include_top=False, weights= imagenet )
prediction = [0]*total_movies
matrix_res = np.zeros([total_movies,25088])
for i in range(total_movies):
prediction[i] = model.predict(x[i]).ravel()
matrix_res[i,:] = prediction[i]
similarity_deep = matrix_res.dot(matrix_res.T)
norms = np.array([np.sqrt(np.diagonal(similarity_deep))])
similarity_deep = similarity_deep / norms / norms.T
在代碼中,我們首先使用API和IMDB id,從TMDB網站獲取電影海報。然後向VGG16提供海報來訓練神經網路。最後,用VGG16學習的特徵來計算餘弦相似性。獲得電影相似性之後,我們可以推薦相似度最高的電影。VGG16總共有25088個學來的特徵,我們使用這些特徵來描述數據集中的每個電影。
來看看使用深度學習的電影推薦系統。
《導火線》不再和愛情戲劇一起出現了!這些電影海報有一些相同的特點:深藍色的、上面還有人物等等。讓我們再來試試《玩具總動員》。
《阿甘正傳》不會再被推薦了!結果看起來不錯,朕心甚慰,再來試試別的!
注意,這些海報里都有一或兩個人,並有冷色系的主題風格。
這些海報想讓觀眾知道相應電影的氛圍歡樂、緊張,並有很多動作鏡頭,所以海報的顏色也很強烈。
不同於上一組,這些海報想告訴觀眾:這些電影講述的是一個單身漢。
我們找到的與《功夫熊貓》類似的電影。
這一組很有趣。一群相似的怪獸以及湯姆·克魯斯!
所有這些海報里都有姿勢類似的女士。等等,那個是奧尼爾!?
成功找到了蜘蛛俠!
這些海報的排版設計很接近。
結論
在推薦系統中有幾種使用深度學習的方法:
無監督學習
從協同過濾中預測潛在特徵
將深度學習生成的特徵作為輔助信息
電影海報具有創造噱頭和興趣的視覺元素。這個項目中,我們使用了無監督深度學習,通過海報來學習電影的相似性。顯然,這只是在推薦系統中使用深度學習的第一步,我們還可以嘗試很多東西。例如,我們可以用深度學習來預測協同過濾生成的潛在特徵。Spotify的音樂推薦也使用了類似的方法,區別於圖像處理,他們通過處理歌曲的聲音,來用深度學習來預測協同過濾中的潛在特徵。還有一個可能的方向。是把深度學習學到的特徵作為輔助信息,來提高預測的準確性。
vianycdatascience,雷鋒字幕組編譯
※為什麼國內智能音箱難敵 Amazon Echo和Google Home?
※遠場語音交互體驗的思考:Alexa 為什麼不用屏幕和多輪對話?
※英偉達股價暴漲17%、5大AI新品,GTC上黃仁勛都講了啥?
TAG:唯物 |
※你有電影推薦給我嗎?
※深度學習在推薦系統上的應用
※「電影推薦」古天樂他的電影怎麼樣?好不好看呢?推薦幾部給你
※我想把這些電影推薦給過去的自己
※推薦一些好看的動漫電影!
※基於深度學習的協同過濾電影推薦系統
※電影推薦 理解孩子的心
※你有哪些值得推薦的好電影?
※有什麼好用的手機推薦嗎?
※美妝博主推薦的,你還不用嗎?
※有哪些好看的動漫推薦?
※電影推薦《摔跤吧!爸爸》
※【好課推薦】材質很難畫嗎?看完這教程不會你打我!
※有什麼好看的電影可以推薦碼?
※她推薦的東西究竟好不好用?
※如何判斷自己是否有,推薦五種矯正運動!
※【推薦】願你遇見更好的自己
※有什麼好的手游神器推薦嗎?
※大劉推薦的硬科幻作者當老師,你不來聽聽他講課嗎?
※動漫推薦——全治癒系動漫推薦,全看過算我輸!