博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于baseline、svd和stochastic gradient descent的个性化推荐系统
阅读量:2730 次
发布时间:2019-05-13

本文共 8190 字,大约阅读时间需要 27 分钟。

 

分类:    
 
219人阅读 
(4) 
 

文章主要介绍的是koren 08年发的论文[1],  2.3部分内容(其余部分会陆续补充上来)。

koren论文中用到netflix 数据集, 过于大, 在普通的pc机上运行时间很长很长。考虑到写文章目地主要是已介绍总结方法为主,所以采用Movielens 数据集。

变量介绍

部分变量介绍可以参看《》

文章中,将介绍两种方法实现的简易个性化推荐系统,用RMSE评价标准,对比这两个方法的实验结果。

(1) svd + stochstic gradient descent 方法来实现系统。

(2) baseline + svd + stochastic gradient descent 方法来实现系统。

注:

方法1: svd + stochastic gradient descent

svd:  

object function:

梯度变化(利用stochastic gradient descent算法使上述的目标函数值,在设定的迭代次数内,降到最小)

方法1,具体代码实现

[python] 
  1. ''''' 
  2. Created on Dec 13, 2012 
  3.  
  4. @Author: Dennis Wu 
  5. @E-mail: hansel.zh@gmail.com 
  6. @Homepage: http://blog.csdn.net/wuzh670 
  7.  
  8. Data set download from : http://www.grouplens.org/system/files/ml-100k.zip 
  9. '''  
  10.   
  11. from operator import itemgetter, attrgetter  
  12. from math import sqrt  
  13. import random  
  14.   
  15. def load_data():  
  16.       
  17.     train = {}  
  18.     test = {}  
  19.     filename_train = 'data/ua.base'  
  20.     filename_test = 'data/ua.test'  
  21.       
  22.     for line in open(filename_train):  
  23.         (userId, itemId, rating, timestamp) = line.strip().split('\t')  
  24.         train.setdefault(userId,{})  
  25.         train[userId][itemId] = float(rating)  
  26.     
  27.     for line in open(filename_test):  
  28.         (userId, itemId, rating, timestamp) = line.strip().split('\t')  
  29.         test.setdefault(userId,{})  
  30.         test[userId][itemId] = float(rating)  
  31.           
  32.     return train, test  
  33.   
  34. def calMean(train):  
  35.     stat = 0  
  36.     num = 0  
  37.     for u in train.keys():  
  38.         for i in train[u].keys():  
  39.             stat += train[u][i]  
  40.             num += 1  
  41.     mean = stat*1.0/num  
  42.     return mean  
  43.   
  44. def initialFeature(feature, userNum, movieNum):  
  45.   
  46.     random.seed(0)  
  47.     user_feature = {}  
  48.     item_feature = {}  
  49.     i = 1  
  50.     while i < (userNum+1):  
  51.         si = str(i)  
  52.         user_feature.setdefault(si,{})  
  53.         j = 1  
  54.         while j < (feature+1):  
  55.             sj = str(j)  
  56.             user_feature[si].setdefault(sj,random.uniform(0,1))  
  57.             j += 1  
  58.         i += 1  
  59.       
  60.     i = 1  
  61.     while i < (movieNum+1):  
  62.         si = str(i)  
  63.         item_feature.setdefault(si,{})  
  64.         j = 1  
  65.         while j < (feature+1):  
  66.             sj = str(j)  
  67.             item_feature[si].setdefault(sj,random.uniform(0,1))  
  68.             j += 1  
  69.         i += 1  
  70.     return user_feature, item_feature  
  71.   
  72. def svd(train, test, userNum, movieNum, feature, user_feature, item_feature):  
  73.   
  74.     gama = 0.02  
  75.     lamda = 0.3  
  76.     slowRate = 0.99  
  77.     step = 0  
  78.     preRmse = 1000000000.0  
  79.     nowRmse = 0.0  
  80.       
  81.     while step < 100:  
  82.         rmse = 0.0  
  83.         n = 0  
  84.         for u in train.keys():  
  85.             for i in train[u].keys():  
  86.                 pui = 0  
  87.                 k = 1  
  88.                 while k < (feature+1):  
  89.                     sk = str(k)  
  90.                     pui += user_feature[u][sk] * item_feature[i][sk]  
  91.                     k += 1  
  92.                 eui = train[u][i] - pui  
  93.                 rmse += pow(eui,2)  
  94.                 n += 1  
  95.                 k = 1  
  96.                 while k < (feature+1):  
  97.                     sk = str(k)  
  98.                     user_feature[u][sk] += gama*(eui*item_feature[i][sk] - lamda*user_feature[u][sk])  
  99.                     item_feature[i][sk] += gama*(eui*user_feature[u][sk] - lamda**item_feature[i][sk])  
  100.                     k += 1  
  101.               
  102.         nowRmse = sqrt(rmse*1.0/n)  
  103.         print 'step: %d      Rmse: %s' % ((step+1), nowRmse)  
  104.         if (nowRmse < preRmse):  
  105.             preRmse = nowRmse  
  106.               
  107.         gama *= slowRate  
  108.         step += 1  
  109.           
  110.     return user_feature, item_feature  
  111.   
  112. def calRmse(test, user_feature, item_feature, feature):  
  113.       
  114.     rmse = 0.0  
  115.     n = 0  
  116.     for u in test.keys():  
  117.         for i in test[u].keys():  
  118.             pui = 0  
  119.             k = 1  
  120.             while k < (feature+1):  
  121.                 sk = str(k)  
  122.                 pui += user_feature[u][sk] * item_feature[i][sk]  
  123.                 k += 1  
  124.             eui = pui - test[u][i]  
  125.             rmse += pow(eui,2)  
  126.             n += 1  
  127.     rmse = sqrt(rmse*1.0 / n)  
  128.     return rmse;  
  129.      
  130. if __name__ == "__main__":  
  131.   
  132.     # load data  
  133.     train, test = load_data()  
  134.     print 'load data success'  
  135.   
  136.     # initial user and item feature, respectly  
  137.     user_feature, item_feature = initialFeature(1009431682)  
  138.     print 'initial user and item feature, respectly success'  
  139.       
  140.     # baseline + svd + stochastic gradient descent  
  141.     user_feature, item_feature = svd(train, test, 9431682100, user_feature, item_feature)  
  142.     print 'svd + stochastic gradient descent success'  
  143.       
  144.     # compute the rmse of test set  
  145.     print 'the Rmse of test test is: %s' % calRmse(test, user_feature, item_feature, 100)  
  146.       
  147.       

