基于随机梯度下降的矩阵分解推荐算法(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脚本
Feb 10 Python
python实现计算资源图标crc值的方法
Oct 05 Python
python多进程操作实例
Nov 21 Python
Python操作CouchDB数据库简单示例
Mar 10 Python
用Python制作简单的钢琴程序的教程
Apr 01 Python
Django中对数据查询结果进行排序的方法
Jul 17 Python
Python线性拟合实现函数与用法示例
Dec 13 Python
pycharm配置当鼠标悬停时快速提示方法参数
Jul 31 Python
Python字典推导式将cookie字符串转化为字典解析
Aug 10 Python
python中if及if-else如何使用
Jun 02 Python
Python unittest discover批量执行代码实例
Sep 08 Python
Python识别处理照片中的条形码
Nov 16 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+AJAX聊天程序[聊天室]提供下载
2007/07/21 PHP
PHP Header用于页面跳转要注意的几个问题总结
2008/10/03 PHP
php简单开启gzip压缩方法(zlib.output_compression)
2013/04/13 PHP
PHP中echo,print_r与var_dump区别分析
2014/09/29 PHP
浅谈PHP正则表达式中修饰符/i, /is, /s, /isU
2014/10/21 PHP
使用script的src实现跨域和类似ajax效果
2014/11/10 Javascript
jQuery EasyUI实现右键菜单变灰不可用效果
2015/09/24 Javascript
jquery文字填写自动高度的实现方法
2016/11/07 Javascript
深入浅析AngularJS中的一次性数据绑定 (bindonce)
2017/05/11 Javascript
jQuery基于cookie实现换肤功能实例
2017/10/14 jQuery
NestJs 静态目录配置详解
2019/03/12 Javascript
详解vue中axios的使用与封装
2019/03/20 Javascript
浅谈redux, koa, express 中间件实现对比解析
2019/05/23 Javascript
将Vue组件库更换为按需加载的方法步骤
2020/05/06 Javascript
在vue项目中promise解决回调地狱和并发请求的问题
2020/11/09 Javascript
浅谈Python中用datetime包进行对时间的一些操作
2016/06/23 Python
Python计时相关操作详解【time,datetime】
2017/05/26 Python
Python神奇的内置函数locals的实例讲解
2019/02/22 Python
Python+opencv 实现图片文字的分割的方法示例
2019/07/04 Python
python实现数据清洗(缺失值与异常值处理)
2019/12/02 Python
Python动态导入模块和反射机制详解
2020/02/18 Python
Python模拟伯努利试验和二项分布代码实例
2020/05/27 Python
台湾租车首选品牌:IWS艾维士租车
2019/05/03 全球购物
护士演讲稿范文
2014/01/05 职场文书
法学个人求职信范文
2014/01/27 职场文书
竞选大队委员演讲稿
2014/04/28 职场文书
小学课外活动总结
2014/07/09 职场文书
五心教育心得体会
2014/09/04 职场文书
小学生运动会通讯稿
2014/09/23 职场文书
2014年班组工作总结
2014/11/20 职场文书
2014年社区教育工作总结
2014/12/02 职场文书
2014年科研工作总结
2014/12/03 职场文书
文言文辞职信
2015/02/28 职场文书
工作服管理制度范本
2015/08/06 职场文书
Nginx实现会话保持的两种方式
2022/03/18 Servers
SQL Server数据库查询出现阻塞之性能调优
2022/04/10 SQL Server