介绍几乎每个人都喜欢和家人朋友一起看电影来度过闲暇时光。每个人可能都有过这样的经历:我想在接下来的两个小时内看一场电影,但我在沙发上坐了20分钟,却不知道该看什么。沮丧的。因此,我们在选择电影时需要一个计算机代理来提供推荐。现在,电影智能推荐系统已经成为日常生活的一部分。DataScienceCentral曾表示:“虽然硬数据很难获得,但据知情人士估计,对于亚马逊、Netflix等大型电商平台而言,推荐系统已经为它们带来了高达10%至25%的收入增长。“在这个项目中,我研究了电影推荐的一些基本算法,并尝试将深度学习融入到电影推荐系统中。将娱乐与视觉艺术相结合,电影就是一个很好的例子。电影海报可以直接、快速地向观众传达电影信息。DesignMantic表示:“无论上映与否,电影海报都是制造噱头的主要因素,大部分人(目标观众)都是根据海报来决定买票还是看电影。”我们甚至可以单独使用海报字体,来揣测电影的意境。这听起来有点像魔法——但只需看一眼海报就可以预测电影的类型。就我而言,看一眼海报就知道我是否想看这部电影。例如,我不喜欢卡通片。一旦我看到一张卡通主题的海报,我就知道这不是我的菜。决策过程很简单,不需要阅读电影评论(不确定谁真正有时间阅读这些评论)。因此,除了标准的电影推荐算法外,我还使用深度学习来处理海报并向用户推荐类似的电影。最终目标是模仿人类视觉,利用深度学习创建一个只看海报就直观的电影推荐系统。这个项目的灵感来自EthanRosenthal的博客。我改编了他博客中的代码以适合该项目的算法。我们使用从MovieLens下载的电影数据集。它包含9066部电影和671个用户,分为100000个评分和1300个标签。该数据集最后更新于10/2016。Collaborativefiltering粗略的说,推荐系统有3种类型(不包括简单的评分方法)电影的评价。在“协同过滤”推荐系统中,一般不可能提前获取内容特征。它使用用户之间的相似性(用户对电影给出相同的评分)和电影之间的相似性(具有相似用户评分的电影)来学习潜在特征并预测用户对电影的评分。此外,在了解电影的特征后,我们可以衡量电影之间的相似度,并根据用户的历史观看信息向用户推荐最相似的电影。“基于内容的推荐”和“协同过滤”在10多年前还是最先进的技术。显然,有许多模型和算法可以提高预测性能。例如,在事先没有用户电影评分信息的情况下,可以使用隐式矩阵分解,用偏好和置信度来代替用户电影评分——比如用户点击了多少次电影推荐,从而进行协同过滤。此外,我们还可以结合“内容推荐”和“协同过滤”的方法,将内容作为辅助信息来提高预测精度。这种混合方法可以通过“LearningtoRank”算法来实现。在这个项目中,我将重点关注“协同过滤”方法。首先,我将讨论如何不使用回归,而是使用电影(用户)相似度来预测评分,并根据相似度进行电影推荐。然后,我将讨论如何使用回归来同时学习潜在特征和进行电影推荐。最后,我将谈谈如何在推荐系统中使用深度学习。电影相似度对于基于协同过滤的推荐系统,第一步是构建评分矩阵。其中,每一行代表一个用户,每一列对应其对某部电影的评分。建立的评分矩阵如下: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.movi??eId)))forrowindf.itertuples():rating_matrix[row[1]-1,row[2]-1]=row[3]rating_matrix=rating_matrix[:,:9000]其中“ratings.csv”包含用户id、电影id、评分、时间信息;“link.csv”包括电影ID、IMDBID和TMDBID。每部使用API从电影数据库网站获取海报的电影都需要一个IMDBid-因此我们将这两个表结合起来。我们测试了评分矩阵的稀疏性如下:sparsity=float(len(ratings.nonzero()[0]))sparsity/=(ratings.shape[0]*ratings.shape[1])sparsity*=100评级矩阵是稀疏的,只有1.40%的非零条目。现在,为了训练和测试,我们将评分矩阵分解为两个较小的矩阵。我们从评分矩阵中删除了10个评分并将它们放入测试集中。train_matrix=rating_matrix.copy()test_matrix=np.zeros(ratings_matrix.shape)foriinxrange(rating_matrix.shape[0]):rating_idx=np.random.choice(rating_matrix[i,:].nonzero()[0],size=10,replace=True)train_matrix[i,rating_idx]=0.0test_matrix[i,rating_idx]=rating_matrix[i,rating_idx]这里根据下面的公式计算用户/电影中的(余弦余弦)相似度s(u,v)是用户u和v之间的余弦相似度。norms*norms.T))similarity_movie=train_matrix。T.dot(train_matrix)+1e-9norms=np.array([np.sqrt(np.diagonal(similarity_movie))])similarity_movie=(similarity_movie/(norms*norms.T))利用用户之间的相似度,我们可以预测每个用户的电影评分并计算相应的MSE。预测基于相似用户的评分。特别地,可以根据以下公式进行评分预测:用户u对电影i的预测是用户v对电影i的评分的(归一化)加权和。权重是用户u和v之间的相似度。fromsklearn.metricsimportmean_squared_errorprediction=similarity_user.dot(train_matrix)/np.array([np.abs(similarity_user).sum(axis=1)]).Tprediction=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结果来评估预测能力不是很直观。因此,我们直接检查电影推荐以进行评估。我们会搜索一部感兴趣的电影,让计算机代理推荐几部电影。首先,你需要拿到相应的电影海报,这样你才能看到推荐的是什么电影。我们使用IMDBid并使用其API从电影数据库网站获取海报。importrequestsimportjsonfromIPython.displayimportImagefromIPython.displayimportdisplayfromIPython.displayimportHTMLidx_to_movie={}forrowindf_id.itertuples():idx_to_movie[row[1]-1]=row[2]idx_to_moviek=6idx=0movies=[idx_to_movie[x]forxinnp.miargity])[:---1:-1]]movies=filter(lambdaimdb:len(str(imdb))==6,movies)n_display=5URL=[0]*n_displayIMDB=[0]*n_displayi=0formovieinmovies:(URL[i],IMDB[i])=get_poster(movie,base_url)i+=1images=''foriinrange(n_display):images+=""\%URL[i]display(HTML(images))乐趣来了!让我们搜索一部电影,看看四个最相似的推荐。让我们尝试搜索《盗火线》,左边第一个,后面是四部推荐电影。《盗火线》是1995年上映的美国犯罪片,由罗伯特·德尼罗和阿尔·帕西诺主演。搜索结果看起来不错。不过《离开拉斯维加斯》可能不是一个好的建议,我猜是因为电影《勇闯夺命岛》里面有尼古拉斯·凯奇,《The Rock》,对于喜欢《盗火线》的人来说,这是一个很好的推荐。这可能是相似度矩阵和协同过滤的缺点之一。让我们尝试更多示例。这个看起来不错。《玩具总动员2》绝对值得推荐给喜欢《玩具总动员》的观众。但是《阿甘正传》对我来说不合适。显然,由于在《玩具总动员》中出现了汤姆·汉克斯的声音,因此《阿甘正传》也出现了。值得注意的是,我们只看海报就可以分辨出《玩具总动员》和《阿甘正传》的区别,比如电影类型、心情等。假设每个孩子都喜欢《玩具总动员》,他们可能会忽略《阿甘正传》。AlternatingStochasticGradientDescent在前面的讨论中,我们简单地计算了用户和电影之间的余弦相似度,以预测用户对电影的评分,并根据电影推荐其他电影。现在,我们可以将问题表述为回归问题;向所有电影添加潜在特征y,向所有用户添加权重向量x。目标是最小化分数预测的MSE(在2范数正则化下)。雷锋网(公众号:雷锋网)提醒:权重向量和特征向量都是决策变量。很明显,这不是凸函数问题,现在不用太担心这个非凸函数的收敛性。解决非凸函数优化问题的方法有很多种。一种方法是以交替方式()求解权重向量(对于用户)和特征向量(对于电影)。在处理权重向量时,假设特征向量是常数向量;在处理特征向量时,假设权重向量是常数向量。解决这个回归问题的另一种方法是将权重向量的更新与特征向量的更新结合起来,在同一次迭代中更新它们。此外,还可以使用随机梯度下降来加速计算。在这里,我使用随机梯度下降来解决这个回归问题,我们的MSE预测如下:这个MSE比使用相似矩阵得到的要小很多。当然,我们也可以使用网格搜索和交叉验证来调优模型和算法。看看电影搜索推荐:看起来不太好。我觉得这四部电影不应该通过搜索《盗火线》来推荐给我,它们似乎与《盗火线》完全无关,这四部电影是爱情和戏剧。如果我要找一部有大明星的美国犯罪电影,我为什么要看剧情片呢?这让我感到困惑-一个好的MSE结果可能会给我们一个不相关的推荐。因此,我们讨论了基于协同过滤的推荐系统的弱点。协同过滤方法使用数据来发现相似的用户和电影,这将导致热门电影比小众电影被推荐更多。由于新上映电影的使用数据不多,因此期望协同过滤向用户推荐任何新电影是不现实的。接下来,我们将考虑另一种解决协同过滤问题的方法——用深度学习推荐电影。深度学习我们将在Keras中使用VGG16来训练神经网络。我们的数据集中没有对象,只有倒数第二层作为特征向量。我们使用这个特征向量来描述数据集中的每部电影。雷锋网提醒,在训练神经网络之前,需要进行一些预处理。训练过程如下。df_id=pd.read_csv('links.csv',sep=',')idx_to_movie={}forrowindf_id.itertuples():idx_to_movie[row[1]-1]=row[2]total_movies=9000movies=[0]*total_moviesforiinrange(len(movies)):ifiinidx_to_movie.keys()andlen(str(idx_to_movie[i]))==6:movies[i]=(idx_to_movie[i])movies=filter(lambdaimdb:imdb!=0,movies)total_movies=len(movies)URL=[0]*total_moviesIMDB=[0]*total_moviesURL_IMDB={"url":[],"imdb":[]}i=0formovieinmovies:(URL[i],IMDB[i])=get_poster(movie,base_url)ifURL[i]!=base_url+"":URL_IMDB["url"].append(URL[i])URL_IMDB["imdb"].append(IMDB[i])i+=1#URL=filter(lambdaurl:url!=base_url+"",URL)df=pd.DataFrame(data=URL_IMDB)total_movies=len(df)importurllibposter_path="/Users/wannjiun/Desktop/nycdsa/project_5_recommender/posters/"foriinrange(total_movies):urllib.urlretrieve(df.url[i],poster_path+str(i)+".jpg")fromkeras.applicationsimportVGG16fromkeras.applications.vgg16importpreprocess_inputfromkeras.preprocessingimportimageaskimageimage=[0]*total_moviesx=[0]*total_moviesforiinrange(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,权重='imagenet')prediction=[0]*total_moviesmatrix_res=np.zeros([total_movies,25088])foriinrange(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和IMDBid,从TMDB网站获取电影海报,然后将海报提供给VGG16以训练神经网络。最后,VGG16学习到的特征用于计算余弦相似度。得到电影相似度后,我们就可以推荐相似度最高的电影。VGG16总共有25088个学习特征,我们用它们来描述数据集中的每部电影。看一看使用深度学习的电影推荐系统。《导火线》不再附送爱情剧!这些电影海报有一些共同的特点:深蓝色,上面有人物等等。让我们再试一试《玩具总动员》。《阿甘正传》不会再推荐!结果看起来不错,我很放心,我会尝试别的!请注意,这些海报中都有一两个人,并且主题很酷。这些海报让观众知道对应电影的气氛是欢乐的、紧张的,而且有很多动作镜头,所以海报的色彩也很浓。与上一组不同的是,这些海报想告诉观众:这些电影是关于单身汉的。我们找到了与《功夫熊猫》类似的电影。这组很好玩一堆和汤姆克鲁斯相似的怪物!所有这些海报都有相似姿势的女性。等等,那是奥尼尔!?成功找到蜘蛛侠!这些海报的排版设计很接近。结论有几种方法可以在推荐系统中使用深度学习:无监督学习从协同过滤中预测潜在特征使用深度学习生成的特征作为辅助信息电影海报中的视觉元素会制造噱头和趣味。在这个项目中,我们使用无监督深度学习从海报中学习电影相似度。显然,这只是在推荐系统中使用深度学习的第一步,还有很多事情我们可以尝试。例如,我们可以使用深度学习来预测协同过滤产生的潜在特征。Spotify的音乐推荐也采用了类似的方法,区别于图像处理。他们使用深度学习通过处理歌曲的声音来预测协同过滤中的潜在特征。还有一种可能的方向。就是利用深度学习学习到的特征作为辅助信息,提高预测的准确性。