2022-10-31-基于用户的协同过滤推荐算法实现+MAE+RMSE的求解+项目代码+运行结果图

article/2025/9/15 23:22:43

目录

  • 推荐算法学习笔记
  • 项目代码
  • 运行结果图



推荐算法学习笔记

协同过滤推荐算法测评指标RMSE均方根误差
推荐系统笔记:
一、为什么需要推荐系统
为了解决互联网时代下的信息超载问题。
二、搜索引擎和推荐系统的区别
· 分类目录,是将著名网站分门别类,从而方便用户根据类别查找公司。
· 搜索引擎,用户通过输入关键字,查找自己需要的信息。
· 推荐系统,和搜索引擎一样,是一种帮助用户快速发展有用信息的工具。通过分析用户的历史行为,给用户的兴趣建模,从而主动给用户推荐能够满足他们兴趣和需求的信息。并且,推荐系统能够很好的发掘物品的长尾,挑战传统的2/8原则(80%的销售额来自20%的热门品牌)。
三、技术角度来看,搜索引擎和推荐系统的区别
1)搜索引擎,注重搜索结果之间的关系和排序;
2)推荐系统,需要研究用户的兴趣模型,利用社交网络的信息进行个性化的计算;
3)搜索引擎,由用户主导,需要输入关键词,自行选择结果。如果结果不满意,需要修改关键词,再次搜索;
4)推荐系统,由系统主导,根据用户的浏览顺序,引导用户发现自己感兴趣的信息;
四、推荐系统的定义
推荐系统通过发掘用户的行为,找到用户的个性化需求,从而将长尾物品准确推荐给需要它的用户,帮助用户找到他们感兴趣但很难发现的物品。
高质量的推荐系统会使用户对系统产生依赖,因此,推荐系统不仅能为用户提供个性化服务,还能与用户建立长期稳定的关系,提高用户忠诚度,防止用户流失。
五、推荐系统评测
一般推荐系统的参与方有3个:

  • 用户
  • 物品提供商
  • 推荐系统提供网站

因此,评测一个推荐系统时,需要考虑3方的利益,一个好的推荐系统是能够令三方共赢的系统。
在这里插入图片描述
六、三个实验方法的优缺点
1)离线实验
离线实验的方法的步骤如下:
a)通过日志系统获得用户行为数据,并按照一定格式生成一个标准的数据集;
b)将数据集按照一定的规则分成训练集和测试集;
c)在训练集上训练用户兴趣模型,在测试集上进行预测;
d)通过事先定义的离线指标,评测算法在测试集上的预测结果。
从以上步骤看出,离线实验的都是在数据集上完成的。意味着,它不需要一个实际的系统作为支撑,只需要有一个从日志中提取的数据集即可。
离线实验的优点是:
不需要有对实际系统的控制权;
不需要用户参与实践;
速度快,可以测试大量算法;
缺点是:
数据集的稀疏性限制了适用范围,例如一个数据集中没有包含某用户的历史行为,则无法评价对该用户的推荐结果;
评价结果的客观性,无法得到用户主观性的评价;
难以找到离线评价指标和在线真实反馈(如 点击率、转化率、点击深度、购买客单价、购买商 品类别等)之间的关联关系;
2)用户调查
用户调查需要一些真实的用户,让他们在需要测试的推荐系统上完成一些任务。在他们完成任务时,需要观察和记录用户的行为,并让他们回答一些问题。
最后,我们通过分析他们的行为和答案,了解测试系统的性能。
用户调查的优点是:
可以获得用户主观感受的指标,出错后容易弥补;
缺点是:
招募测试用户代价较大;
无法组织大规模的测试用户,统计意义不足;
3)在线实验
在完成离线实验和用户调查之后,可以将系统上线做AB测试,将它和旧算法进行比较。
在线实验最常用的评测算法是【A/B测试】,它通过一定的规则将用户随机分成几组,对不同组的用户采用不同的算法,然后通过统计不同组的评测指标,比较不同算法的好坏。
它的核心思想是:
a) 多个方案并行测试;
b) 每个方案只有一个变量不同;
c) 以某种规则优胜劣汰。

其中第2点暗示了A/B 测试的应用范围:A/B测试必须是单变量。
对于推荐系统的评价中,唯一变量就是–推荐算法。
AB测试的优点是:
可以公平获得不同算法实际在线时的性能指标,包括商业上关注的指标;
缺点是:
周期较长,必须进行长期的实验才能得到可靠的结果;
大型网站做AB测试,可能会因为不同团队同时进行各种测试对结果造成干扰,所以切分流量是AB测试中的关键。
不同的层以及控制这些层的团队,需要从一个统一的地方获得自己AB测试的流量,而不同层之间的流量应该是正交的。
总结:一般来说,一个新的推荐算法最终上线,需要完成上述的3个实验。

  1. 首先,通过离线实验证明它在很多离线指标上优于现有的算法;
  2. 其次,通过用户调查确定用户满意度不低于现有的算法;
  3. 最后,通过在线AB测试确定它在我们关心的指标上优于现有的算法;

