基于随机梯度下降的矩阵分解推荐算法(python)


Posted in Python onAugust 31, 2018

SVD是矩阵分解常用的方法,其原理为:矩阵M可以写成矩阵A、B与C相乘得到,而B可以与A或者C合并,就变成了两个元素M1与M2的矩阵相乘可以得到M。

矩阵分解推荐的思想就是基于此,将每个user和item的内在feature构成的矩阵分别表示为M1与M2,则内在feature的乘积得到M;因此我们可以利用已有数据(user对item的打分)通过随机梯度下降的方法计算出现有user和item最可能的feature对应到的M1与M2(相当于得到每个user和每个item的内在属性),这样就可以得到通过feature之间的内积得到user没有打过分的item的分数。

本文所采用的数据是movielens中的数据,且自行切割成了train和test,但是由于数据量较大,没有用到全部数据。

代码如下:

# -*- coding: utf-8 -*-
"""
Created on Mon Oct 9 19:33:00 2017
@author: wjw
"""
import pandas as pd
import numpy as np
import os
 
def difference(left,right,on): #求两个dataframe的差集
 df = pd.merge(left,right,how='left',on=on) #参数on指的是用于连接的列索引名称
 left_columns = left.columns
 col_y = df.columns[-1] # 得到最后一列
 df = df[df[col_y].isnull()]#得到boolean的list
 df = df.iloc[:,0:left_columns.size]#得到的数据里面还有其他同列名的column
 df.columns = left_columns # 重新定义columns
 return df
 
def readfile(filepath): #读取文件,同时得到训练集和测试集
 
 pwd = os.getcwd()#返回当前工程的工作目录
 os.chdir(os.path.dirname(filepath))
 #os.path.dirname()获得filepath文件的目录;chdir()切换到filepath目录下
 initialData = pd.read_csv(os.path.basename(filepath))
 #basename()获取指定目录的相对路径
 os.chdir(pwd)#回到先前工作目录下
 predData = initialData.iloc[:,0:3] #将最后一列数据去掉
 newIndexData = predData.drop_duplicates()
 trainData = newIndexData.sample(axis=0,frac = 0.1) #90%的数据作为训练集
 testData = difference(newIndexData,trainData,['userId','movieId']).sample(axis=0,frac=0.1)
 return trainData,testData
 
def getmodel(train):
 slowRate = 0.99
 preRmse = 10000000.0
 max_iter = 100
 features = 3
 lamda = 0.2
 gama = 0.01 #随机梯度下降中加入,防止更新过度
 user = pd.DataFrame(train.userId.drop_duplicates(),columns=['userId']).reset_index(drop=True) #把在原来dataFrame中的索引重新设置,drop=True并抛弃
 
 movie = pd.DataFrame(train.movieId.drop_duplicates(),columns=['movieId']).reset_index(drop=True)
 userNum = user.count().loc['userId'] #671
 movieNum = movie.count().loc['movieId'] 
 userFeatures = np.random.rand(userNum,features) #构造user和movie的特征向量集合
 movieFeatures = np.random.rand(movieNum,features)
 #假设每个user和每个movie有3个feature
 userFeaturesFrame =user.join(pd.DataFrame(userFeatures,columns = ['f1','f2','f3']))
 movieFeaturesFrame =movie.join(pd.DataFrame(movieFeatures,columns= ['f1','f2','f3']))
 userFeaturesFrame = userFeaturesFrame.set_index('userId')
 movieFeaturesFrame = movieFeaturesFrame.set_index('movieId') #重新设置index
 
 for i in range(max_iter): 
  rmse = 0
  n = 0
  for index,row in user.iterrows():
   uId = row.userId
   userFeature = userFeaturesFrame.loc[uId] #得到userFeatureFrame中对应uId的feature
 
   u_m = train[train['userId'] == uId] #找到在train中userId点评过的movieId的data
   for index,row in u_m.iterrows(): 
    u_mId = int(row.movieId)
    realRating = row.rating
    movieFeature = movieFeaturesFrame.loc[u_mId] 
 
    eui = realRating-np.dot(userFeature,movieFeature)
    rmse += pow(eui,2)
    n += 1
    userFeaturesFrame.loc[uId] += gama * (eui*movieFeature-lamda*userFeature) 
    movieFeaturesFrame.loc[u_mId] += gama*(eui*userFeature-lamda*movieFeature)
  nowRmse = np.sqrt(rmse*1.0/n)
  print('step:%f,rmse:%f'%((i+1),nowRmse))
  if nowRmse<preRmse:
   preRmse = nowRmse
  elif nowRmse<0.5:
   break
  elif nowRmse-preRmse<=0.001:
   break
  gama*=slowRate
 return userFeaturesFrame,movieFeaturesFrame
 