方法2:baseline + svd + stochastic gradient descent 

baseline + svd:

object function:

梯度变化(利用stochastic gradient descent算法使上述的目标函数值,在设定的迭代次数内,降到最小)

方法2: 具体代码实现

[python] 
  1. ''''' 
  2. Created on Dec 13, 2012 
  3.  
  4. @Author: Dennis Wu 
  5. @E-mail: hansel.zh@gmail.com 
  6. @Homepage: http://blog.csdn.net/wuzh670 
  7.  
  8. Data set download from : http://www.grouplens.org/system/files/ml-100k.zip 
  9. '''  
  10.   
  11. from operator import itemgetter, attrgetter  
  12. from math import sqrt  
  13. import random  
  14.   
  15. def load_data():  
  16.       
  17.     train = {}  
  18.     test = {}  
  19.     filename_train = 'data/ua.base'  
  20.     filename_test = 'data/ua.test'  
  21.       
  22.     for line in open(filename_train):  
  23.         (userId, itemId, rating, timestamp) = line.strip().split('\t')  
  24.         train.setdefault(userId,{})  
  25.         train[userId][itemId] = float(rating)  
  26.     
  27.     for line in open(filename_test):  
  28.         (userId, itemId, rating, timestamp) = line.strip().split('\t')  
  29.         test.setdefault(userId,{})  
  30.         test[userId][itemId] = float(rating)  
  31.           
  32.     return train, test  
  33.   
  34. def calMean(train):  
  35.     stat = 0  
  36.     num = 0  
  37.     for u in train.keys():  
  38.         for i in train[u].keys():  
  39.             stat += train[u][i]  
  40.             num += 1  
  41.     mean = stat*1.0/num  
  42.     return mean  
  43.   
  44. def initialBias(train, userNum, movieNum, mean):  
  45.   
  46.     bu = {}  
  47.     bi = {}  
  48.     biNum = {}  
  49.     buNum = {}  
  50.       
  51.     u = 1  
  52.     while u < (userNum+1):  
  53.         su = str(u)  
  54.         for i in train[su].keys():  
  55.             bi.setdefault(i,0)  
  56.             biNum.setdefault(i,0)  
  57.             bi[i] += (train[su][i] - mean)  
  58.             biNum[i] += 1  
  59.         u += 1  
  60.           
  61.     i = 1  
  62.     while i < (movieNum+1):  
  63.         si = str(i)  
  64.         biNum.setdefault(si,0)  
  65.         if biNum[si] >= 1:  
  66.             bi[si] = bi[si]*1.0/(biNum[si]+25)  
  67.         else:  
  68.             bi[si] = 0.0  
  69.         i += 1  
  70.   
  71.     u = 1  
  72.     while u < (userNum+1):  
  73.         su = str(u)  
  74.         for i in train[su].keys():  
  75.             bu.setdefault(su,0)  
  76.             buNum.setdefault(su,0)  
  77.             bu[su] += (train[su][i] - mean - bi[i])  
  78.             buNum[su] += 1  
  79.         u += 1  
  80.           
  81.     u = 1  
  82.     while u < (userNum+1):  
  83.         su = str(u)  
  84.         buNum.setdefault(su,0)  
  85.         if buNum[su] >= 1:  
  86.             bu[su] = bu[su]*1.0/(buNum[su]+10)  
  87.         else:  
  88.             bu[su] = 0.0  
  89.         u += 1  
  90.   
  91.     return bu,bi  
  92.   
  93. def initialFeature(feature, userNum, movieNum):  
  94.   
  95.     random.seed(0)  
  96.     user_feature = {}  
  97.     item_feature = {}  
  98.     i = 1  
  99.     while i < (userNum+1):  
  100.         si = str(i)  
  101.         user_feature.setdefault(si,{})  
  102.         j = 1  
  103.         while j < (feature+1):  
  104.             sj = str(j)  
  105.             user_feature[si].setdefault(sj,random.uniform(0,1))  
  106.             j += 1  
  107.         i += 1  
  108.       
  109.     i = 1  
  110.     while i < (movieNum+1):  
  111.         si = str(i)  
  112.         item_feature.setdefault(si,{})  
  113.         j = 1  
  114.         while j < (feature+1):  
  115.             sj = str(j)  
  116.             item_feature[si].setdefault(sj,random.uniform(0,1))  
  117.             j += 1  
  118.         i += 1  
  119.     return user_feature, item_feature  
  120.   
  121. def svd(train, test, mean, userNum, movieNum, feature, user_feature, item_feature, bu, bi):  
  122.   
  123.     gama = 0.02  
  124.     lamda = 0.3  
  125.     slowRate = 0.99  
  126.     step = 0  
  127.     preRmse = 1000000000.0  
  128.     nowRmse = 0.0  
  129.       
  130.     while step < 100:  
  131.         rmse = 0.0  
  132.         n = 0  
  133.         for u in train.keys():  
  134.             for i in train[u].keys():  
  135.                 pui = 1.0 * (mean + bu[u] + bi[i])  
  136.                 k = 1  
  137.                 while k < (feature+1):  
  138.                     sk = str(k)  
  139.                     pui += user_feature[u][sk] * item_feature[i][sk]  
  140.                     k += 1  
  141.                 eui = train[u][i] - pui  
  142.                 rmse += pow(eui,2)  
  143.                 n += 1  
  144.                 bu[u] += gama * (eui - lamda * bu[u])  
  145.                 bi[i] += gama * (eui - lamda * bi[i])  
  146.                 k = 1  
  147.                 while k < (feature+1):  
  148.                     sk = str(k)  
  149.                     user_feature[u][sk] += gama*(eui*item_feature[i][sk] - lamda*user_feature[u][sk])  
  150.                     item_feature[i][sk] += gama*(eui*user_feature[u][sk] - lamda*item_feature[i][sk])  
  151.                     k += 1  
  152.               
  153.         nowRmse = sqrt(rmse*1.0/n)  
  154.         print 'step: %d      Rmse: %s' % ((step+1), nowRmse)  
  155.         if (nowRmse < preRmse):  
  156.             preRmse = nowRmse  
  157.               
  158.         gama *= slowRate  
  159.         step += 1  
  160.     return user_feature, item_feature, bu, bi  
  161.   
  162. def calRmse(test, bu, bi, user_feature, item_feature, mean, feature):  
  163.       
  164.     rmse = 0.0  
  165.     n = 0  
  166.     for u in test.keys():  
  167.         for i in test[u].keys():  
  168.             pui = 1.0 * (mean + bu[u] + bi[i])  
  169.             k = 1  
  170.             while k < (feature+1):  
  171.                 sk = str(k)  
  172.                 pui += user_feature[u][sk] * item_feature[i][sk]  
  173.                 k += 1  
  174.             eui = pui - test[u][i]  
  175.             rmse += pow(eui,2)  
  176.             n += 1  
  177.     rmse = sqrt(rmse*1.0 / n)  
  178.     return rmse;  
  179.      
  180. if __name__ == "__main__":  
  181.   
  182.     # load data  
  183.     train, test = load_data()  
  184.     print 'load data success'  
  185.       
  186.     # Calculate overall mean rating  
  187.     mean = calMean(train)  
  188.     print 'Calculate overall mean rating success'  
  189.   
  190.     # initial user and item Bias, respectly  
  191.     bu, bi = initialBias(train, 9431682, mean)  
  192.     print 'initial user and item Bias, respectly success'  
  193.   
  194.     # initial user and item feature, respectly  
  195.     user_feature, item_feature = initialFeature(1009431682)  
  196.     print 'initial user and item feature, respectly success'  
  197.       
  198.     # baseline + svd + stochastic gradient descent  
  199.     user_feature, item_feature, bu, bi = svd(train, test, mean, 9431682100, user_feature, item_feature, bu, bi)  
  200.     print 'baseline + svd + stochastic gradient descent success'  
  201.       
  202.     # compute the rmse of test set  
  203.     print 'the Rmse of test test is: %s' % calRmse(test, bu, bi, user_feature, item_feature, mean, 100)  
  204.       
  205.       