关于均方根误差(RMSE):
RMSE是一个重要的预测评分的准确度指标,所谓预测评分的准确度衡量的是算法评测的评分与用户的实际评分之间的贴合度
RMSE越小表示误差越小,推荐系统的性能就越好
在这里插入图片描述

其中的平方根是RMSE加大了对预测不准的用户物品评分的惩罚(平方项的惩罚),因而对系统的评测更加苛刻。但是要注意研究表明,如果评分系统是基于整数建立的(即用户给的评分都是整数),那么对预测结果取整数会降低MAE的误差。


项目代码

一、实现原理和步骤

1、使用movielens数据集(943个用户,1682部电影,80000条评分数据);
2、构建用户-电影评分矩阵;
二维矩阵,横坐标为943的用户的id,纵坐标为1682部电影的id,其中在用户打过分 的电影的下方标出对应的分数。
3、数据统计分析,可以直观地打印出比如电影的评分分布情况,可以明显的看出打高分的 数量和打低分的数量。
4、输入用户id(1-943);
5、基于用户的协同过滤推荐算法;
1、根据用户历史行为信息构建用户-项目评分矩阵,用户历史行为信息包括项目评分、浏览历史、收藏历史、喜好标签等,本项目以单一的项目评分为例
2、根据用户-项目评分矩阵计算用户之间的相似度。计算相似度常用的方法有余弦算法、修正余弦算法、皮尔森算法等等,该项目为余弦算法。
3、根据用户之间的相似度得到目标用户的最近邻居KNN。KNN的筛选常用的有两种方式,一种是设置相似度阀值(给定一个相似度的下限,大于下限的相似度为最近邻居),一种是根据与目标用户相似度的高低来选择前N个最近邻居(本项目以前N个为例)。相似度排序可用经典冒泡排序法。
4、预测项目评分并进行推荐。
6、计算推荐算法测评指标rmse值。
7、冷启动推荐(扩展,暂未实现);
在该推荐系统中用所拥有的用户-电影-评分数据集进行训练测试所产生的一个推荐算法进行一个冷启动推荐,冷启动推荐的场景分别为刚注册的新用户在没有用户使用系统历史数据的情况下进行一个合适的推荐,和刚刚上线一个新电影的时候在没有用户观看记录数据的情况下将该电影推荐给可能对该电影感兴趣的用户。
二、代码实现
项目目录:
在这里插入图片描述
Application:算法主运行算法
Base:基础常量接口
ComputeSimilarity:比较两个用户相似度的类
GetScore:获取预测评分
PearsonCorrelation:余弦算法/皮尔森算法
ProduceSimilarityMatrix:得到用户相似度矩阵
ReadFile:读取movielens
u1.base:训练集
ui.test:测试集