def evaluate(userFeaturesFrame,movieFeaturesFrame,test):
 test['predictRating']='NAN' # 新增一列
 
 for index,row in test.iterrows(): 
  
  print(index)
  userId = row.userId
  movieId = row.movieId
  if userId not in userFeaturesFrame.index or movieId not in movieFeaturesFrame.index:
   continue
  userFeature = userFeaturesFrame.loc[userId]
  movieFeature = movieFeaturesFrame.loc[movieId]
  test.loc[index,'predictRating'] = np.dot(userFeature,movieFeature) #不定位到不能修改值
  
 return test 
 
if __name__ == "__main__":
 filepath = r"E:\学习\研究生\推荐系统\ml-latest-small\ratings.csv"
 train,test = readfile(filepath)
 userFeaturesFrame,movieFeaturesFrame = getmodel(train)
 result = evaluate(userFeaturesFrame,movieFeaturesFrame,test)

在test中得到的结果为:

基于随机梯度下降的矩阵分解推荐算法(python)

NAN则是训练集中没有的数据

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
使用Python的Flask框架实现视频的流媒体传输
Mar 31 Python
python输出指定月份日历的方法
Apr 23 Python
Python解析最简单的验证码
Jan 07 Python
Python求算数平方根和约数的方法汇总
Mar 09 Python
python如何在终端里面显示一张图片
Aug 17 Python
python引入导入自定义模块和外部文件的实例
Jul 24 Python
python 判断网络连通的实现方法
Apr 22 Python
python通过安装itchat包实现微信自动回复收到的春节祝福
Jan 19 Python
python如何提取英语pdf内容并翻译
Mar 03 Python
Python 开发工具通过 agent 代理使用的方法
Sep 27 Python
分享一个python的aes加密代码
Dec 22 Python
python 管理系统实现mysql交互的示例代码
Dec 06 Python
python实现梯度下降算法
Mar 24 #Python
wtfPython—Python中一组有趣微妙的代码【收藏】
Aug 31 #Python
opencv python 图像去噪的实现方法
Aug 31 #Python
python+numpy+matplotalib实现梯度下降法
Aug 31 #Python
python实现随机梯度下降法
Mar 24 #Python
python实现决策树分类(2)
Aug 30 #Python
python实现决策树分类
Aug 30 #Python
You might like
雄兵连三大错觉:凯莎没了,凉冰阵亡了,华烨觉得自己又行了
2020/04/09 国漫
站长助手-网站web在线管理程序 v1.0 下载
2007/05/12 PHP
Yii数据库缓存实例分析
2016/03/29 PHP
PHP实现将上传图片自动缩放到指定分辨率,并保持清晰度封装类示例
2019/06/17 PHP
php5.3/5.4/5.5/5.6/7常见新增特性汇总整理
2020/02/27 PHP
imagettftext() 失效,不起作用
2021/03/09 PHP
fckeditor粘贴Word时弹出窗口取消的方法
2014/10/30 Javascript
js检测离开或刷新页面时表单数据是否更改的方法
2016/08/02 Javascript
JavaScript自动点击链接 防止绕过浏览器访问的方法
2017/01/19 Javascript
jQuery实现选中行变色效果(实例讲解)
2017/07/06 jQuery
Three.js利用顶点绘制立方体的方法详解
2017/09/27 Javascript
AnglarJs中的上拉加载实现代码
2018/02/08 Javascript
angularjs 获取默认选中的单选按钮的value方法
2018/02/28 Javascript
jQuery实现的简单获取索引功能示例
2018/06/04 jQuery
微信小程序日历效果
2018/12/29 Javascript
通过图带你深入了解vue的响应式原理
2019/06/21 Javascript
vue-router路由模式详解(小结)
2019/08/26 Javascript
基于layui内置模块(element常用元素的操作)
2019/09/20 Javascript
vue项目中锚点定位替代方式
2019/11/13 Javascript
[00:20]DOTA2荣耀之路7:-ah fu-抢盾
2018/05/31 DOTA
Python正则表达式使用经典实例
2016/06/21 Python
python 二分查找和快速排序实例详解
2017/10/13 Python
Python内置函数——__import__ 的使用方法
2017/11/24 Python
运行django项目指定IP和端口的方法
2018/05/14 Python
django 发送邮件和缓存的实现代码
2018/07/18 Python
pandas每次多Sheet写入文件的方法
2018/12/10 Python
Python中zip()函数的简单用法举例
2019/09/02 Python
使用TFRecord存取多个数据案例
2020/02/17 Python
Python print不能立即打印的解决方式
2020/02/19 Python
详解canvas绘图时遇到的跨域问题
2018/03/22 HTML / CSS
世界领先的艺术图书出版社:TASCHEN
2018/07/23 全球购物
英语系毕业生求职信
2014/07/13 职场文书
2014年打非治违工作总结
2014/11/13 职场文书
2016年大学生寒假社会实践心得体会
2015/10/09 职场文书
品牌形象定位,全面分析
2019/07/23 职场文书
互联网的下一个风口:新的独角兽将诞生
2019/08/02 职场文书