基于随机梯度下降的矩阵分解推荐算法(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基于pygame实现的弹力球效果(附源码)
Nov 11 Python
python基础教程之Filter使用方法
Jan 17 Python
Python django实现简单的邮件系统发送邮件功能
Jul 14 Python
Python绘制七段数码管实例代码
Dec 20 Python
Python tkinter事件高级用法实例
Jan 31 Python
python实现坦克大战游戏 附详细注释
Mar 27 Python
Python with语句和过程抽取思想
Dec 23 Python
Python 解析pymysql模块操作数据库的方法
Feb 18 Python
python生成大写32位uuid代码
Mar 03 Python
windows支持哪个版本的python
Jul 03 Python
大数据分析用java还是Python
Jul 06 Python
Python如何输出警告信息
Jul 30 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
一个简单的PHP入门源程序
2006/10/09 PHP
PHP 函数执行效率的小比较
2010/10/17 PHP
php数组中删除元素的实现代码
2012/06/22 PHP
深入php中var_dump方法的使用详解
2013/06/24 PHP
php获取中文拼音首字母类和函数分享
2014/04/24 PHP
深入理解PHP之源码目录结构与功能说明
2016/06/01 PHP
phpStudy配置多站点多域名和多端口的方法
2017/09/01 PHP
详细解读php的命名空间(二)
2018/02/21 PHP
laravel 事件/监听器实例代码
2019/04/12 PHP
ThinkPHP3.2框架自带分页功能实现方法示例
2019/05/13 PHP
在 Laravel 项目中使用 webpack-encore的方法
2019/07/21 PHP
解决laravel5.4下的group by报错的问题
2019/10/16 PHP
nginx 设置多个站跨域
2021/03/09 Servers
css图片自适应大小
2007/11/28 Javascript
使用JSLint提高JS代码质量方法分享
2013/12/16 Javascript
jQuery后代选择器用法实例
2014/12/23 Javascript
js中的触发事件对象event.srcElement与event.target详解
2017/03/15 Javascript
js动态设置select下拉菜单的默认选中项实例
2018/08/21 Javascript
jQuery+Datatables实现表格批量删除功能【推荐】
2018/10/24 jQuery
Vue项目引发的「过滤器」使用教程
2019/03/12 Javascript
vue.js实现简单购物车功能
2020/05/30 Javascript
[01:01:18]VP vs NIP 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/17 DOTA
Python专用方法与迭代机制实例分析
2014/09/15 Python
Python根据区号生成手机号码的方法
2015/07/08 Python
不同版本中Python matplotlib.pyplot.draw()界面绘制异常问题的解决
2017/09/24 Python
深入了解Python中pop和remove的使用方法
2018/01/09 Python
Python决策树之基于信息增益的特征选择示例
2018/06/25 Python
python 从文件夹抽取图片另存的方法
2018/12/04 Python
python处理multipart/form-data的请求方法
2018/12/26 Python
Python当中的array数组对象实例详解
2019/06/12 Python
python如何以表格形式打印输出的方法示例
2019/06/21 Python
西班牙用户之间买卖视频游戏的平台:Wakkap
2020/03/21 全球购物
物流司机岗位职责
2013/12/28 职场文书
幼儿园小班家长寄语
2014/04/02 职场文书
2014党的群众路线教育实践活动总结报告
2014/10/31 职场文书
nginx共享内存的机制详解
2022/03/21 Servers