基于随机梯度下降的矩阵分解推荐算法(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数据库操作常用功能使用详解(创建表/插入数据/获取数据)
Dec 06 Python
Python中字典的setdefault()方法教程
Feb 07 Python
python使用opencv按一定间隔截取视频帧
Mar 06 Python
Python中shapefile转换geojson的示例
Jan 03 Python
pytorch中的transforms模块实例详解
Dec 31 Python
浅谈pytorch torch.backends.cudnn设置作用
Feb 20 Python
Python网络爬虫信息提取mooc代码实例
Mar 06 Python
python实现最速下降法
Mar 24 Python
jupyter notebook 添加kernel permission denied的操作
Apr 21 Python
属性与 @property 方法让你的python更高效
Sep 21 Python
Python 实现国产SM3加密算法的示例代码
Sep 21 Python
Django实现聊天机器人
May 31 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
资料注册后发信小技巧
2006/10/09 PHP
PHP判断表单复选框选中状态完整例子
2014/06/24 PHP
typecho插件编写教程(五):核心代码
2015/05/28 PHP
yii2 url重写并隐藏index.php方法
2018/12/10 PHP
js获取单选按钮的数据
2006/11/27 Javascript
DOMAssitant最新版 DOMAssistant 2.5发布
2007/12/25 Javascript
常用简易JavaScript函数
2009/04/09 Javascript
Javascript select下拉框操作常用方法
2009/11/09 Javascript
基于Jquery实现的一个图片滚动切换
2012/06/21 Javascript
一个支持任意尺寸的图片上下左右滑动效果
2014/08/24 Javascript
JavaScript italics方法入门实例(把字符串显示为斜体)
2014/10/17 Javascript
node.js中的fs.appendFileSync方法使用说明
2014/12/17 Javascript
JavaScript获取当前日期是星期几的方法
2015/04/06 Javascript
node.js下LDAP查询实例分享
2015/09/30 Javascript
jQuery实现鼠标经过事件的延时处理效果
2020/08/20 Javascript
实例详解ECMAScript5中新增的Array方法
2016/04/05 Javascript
全面了解javascript三元运算符
2016/06/27 Javascript
在Web项目中引入Jquery插件报错的完美解决方案(图解)
2016/09/19 Javascript
Bootstrap进度条实现代码解析
2017/03/07 Javascript
浅谈Vuex@2.3.0 中的 state 支持函数申明
2017/11/22 Javascript
修改vue+webpack run build的路径方法
2018/09/01 Javascript
JavaScript创建防篡改对象的方法分析
2018/12/30 Javascript
详解Vue-Router源码分析路由实现原理
2019/05/15 Javascript
jquery实现掷骰子小游戏
2019/10/24 jQuery
详解JSON.stringify()的5个秘密特性
2020/05/26 Javascript
Vue props中Object和Array设置默认值操作
2020/07/30 Javascript
vue 内联样式style中的background用法说明
2020/08/05 Javascript
Django之Mode的外键自关联和引用未定义的Model方法
2018/12/15 Python
对python 自定义协议的方法详解
2019/02/13 Python
解决pyinstaller打包发布后的exe文件打开控制台闪退的问题
2019/06/21 Python
基于Python爬取京东双十一商品价格曲线
2020/10/23 Python
python 视频下载神器(you-get)的具体使用
2021/01/06 Python
德国圣伯纳德草药屋:Kräuterhaus Sanct Bernhard(有中文站)
2018/08/05 全球购物
Dockers鞋官网:Dockers Shoes
2018/11/13 全球购物
合伙购房协议样本
2014/10/06 职场文书
python中sys模块的介绍与实例
2021/04/17 Python