基于随机梯度下降的矩阵分解推荐算法(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实现可将字符转换成大写的tcp服务器实例
Apr 29 Python
解决python matplotlib imshow无法显示的问题
May 24 Python
详解Python3中的迭代器和生成器及其区别
Oct 09 Python
python儿童学游戏编程知识点总结
Jun 03 Python
用python写一个定时提醒程序的实现代码
Jul 22 Python
Pytorch框架实现mnist手写库识别(与tensorflow对比)
Jul 20 Python
用python实现一个简单计算器(完整DEMO)
Oct 14 Python
Python爬虫实现selenium处理iframe作用域问题
Jan 27 Python
秀!学妹看见都惊呆的Python小招数!【详细语言特性使用技巧】
Apr 27 Python
利用Python+OpenCV三步去除水印
May 28 Python
使用qt quick-ListView仿微信好友列表和聊天列表的示例代码
Jun 13 Python
python ConfigParser库的使用及遇到的坑
Feb 12 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
3个PHP多维数组转为一维数组的方法实例
2014/03/13 PHP
浅析PHP的静态成员函数效率更高的原因
2014/06/13 PHP
php以fastCGI的方式运行时文件系统权限问题及解决方法
2015/05/11 PHP
PHP设计模式之观察者模式实例
2016/02/22 PHP
PHP如何将XML转成数组
2016/04/04 PHP
PHP基于XMLWriter操作xml的方法分析
2017/07/17 PHP
PHP实现图的邻接矩阵表示及几种简单遍历算法分析
2017/11/24 PHP
js 屏蔽鼠标右键脚本附破解方法
2009/12/03 Javascript
基于jquery的代码显示区域自动拉长效果
2011/12/07 Javascript
Jquery的Tabs内容轮换效果实现代码,几行搞定
2014/02/12 Javascript
论JavaScript模块化编程
2016/03/07 Javascript
jQuery1.9+中删除了live以后的替代方法
2016/06/17 Javascript
给Easyui-Datebox设置隐藏或者不可用的解决方法
2017/05/26 Javascript
在vue-cli中组件通信的方法
2017/12/16 Javascript
Vue指令v-for遍历输出JavaScript数组及json对象的常见方式小结
2019/02/11 Javascript
VUE渲染后端返回含有script标签的html字符串示例
2019/10/28 Javascript
jQuery实现弹出层效果
2019/12/10 jQuery
vue模块移动组件的实现示例
2020/05/20 Javascript
openlayers4实现点动态扩散
2020/08/17 Javascript
js 图片懒加载的实现
2020/10/21 Javascript
[36:22]VP vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
Python复制文件操作实例详解
2015/11/10 Python
Python列表推导式与生成器表达式用法示例
2018/02/08 Python
python numpy格式化打印的实例
2018/05/14 Python
Python3基于sax解析xml操作示例
2018/05/22 Python
python定时任务 sched模块用法实例
2019/11/04 Python
Python抓包程序mitmproxy安装和使用过程图解
2020/03/02 Python
VSCode基础使用与VSCode调试python程序入门的图文教程
2020/03/30 Python
Python运行提示缺少模块问题解决方案
2020/04/02 Python
python字典按照value排序方法
2020/12/28 Python
公司JAVA开发面试题
2015/04/02 面试题
电大毕业生自我鉴定
2013/11/10 职场文书
小学生防溺水广播稿
2014/01/12 职场文书
大学生简历求职信
2014/06/24 职场文书
社区节水倡议书
2015/04/29 职场文书
如何利用Python实现一个论文降重工具
2021/07/09 Python