基于随机梯度下降的矩阵分解推荐算法(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实现的Kmeans++算法实例
Apr 26 Python
轻松掌握python设计模式之策略模式
Nov 18 Python
详解如何使用Python编写vim插件
Nov 28 Python
[原创]教女朋友学Python3(二)简单的输入输出及内置函数查看
Nov 30 Python
python numpy实现文件存取的示例代码
May 26 Python
Python数据分析模块pandas用法详解
Sep 04 Python
在tensorflow中设置使用某一块GPU、多GPU、CPU的操作
Feb 07 Python
python的Jenkins接口调用方式
May 12 Python
详解python变量与数据类型
Aug 25 Python
python 合并多个excel中同名的sheet
Jan 22 Python
Python字典和列表性能之间的比较
Jun 07 Python
仅用几行Python代码就能复制她的U盘文件?
Jun 26 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 验证码制作(网树注释思想)
2009/07/20 PHP
php+redis实现多台服务器内网存储session并读取示例
2017/01/12 PHP
用 JSON 处理缓存
2007/04/27 Javascript
js中更短的 Array 类型转换
2011/10/30 Javascript
js数组Array sort方法使用深入分析
2013/02/21 Javascript
jQuery判断checkbox是否选中的小例子
2013/12/02 Javascript
为jQuery添加Webkit的触摸的方法分享
2014/02/02 Javascript
js实现点击后将文字或图片复制到剪贴板的方法
2014/08/04 Javascript
javascript 回调函数详解
2014/11/11 Javascript
jQuery中hasClass()方法用法实例
2015/01/06 Javascript
基于js实现投票的实例代码
2015/08/04 Javascript
js实现文件上传表单域美化特效
2015/11/02 Javascript
jquery制作属于自己的select自定义样式
2015/11/23 Javascript
jQuery 常见小例汇总
2016/12/14 Javascript
jQuery实现Table表格隔行变色及高亮显示当前选择行效果示例
2017/02/14 Javascript
深究AngularJS中ng-drag、ng-drop的用法
2017/06/12 Javascript
如何抽象一个Vue公共组件
2017/10/17 Javascript
使用Vuex解决Vue中的身份验证问题
2018/09/28 Javascript
RxJS的入门指引和初步应用
2019/06/15 Javascript
js实现微信聊天效果
2020/08/09 Javascript
vue实现简单加法计算器
2020/10/22 Javascript
vue使用keep-alive实现组件切换时保存原组件数据方法
2020/10/30 Javascript
[56:13]DOTA2-DPC中国联赛定级赛 LBZS vs Phoenix BO3第一场 1月10日
2021/03/11 DOTA
Python实现的最近最少使用算法
2015/07/10 Python
python爬虫的数据库连接问题【推荐】
2018/06/25 Python
对PyQt5中的菜单栏和工具栏实例详解
2019/06/20 Python
Python交互式图形编程的实现
2019/07/25 Python
tesserocr与pytesseract模块的使用方法解析
2019/08/30 Python
解决python多线程报错:AttributeError: Can't pickle local object问题
2020/04/08 Python
电台实习生求职信
2014/02/25 职场文书
建筑工程技术专业求职信
2014/07/16 职场文书
2014学校领导四风问题对照检查材料思想汇报
2014/09/22 职场文书
社区党建工作汇报材料
2014/10/27 职场文书
考试作弊检讨书怎么写?
2014/12/21 职场文书
比赛口号霸气押韵
2015/12/24 职场文书
利用Java连接Hadoop进行编程
2022/06/28 Java/Android