基于随机梯度下降的矩阵分解推荐算法(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 28 Python
详谈python http长连接客户端
Jun 12 Python
Python使用Scrapy保存控制台信息到文本解析
Dec 27 Python
浅谈python日志的配置文件路径问题
Apr 28 Python
Python面向对象类的继承实例详解
Jun 27 Python
Python实现基于KNN算法的笔迹识别功能详解
Jul 09 Python
Python多进程写入同一文件的方法
Jan 14 Python
详解PyCharm+QTDesigner+PyUIC使用教程
Jun 13 Python
pygame编写音乐播放器的实现代码示例
Nov 19 Python
利用Python脚本实现自动刷网课
Feb 03 Python
40行Python代码实现天气预报和每日鸡汤推送功能
Feb 27 Python
在pycharm创建scrapy项目的实现步骤
Dec 01 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+mysql 采用ajax技术的 省 市 地 3级联动无刷新菜单 源码
2006/12/16 PHP
php 模拟 asp.net webFrom 按钮提交事件的思路及代码
2013/12/02 PHP
thinkPHP中create方法与令牌验证实例浅析
2015/12/08 PHP
js中 关于undefined和null的区别介绍
2013/04/16 Javascript
JavaScript中的关键字&quot;VAR&quot;使用详解 分享
2013/07/31 Javascript
8个实用的jQuery技巧
2014/03/04 Javascript
jQery使网页在显示器上居中显示适用于任何分辨率
2014/06/09 Javascript
jQuery实现手机号码输入提示功能实例
2015/04/30 Javascript
jQuery实现美观的多级动画效果菜单代码
2015/09/06 Javascript
js实现商品抛物线加入购物车特效
2020/11/18 Javascript
详述 Sublime Text 打开 GBK 格式中文乱码的解决方法
2017/10/26 Javascript
JavaScript创建、读取和删除cookie
2019/09/03 Javascript
js实现手表表盘时钟与圆周运动
2020/09/18 Javascript
[48:39]Ti4主赛事胜者组第一天 EG vs NEWBEE 2
2014/07/19 DOTA
python中去空格函数的用法
2014/08/21 Python
Python中__call__用法实例
2014/08/29 Python
基于Python的关键字监控及告警
2017/07/06 Python
python爬取个性签名的方法
2018/06/17 Python
python交易记录链的实现过程详解
2019/07/03 Python
如何在mac环境中用python处理protobuf
2019/12/25 Python
OpenCV中VideoCapture类的使用详解
2020/02/14 Python
Django-simple-captcha验证码包使用方法详解
2020/11/28 Python
Python Pandas list列表数据列拆分成多行的方法实现
2020/12/14 Python
详解HTML5 LocalStorage 本地存储
2016/12/23 HTML / CSS
前端实现背景虚化但内容清晰且自适应 的实例代码
2019/08/01 HTML / CSS
美国婚礼和派对礼品网站:Kate Aspen(新娘送礼会、迎婴派对)
2018/03/28 全球购物
Nebula美国官网:便携式投影仪
2019/03/15 全球购物
爱尔兰电脑、家电和家具购物网站:Buy It Direct
2019/07/09 全球购物
外语系毕业生自荐信范文
2013/12/16 职场文书
美术教师岗位职责
2014/03/18 职场文书
啤酒节策划方案
2014/05/28 职场文书
五一劳动节演讲稿
2014/09/12 职场文书
2014年中职班主任工作总结
2014/12/16 职场文书
2015年清明节网上祭英烈活动总结
2015/03/26 职场文书
幼儿园2016圣诞节活动总结
2016/03/31 职场文书
排查并解决MySQL生产库内存使用率高的报警
2022/04/11 MySQL