Application:

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
/*** 协同过滤推荐算法运行主方法* @author line**/public class Application implements Base {public static void main(String[] args) {// 输入userId,并获取System.out.println("请输入一个用户Id(1、2、3……943)");Scanner scanner = new Scanner(System.in);//获取得到输入的userIdint userId = scanner.nextInt();// 从文件中读取数据int[][] user_movie_base = new int[PREFROWCOUNT][COLUMNCOUNT];//读取文件中的数据user_movie_base = new ReadFile().readFile(BASE);//产生相似度矩阵double[] similarityMatrix = new ProduceSimilarityMatrix().produceSimilarityMatrix(user_movie_base, userId);// 知道每个用户之间的相似度值之后,开始获取每隔相似值对应的userId,然后和相似值关联,再根据相似值排序,即得到相似爱好的userId,然后再输出相似推荐的商品int[] id = new int[KNEIGHBOUR];//存放K个最近邻userId//产生一个临时相似度矩阵变量,是为了相似度排序时和userid对应double[] tempSimilarity = new double[similarityMatrix.length];for (int j = 0; j < tempSimilarity.length; j++) {tempSimilarity[j] = similarityMatrix[j];}Arrays.sort(tempSimilarity);//排序,升序int flag = 0;//临时变量double[] similarity = new double[KNEIGHBOUR];//保存前K个相似度,从大到小for (int m = tempSimilarity.length - 1; m >= tempSimilarity.length - KNEIGHBOUR; m--) {for(int j = 0; j < similarityMatrix.length; j++) {if (similarityMatrix[j] == tempSimilarity[m] && similarityMatrix[j] != 0.0){similarity[flag] = tempSimilarity[m];id[flag]=j;//保存前K个相似度的useridflag++;}}}System.out.println("相似度最近的" + KNEIGHBOUR + "个用户是:");System.out.print("近邻用户");System.out.printf("%25s","相似度");//格式化输出"%25s"是占多少位System.out.printf("%30s\n","推荐产品");Map<Integer, Double> map = new HashMap<Integer, Double>();//存放每件商品的id和期望值,是键值对关系,即一对一for (int i = 0; i < KNEIGHBOUR; i++) {//按照k值得大小来循环// 前k个近邻用户的推荐产品int user_id = id[i];//数组id中的userid根据相似度大小顺序已经排好,从大到小int[] items = user_movie_base[user_id];// 获取源数据K个邻近用户userid的所有评分String str = "";for (int j = 0; j < COLUMNCOUNT; j++) {//循环每件商品,如果相邻用户对某件商品的评分不为0,而目标用户的评分为0,该商品就为推荐商品if ((items[j] != 0) && (user_movie_base[userId - 1][j] == 0)){str += " " + (j + 1);//将推荐商品的id保存在一个字符串中,可以直接输出//此时,可以通过循环计算某一件推荐商品的评分用户的相似度期望//开始计算期望,将相同商品的相似度相加,并保存在map集合中if(map.containsKey(j + 1)){//如果一件商品的值,已经保存在map集合的键中(键是唯一的,即不会和其他的数值一样),那么键对应的值,就会改变,加上该商品不用用户的相似度double d = map.get(j+1);d+=similarity[i];map.put(j+1,d);//修改map中的值}else{map.put(j+1, similarity[i]);//如果没有保存一件商品的id,那么开始保存}}}System.out.print(id[i] + 1);System.out.printf("%16s\t" ,String.format("%.2f",similarity[i]*100)+"%");//输出的同时格式化数据System.out.println(str);//输出每个用户的推荐商品}//选择最好的推荐商品,期望加权//循环map集合的键Map<Integer,Double> map2 = new HashMap<Integer, Double>(); //保存商品id和加权期望,因为还要对加权期望排序,要和商品id对应double s1 = 0;double s2 = 0;Set<Integer> set = map.keySet();//获取map集合中的所有键,输出是一个set集合for(int key : set){//循环map中的所有键for (int i = 0; i < KNEIGHBOUR; i++) {int score = user_movie_base[id[i]][key-1];//map中的键是商品id,i是userid,获取评分s1+=score*map.get(key);s2+=score;}map2.put(key, s1/s2);//保存加权期望值,和商品id对应}Object[] arr = map2.values().toArray();//获取map2中所有的值,也就是每件商品的加权期望Arrays.sort(arr);//升序排列,调用系统数据包中的函数,自动排列数组set = map2.keySet();//获取商品idint max=0;//最佳推荐项目idfor(int key : set){//循环商品id,根据最大的加权期望,找到商品idif(map2.get(key)==arr[arr.length-1]){max = key;break;}}System.out.println("最值得推荐的商品是:"+max);
// 误差率int[][] test = new ReadFile().readFile(TEST); // 462个用户的实际评分double[][] similarityMatrix2 = new ProduceSimilarityMatrix().produceSimilarityMatrix(user_movie_base);//获取任意两行之间的相似度矩阵double[][] matrix = new GetScore().getScore(user_movie_base,similarityMatrix2);double[] mae = new ProduceMAE().produceMAE(matrix, test);double Mae = 0.0, MAE = 0.0;//平均绝对误差,通过两大组数据的相似度矩阵对比而来for (int k = 0; k < mae.length; k++) {Mae += mae[k];}MAE = Mae / TESTROWCOUNT;System.out.println("MAE=:" + MAE);double RMSE=new ProduceMSE().produceMSE(matrix,test);System.out.println("MSE=:" + RMSE);}
} 

Base

/*** 基础静态文件数据* @author line**/public interface Base {public static final int KNEIGHBOUR = 10; //number of neighbors最近邻个数public static final int COLUMNCOUNT = 1682; //number of items 项目总数public static final int PREFROWCOUNT = 943; //number of users in base训练集上的用户数目public static final int TESTROWCOUNT = 462; //number of users in test测试集上的用户数目public static final String BASE = "./ml-100k/u1.base";//训练集public static final int BASE_LINE = 80000;//base数据集的行数public static final String TEST = "./ml-100k/u1.test";//测试集public static final int TEST_LINE = 20000;//test数据集的行数public static final String BASE_GENRE = "./ml-100k/u.user";//用户属性集public static final String BASE_ITEMS_GENRE = "./ml-100k/u.item";//用户属性集public static final int ITEMS_GENRE_LINE = 19;//test数据集的行数} 

ComputeSimilarity

import java.util.ArrayList;
import java.util.List;/*** 从两行数据中,获取需要对比的要求数据* @author line**/public class ComputeSimilarity {public double computeSimilarity(int[] item1,int[] item2) {List<Integer> list1 = new ArrayList<Integer>();//因为不知道两行userid的评分是否有效即都不为0,所以定义集合来储存不知道的有效评分List<Integer> list2 = new ArrayList<Integer>();for (int i = 0; i < item1.length; i++) {if(item1[i] != 0 || item2[i] !=0) {//如果相同列上有0就舍去list1.add(new Integer(item1[i]));//因为合格数据个数不确定,所以用集合表示list2.add(new Integer(item2[i]));}}return new PearsonCorrelation().pearsonCorrelation(list1,list2);//返回相似度值}} 

GetScore

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;public class GetScore implements Base {//方法参数,一个是源数据,一个是通过源数据得到的相似度矩阵//得到预测评分矩阵,先循环行userid,得到每一个userid的K个近邻用户和相似度,再得到目标用户的预测项目public double[][] getScore(int[][] user_movie_base,double[][] combineMatrix ){double[][] matrix = new double[PREFROWCOUNT][COLUMNCOUNT];//保存每个用户对评分为0的项目的预测值//循环useridfor (int i = 0; i < PREFROWCOUNT; i++) {//KNEIGHBOUR//得到每一个userid的K个邻近相似度极其useridint[] id = new int[KNEIGHBOUR];//存放K个最近邻userIddouble[] tempSimilarity = new double[combineMatrix[i].length];//产生一个临时相似度矩阵变量,是为了相似度排序时和userid对应for (int j = 0; j < tempSimilarity.length; j++) {tempSimilarity[j] = combineMatrix[i][j];}//Arrays.sort(tempSimilarity);//排序,升序//int flag = 0;//临时变量double[] similarity = new double[KNEIGHBOUR];//保存前K个相似度,从大到小// for (int m = tempSimilarity.length - 1; m >= tempSimilarity.length - KNEIGHBOUR; m--) {// for(int j = 0; j < combineMatrix[i].length; j++) {// if (combineMatrix[i][j] == tempSimilarity[m] && combineMatrix[i][j] != 0.0){// similarity[flag] = tempSimilarity[m];// id[flag]=j;//保存前K个相似度的userid// flag++;// }// }// }int[] ids = new int[PREFROWCOUNT];//存放K个邻近项目idfor (int h = 0; h < PREFROWCOUNT; h++) {ids[h] = h;}for (int h = 0; h < tempSimilarity.length; h++) {for (int j = 0; j < tempSimilarity.length - 1 - h; j++) {if (tempSimilarity[j] < tempSimilarity[j + 1]) { //如果后一个数小于前一个数交换double tmp = tempSimilarity[j];tempSimilarity[j] = tempSimilarity[j + 1];tempSimilarity[j + 1] = tmp;int temp = ids[j];ids[j] = ids[j + 1];ids[j + 1] = temp;}}}for (int h = 0; h < KNEIGHBOUR; h++) {similarity[h] = tempSimilarity[h];}for (int h = 0; h < KNEIGHBOUR; h++) {id[h] = ids[h];}//以上代码已经得到一个目标用户的K个相似度userid和相似度结束,并且已经排好顺序,分别是:数组id,和数组similarity
//开始计算一个目标用户的推荐产品的预测评分,方法,K个邻近用户的相同商品的加权平均数Map<Integer, Double> map = new HashMap<Integer, Double>();//存放每件商品的id和商品评分*相似度Map<Integer, Double> map2 = new HashMap<Integer, Double>();//存放每件商品的id和相似度之和for (int k = 0; k < KNEIGHBOUR; k++) {//按照k值得大小来循环
// 前k个近邻用户的推荐产品int user_id = id[k];//数组id中的userid根据相似度大小顺序已经排好,从大到小int[] items = user_movie_base[user_id];// 获取源数据K个邻近用户userid的所有评分for (int j = 0; j < COLUMNCOUNT; j++) {//循环每件商品,如果相邻用户对某件商品的评分不为0,而目标用户的评分为0,该商品就为推荐商品if ((items[j] != 0) && (user_movie_base[i][j] == 0)) {if (map.containsKey(j)) {//如果一件商品的值,已经保存在map集合的键中(键是唯一的,即不会和其他的数值一样),那么键对应的值,就会改变,加上该商品不用用户的相似度double d = map.get(j);d += similarity[k] * items[j];map.put(j, d);//修改map中的值double dd = map2.get(j);dd += similarity[k];map2.put(j, dd);} else {map.put(j, similarity[k] * items[j]);//如果没有保存一件商品的id,那么开始保存map2.put(j, similarity[k]);}}}}Set<Integer> set = map.keySet();//循环所有推荐商品for (Integer key : set) {matrix[i][key] = map.get(key) / map2.get(key);}}return matrix;}
}

PearsonCorrelation

import java.util.List;/*** 余弦算法计算相似度** @author line*/public class PearsonCorrelation implements Base {// 通过余弦求相邻值,对比两行数据,方法有很多,列举的是余弦方法,也可用皮尔森方法public double pearsonCorrelation(List<Integer> a, List<Integer> b) {// 返回某两行的相似度值double sum1 = 0;double sum2 = 0;Object[] a2 = a.toArray();Object[] b2 = b.toArray();int aimcha;int usercha;double wei = 0;for (int j = 0; j < a.size(); j++) {aimcha = (Integer) a2[j];usercha = (Integer) b2[j];sum1 += aimcha * aimcha;sum2 += usercha * usercha;}for (int i = 0; i < a.size(); i++) {double light = 0;double right = 0;aimcha = (Integer) a2[i];usercha = (Integer) b2[i];light = aimcha / Math.sqrt(sum1);right = usercha / Math.sqrt(sum2);wei += light * right;}return wei;//相似度值}}

ProduceMAE

	/*** 计算MSE平均绝对误差* @author line**/public class ProduceMAE implements Base{//求误差public double[] produceMAE(double[][] m,int[][]test){double mae= 0.0;double []mm=new double[TESTROWCOUNT ];for(int i=0;i<TESTROWCOUNT ;i++ ) {double sum_fencha= 0.0;int num=0;for(int j=0;j<PREFROWCOUNT;j++){if(test[i][j]!=0&& m[i][j]!=0){sum_fencha+=Math.abs(m[i][j]-(double)test[i][j]);//相差取绝对值num++;}}if (num==0) mae=0;else mae= sum_fencha/num;mm[i]=mae;}return mm;}} 

ProduceMSE

import static java.lang.Math.sqrt;/*** 计算MSE平均绝对误差* @author line**/public class ProduceMSE implements Base{//求误差//该函数用于计算均方根误差,m为预测数据,test为真实数据//          RMSE : 浮点型//        均方根误差.public double produceMSE(double[][] m,int[][]test){//定义一个变量用于存储所有样本的平方误差之和double  the_sum_of_error = 0;double []mm=new double[TESTROWCOUNT ];for(int i=0;i<TESTROWCOUNT ;i++ ) {for(int j=0;j<test[i].length;j++){the_sum_of_error += ((double) test[i][j]-m[i][j])*((double) test[i][j]-m[i][j]);}}double RMSE = sqrt(the_sum_of_error/TESTROWCOUNT);return RMSE;}} 

ProduceSimilarityMatrix

/*** 产生相似矩阵,通过一个userId找其最近邻userId喜欢的产品,则相似度矩阵为一行n列矩阵,* 若是全部比较一个矩阵所有userId的相关度产生一个n行n列矩阵* @author line**/public class ProduceSimilarityMatrix implements Base{
//在计算MAE会用到public double[][] produceSimilarityMatrix(int[][] preference) {double[][] similarityMatrix = new double[PREFROWCOUNT][PREFROWCOUNT];//行和列都是所有的用户,因为是每一行和每一行相比,所以得到的相似矩阵为正方形for (int i = 0; i < PREFROWCOUNT; i++) {for (int j = 0; j < PREFROWCOUNT; j++) {if (i == j) {continue;}//数据是两行之间对比,其实只需要填满相似度矩阵的左下方或者右上方即可(减少重复运算)similarityMatrix[i][j] =new ComputeSimilarity().computeSimilarity(preference[i], preference[j]);//参数是从第一行开始,和其他每一行比较相似度}}return similarityMatrix;//返回相似度矩阵}//计算某个userId的相似度矩阵,用户之间的相似度是每个用户的每件商品评分的相似度,也就是说相似度矩阵是行是用户列也是用户,是正方形矩阵,对角线上的值都为1//参数i是输入的useridpublic double[] produceSimilarityMatrix(int[][] preference,int i) {double[] similarityMatrix = new double[PREFROWCOUNT];//定义一个相似度矩阵,行和列都是所有的用户,因为是每一行和每一行相比,所以得到的相似矩阵为正方形for (int j = 0; j < PREFROWCOUNT; j++) {//循环和其他userId对比其所有商品if(j==(i-1)){//不比较同行,i-1是因为数组索引比userid小1continue;//跳出循环,继续下一次循环}similarityMatrix[j] =new ComputeSimilarity().computeSimilarity(preference[i-1], preference[j]);//参数是从第一行开始,和其他每一行比较相似度}return similarityMatrix;//返回相似度矩阵,只有在userid-1行有数据,其他行列数据都为0,因为只是userid-1行和其他行对比}//根据性别属性,产生用户性别属性相似度public double[] produceSimilarityMatrixGener(int[] preference,int userId) {double[] similarityMatrix = new double[PREFROWCOUNT];//定义一个相似度矩阵,行和列都是所有的用户,因为是每一行和每一行相比,所以得到的相似矩阵为正方形for (int j = 0; j < PREFROWCOUNT; j++) {//循环和其他userId对比其所有商品if(j==(userId-1)){//不比较同行,i-1是因为数组索引比userid小1continue;//跳出循环,继续下一次循环}if(preference[j]==preference[userId-1])similarityMatrix[j] = 1;elsesimilarityMatrix[j] = 0;}return similarityMatrix;//返回相似度矩阵,只有在userid-1行有数据,其他行列数据都为0,因为只是userid-1行和其他行对比}//基于项目public double[] produceSimilarityMatrixItems(int[][] preference,int i) {double[] similarityMatrix = new double[COLUMNCOUNT];for (int j = 0; j < COLUMNCOUNT; j++) {if(j==(i-1)){//不比较同行continue;//跳出循环,继续下一次循环}similarityMatrix[j] =new ComputeSimilarity().computeSimilarity(preference[i-1], preference[j]);//参数是从第一行开始,和其他每一行比较相似度}return similarityMatrix;//返回相似度矩阵,只有在userid-1行有数据,其他行列数据都为0,因为只是userid-1行和其他行对比}} 

ReadFile

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;/*** 读取数据集中的数据* @author line**/public class ReadFile implements Base {//从文件中读取数据,以“ ”划分public int[][] readFile( String fileName) {int[][] user_movie = new int[PREFROWCOUNT][COLUMNCOUNT];//存放数据try {File file = new File(fileName);FileReader fr = new FileReader(file);BufferedReader br = new BufferedReader(fr);String line = "";while (br.ready()) {line = br.readLine();//按行获取数据String[] data = line.split("\t");//以“TAB”符来分割每行的四个数据数据获取userid,score,productint[] ddd = new int[4];for (int j = 0; j < data.length; j++) {ddd[j] = Integer.parseInt(data[j]);}user_movie[ddd[0] - 1][ddd[1] - 1] = ddd[2];//因为数组的索引是从0开始,而商品和用户id是从1开始,故减去1}} catch (Exception ex) {ex.printStackTrace();//如果方法出现错误,会被抓住,在控制台输出错误原因}return user_movie;}//从文件中读取数据,以“|”划分public int[] readFileGener(String fileName) {int[] user_genre_base = new int[PREFROWCOUNT];//存放数据try {File file = new File(fileName);FileReader fr = new FileReader(file);BufferedReader br = new BufferedReader(fr);String line = "";int i=0;while (br.ready()) {line = br.readLine();//按行获取数据String[] data = line.split("\\|");if(data[2].equals("M")){//男性设为1user_genre_base[i]= 1;}elseuser_genre_base[i]= 0;//女性i++;}} catch (Exception ex) {ex.printStackTrace();//如果方法出现错误,会被抓住,在控制台输出错误原因}return user_genre_base;}//获取items-user矩阵public int[][] readFileItems( String fileName) {int[][] items_movie = new int[COLUMNCOUNT][PREFROWCOUNT];//存放数据try {File file = new File(fileName);FileReader fr = new FileReader(file);BufferedReader br = new BufferedReader(fr);String line = "";while (br.ready()) {//矩阵中循环列line = br.readLine();String[] data = line.split("\t");int itemsId = Integer.parseInt(data[1]);int userId = Integer.parseInt(data[0]);items_movie[itemsId-1][userId-1] = Integer.parseInt(data[2]);}} catch (Exception ex) {ex.printStackTrace();//如果方法出现错误,会被抓住,在控制台输出错误原因}return items_movie;}//获取items-gener矩阵public int[][] readFileItemsGener( String fileName) {int[][] items_movie = new int[COLUMNCOUNT][ITEMS_GENRE_LINE];//存放数据try {File file = new File(fileName);FileReader fr = new FileReader(file);BufferedReader br = new BufferedReader(fr);String line = "";while (br.ready()) {//矩阵中循环列line = br.readLine();String[] data = line.split("\\|");int itemsId = Integer.parseInt(data[0]);int j = 0;for (int i = data.length-ITEMS_GENRE_LINE; i < data.length; i++) {items_movie[itemsId-1][j] =Integer.parseInt(data[i]);j++;}}} catch (Exception ex) {ex.printStackTrace();//如果方法出现错误,会被抓住,在控制台输出错误原因}return items_movie;}} 

运行结果图

RMSE计算过程示意图
在这里插入图片描述

运行结果示意图
在这里插入图片描述
数据集
在这里插入图片描述
MovieLens数据集

MovieLens数据集包含多个用户对多部电影的评级数据,也包括电影元数据信息和用户属性信息。
下载地址
http://files.grouplens.org/datasets/movielens/
介绍

下面以ml-100k数据集为例进行介绍:

最主要用的是u.data(评分) | u.item(电影信息) | u.user(用户信息)

下载之后各文件具体含义如下:
各文件含义如下:

allbut.pl --生成训练和测试集的脚本,其中除了n个用户评分之外,所有训练和测试集都在训练数据中。mku.sh --从u.data数据集生成的所有用户的shell脚本。u.data – 由943个用户对1682个电影的10000条评分组成。每个用户至少评分20部电影。用户和电影从1号开始连续编号。数据是随机排序的。标签分隔列表:user id | item id | rating | timestampu.genre --类型列表。u.info --u.data数据集中的用户数,电影数和评分数。u.item --电影信息。标签分隔列表:movie id | movie title | release date | video release date | IMDb URL | unknown | Action | Adventure | Animation | Children’s | Comedy | Crime | Documentary | Drama | Fantasy | Film-Noir | Horror | Musical | Mystery | Romance | Sci-Fi | Thriller | War | Western最后19个字段是流派,1表示电影是该类型,0表示不是;电影可以同时使用几种流派。电影id和u.data数据集中的id是一致的。u.occupation --职业列表。u.user --用户的人口统计信息。标签分隔列表:user id | age | gender | occupation | zip code用户id和u.data数据集中的id是一致的。u1.base --数据集u1.base / u1.test到u5.base / u5.test都是将u.data数据集按照80% / 20%的比例分割的训练集和测试集。u1.test u1,…,u5有互不相交的测试集;如果是5次交叉验证,那么你可以在每个训练和测试集中重复实验,平均结果。u2.base 这些数据集可以通过mku.sh从u.data生成u2.testu3.baseu3.testu4.baseu4.testu5.baseu5.testua.base --数据集ua.base, ua.test, ub.base, ub.test将u.data数据集分为训练集和测试集,每个用户在测试集中具有10个评分。ua.test ua.test和ub.test是不相交的。这些数据集可以通过mku.sh从u.data生成

http://chatgpt.dhexx.cn/article/SuyEPoRh.shtml

相关文章

LPC图像拼接-代码-RMSE问题

LPC的RMSE代码 2021年cvpr-Leveraging Line-point Consistence to Preserve Structures for Wide Parallax Image Stitching&#xff08;LPC&#xff09;这篇论文作者给的评价指标代码。 function [ rmse ] RMSE( img, C1, C2, pts1, pts2, mesh_X, mesh_Y, off )X_col lin…

图像处理之图像质量评价指标RMSE(均方根误差)

一、RMSE基本定义 MSE全称为“Root Mean Square Error”&#xff0c;中文意思即为均方根误差&#xff0c;是衡量图像质量的指标之一。计算原理为真实值与预测值的差值的平方然后求和再平均&#xff0c;最后开根号&#xff0c;公式如下&#xff1a; RMSE值越小&#xff0c;说明…

使用RMSE分析数据

一。数据概念和特征性 1. MSE&#xff08;Mean Square Error&#xff09;均方误差 是真实值与预测值的插值的平方然后求和平均。是绝对误差的平均值 能更好地反映预测值误差的实际情况. 2. RMSE&#xff08;Root Mean Square Error&#xff09;均方根误差 excel计算公式&am…

matlab计算分布模拟的rmse命令,用MATLAB求RMSE

满意答案 金牛座430 推荐于 2018.03.09 采纳率&#xff1a;55% 等级&#xff1a;12 已帮助&#xff1a;7454人 function fRMSE(h1,h2) %RMSE return RMSE(均方根误差) 求两图像的均方根误差 %input must be a imagehandle 输入图像句柄 %image fusion evaluate parameter 图…

matlab中rmse是什么意思,matlab sse和rmse

索引日期&#xff1a;2016-06-30 23:28:26 SSE,MSE,RMSE,R-square(转)_粽子_新浪博客 使用过Matlab的拟合、优化和统计等工具箱的网友,会经常___SSE,MSE,RMSE,R-square(转) SSE越接近于0,说明___ matlab里sse, rsquare, dfe, adjrsquare, r____百度知道 如题,SSE,RMSE,R-square…

rmse的作用

rmse的Emin的作用 链接http://t.csdn.cn/EkbZS RMSE vs MAE RMSE 与 MAE 的量纲相同&#xff0c;但求出结果后我们会发现RMSE比MAE的要大一些。 这是因为RMSE是先对误差进行平方的累加后再开方&#xff0c;它其实是放大了较大误差之间的差距。而MAE反应的就是真实误差。 因此在…

方差、标准差、均方差、均方根值(RMS)、均方根误差(RMSE)

文章目录 方差标准差均方差均方根值&#xff08;RMS&#xff09;均方根误差&#xff08;RMSE&#xff09; 方差 方差反映的是每个样本值与全体样本值的平均数之差的平方值的平均数。衡量随机变量或者一组数据与其期望的偏离程度。偏离程度越小&#xff0c;说明X的数值越稳定。…

RMSE、MAE和SD的基本概念

RMSE&#xff1a;均方根误差&#xff08;Root-mean-square error&#xff09;, 观测值与真值偏差的平方和与观测次数m比值的平方根。 假如有2000次观测&#xff0c;即m2000&#xff0c;对于某一次&#xff08;第i次&#xff09;观测来说&#xff0c;y值是真实值&#xff0c;而h…

RMSE

RMSE 即 均方根误差 。 均方根误差亦称 标准误差&#xff0c;其定义为 &#xff0c;i1&#xff0c;2&#xff0c;3&#xff0c;…n。在有限测量次数中&#xff0c;均方根误差常用下式表示&#xff1a;√[∑di^2/n]Re&#xff0c;式中&#xff1a;n为测量次数&#xff1b;di为一…

【转载】MSE(均方误差)、RMSE (均方根误差)、MAE (平均绝对误差)- 机器学习 - 线性回归之模型评估

MSE&#xff08;均方误差&#xff09;、RMSE &#xff08;均方根误差&#xff09;、MAE &#xff08;平均绝对误差&#xff09; 1、MSE&#xff08;均方误差&#xff09;&#xff08;Mean Square Error&#xff09; MSE是真实值与预测值的差值的平方然后求和平均。 范围[0,…

算法效果评估:均方根误差(RMSE)/ 标准误差

文章目录 1. 评估算法的效果2. 方差&#xff08;Variance&#xff09;2.1 总体方差2.1.1 在numpy中计算总体方差2.1.2 在pandas中计算总体方差 2.2 样本方差2.2.1 在numpy中计算样本方差2.2.2 在pandas中计算样本方差 3. 标准差 / 均方差 &#xff08;Standard Deviation&#…

SQL中的主键

一、什么是主键 数据库主键是指表中一个列或者列的组合&#xff0c;其值能够唯一的标识表中的每一个行。这样的一列或者多列成为表的主键&#xff0c;通过它可以强制表的实体完整性。当创建或者更改表时可以通过定义PRIMARY KEY约束来创建主键&#xff0c;一个表只能有一个主键…

MyBatis主键返回

这篇文章介绍了MyBatis的主键返回方法 一.需求分析 当我们表的主键设置为自增&#xff0c;且插入数据后需要主键id时&#xff0c;就要使用主键返回的方法&#xff0c;来获取当前插入数据的主键。 表如下&#xff1a; 二.主键返回 1.使用selectKey 标签 < selectKey >…

SQL主键

在SQL中主键是唯一标示表中每一行的列或一组列。SQL可以使用PRIMARY KEY约束为表创建主键。如果主键只包含一列&#xff0c;则可以将PRIMARY KEY约束定义为列约束 。每个表只能有一个主键。参与主键的所有列必须定义为NOT NULL。在SQL中如果没有为这些列指定NOT NULL约束&#…

PostgreSQL主键自增

1.创建表设置主键自增长 CREATE TABLE tab_name(id SERLAL primary key,username varchar,password varchar )SERLAL 为自增关键字 2.修改表字段为主键自增 1 创建关联序列 CREATE SEQUENCE tab_id_seq START 1; -- tab_id_seq 为序列名称 -- 1 为序列起始数2.1 在字段默认…

关于Adobe软件安装提示FATAL: Payload ‘Camera Profiles Installer …information not found in Media_db.问题解决方法

安装Photoshop CS6失败&#xff1a;FATAL: Payload ‘Camera Profiles Installer …information not found in Media_db. 安装失败描述 产生原因&#xff1a;出现以上情况是因为之前系统安装过Adobe相关软件&#xff0c;并且卸载不干净导致的。 解决方法&#xff1a;找到系统盘…

Nature综述:微生物构成的氮循环网络(收藏)

微生物构成的氮循环网络 The microbial nitrogen-cycling network 翻译&#xff1a;翟志文 中科院遗传发育所 责编&#xff1a;刘永鑫 中科院遗传发育所 Nature Reviews Microbiology, [31.851] https://doi.org/10.1038/nrmicro.2018.9 Published: 05 February 2018 第一作者…

特定功能基因定量检测

1 检测对象 特定功能基因指的是具有某种特定作用的酶的编码基因&#xff0c;通过对该酶的基因进行qPCR定量&#xff0c;来确定该基因在样本中的拷贝数。目前研究较多的主要是氮循环、碳循环、硫循环、砷循环等相关的功能基因。微基生物可以利用qPCR定量检测样本中的碳循环、氮…

Quantile g-computation的介绍及R实现

目录 介绍 模型 qgcomp包的使用 例1&#xff0c;线性模型 例2&#xff1a;条件OR&#xff0c;logistic模型中的边际OR 例3&#xff1a;调整协变量&#xff0c;绘制估计值 例4&#xff1a;非线性&#xff08;和非同质性&#xff09; 例5&#xff1a;比较模型拟合和进一步…

Nature综述:微生物构成的氮循环网络

导读论文ID综述结构综述内容 1.综述研究背景、研究目的、研究内容概述2.氮全球生化循环圈&#xff1a;全球的氮库存、氮转化过程、氮通量3.微生物构成的氮化合物的转化4.固氮作用5.羟胺氧化成一氧化氮以及进一步氧化成亚硝酸盐6.亚硝酸盐向硝酸盐的氧化7.硝酸盐还原为亚硝酸盐的…