实验参数设置:

   

(gama = 0.02  lamda =0.3)

   feature = 100 maxstep = 100  slowRate = 0.99(随着迭代次数增加,梯度下降幅度越来越小) 

方法1结果:Rmse of test set : 1.00422938926

方法2结果:Rmse of test set : 0.963661477881

REFERENCES

1.Y. Koren. . Proc. 14th ACM SIGKDD Int. Conf. On Knowledge Discovery and Data Mining  (KDD08), pp. 426434, 2008.

2. Y.Koren.    2009

转载请注明:转自   

你可能感兴趣的文章
leetcode:两数之和-三数之和-四数之和系列之KSum的总结
查看>>
面试题-排序数组中找两数之和为target的所有数的组合-leetcode167的变型题
查看>>
面试题-字符串分类
查看>>
DP系列-leetcode 坐型动态规划系列-45, 55,62,63,64,120题总结
查看>>
CNN中各层的作用
查看>>
String,StringBuffer,StringBuilder的区别
查看>>
java中两个字符串连接的三种方法
查看>>
DP系列-最长公共子串和最长公共子序列总结
查看>>
二分查找
查看>>
java中HashSet和TreeSet的区别
查看>>
【Reverse】Tensorflow中屏蔽Padding处理变长序列的双向LSTM
查看>>
产品研发流程的四个里程碑
查看>>
XML解析技术浅谈
查看>>
Windows操作系统发展历史专题
查看>>
[转]24个英文电子书免费下载网站
查看>>
Web 2.0 –基于服务的下一代互联网
查看>>
VMWare 下OEM系统激活问题
查看>>
maven常见问题问答
查看>>
Maven-依赖管理机制
查看>>
关于maven可选依赖和排除依赖的学习
查看>>