IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> day22--基于M-distance的推荐(day54) -> 正文阅读

[游戏开发]day22--基于M-distance的推荐(day54)

1.出处来源

论文来源: Mei Zheng, Fan Min, Heng-Ru Zhang, Wen-Bin Chen, Fast recommendations with the M-distance, IEEE Access 4 (2016) 1464–1468 的源代码. 点击下载论文.

通过下面这张图来观察:

在这里插入图片描述
图解:u0,u1,…是代表不同的用户,m0,m1,…是代表不同的项目,图中的数据的用户对不同项目的评分,现在我们根据M-distance来估计出所在位置的得分。首先计算出每一种项目所得的平均分,同时也要计算出未知分所在的项目的均分,然后我们在这个未知项目的周围找到误差满足在0.3以内的项目,然后根据未知分对应的用户对满足那个误差的项目的评分就平均值,该平均值我们估计就是为未知分数的值。
我们以右边的这个表为例,首先r就是提前算出来的那个平均值,我们需要求的未知分数(u1,m3)所在的平均数是3.7,我们要找到满足误差在0.3以内的项目平均分,那就是项目m0,m5,然后未知分数对应的用户是u1,然后u1对m0,m5的评分分别是4,3,平均分为(4+3)/2=3.5,所以我们估计未知分数为3.5。

2.基于M-distance的推荐

下面以不同用户对不同电影的评分为例,然后将数据存储在 https://github.com/FanSmale/sampledata/ 中 movielens-943u1682m.txt.
在这里插入图片描述
文档中,一共943个用户,1682部电影,10000条评分记录
0,11,5表示:用户0对电影11的评分是5

3.代码实现

3.1变量解释

	//如果没有满足条件的数据,则默认分数为3
	public static final double DEFAULT_RATING = 3.0;
	//用户数量
	private int numUsers;
	//电影数量
	private int numItems;
	//评分记录数量
	private int numRatings;
	//预测
	private double[] predictions;
	//将文件中的数据读取存放在改二维数中
	private int[][] compressedRatingMatrix;
	//一个用户看的电影量
	private int[] userDegrees;
	//记录每个用户对电影评分的平均分
	private double[] userAverageRatings;
	//一部电影获得用户的评分量
	private int[] itemDegrees;
	//记录每部电影获得的平均分
	private double[] itemAverageRatings;
	//记录不同用户开始的索引
	private int[] userStartingIndices;
	
	private int numNonNeighbors;

	private double radius;

3.2构造方法

主要是完成一些数据的初始化

  • 首先传入4个变量,分别是文件路径,用户数量,电影数量,记录数量
	public MBR(String paraFilename, int paraNumUsers, int paraNumItems, int paraNumRatings) throws Exception {
		numItems = paraNumItems;
		numUsers = paraNumUsers;
		numRatings = paraNumRatings;

		userDegrees = new int[numUsers];
		userStartingIndices = new int[numUsers + 1];
		userAverageRatings = new double[numUsers];
		itemDegrees = new int[numItems];
		compressedRatingMatrix = new int[numRatings][3];
		itemAverageRatings = new double[numItems];

		predictions = new double[numRatings];

		System.out.println("Reading " + paraFilename);

		// Step 2. Read the data file.
		File tempFile = new File(paraFilename);
		if (!tempFile.exists()) {
			System.out.println("File " + paraFilename + " does not exists.");
			System.exit(0);
		} 
		//一行一行的读
		BufferedReader tempBufReader = new BufferedReader(new FileReader(tempFile));
		String tempString;
		String[] tempStrArray;
		int tempIndex = 0;
		userStartingIndices[0] = 0;
		userStartingIndices[numUsers] = numRatings;
		while ((tempString = tempBufReader.readLine()) != null) {
			// Each line has three values
			tempStrArray = tempString.split(",");
			compressedRatingMatrix[tempIndex][0] = Integer.parseInt(tempStrArray[0]);
			compressedRatingMatrix[tempIndex][1] = Integer.parseInt(tempStrArray[1]);
			compressedRatingMatrix[tempIndex][2] = Integer.parseInt(tempStrArray[2]);
			
			//userDegrees是记录每个用户一共对多少部电影进行了评价
			//itemDegrees是记录一部电影一共有多少个用户进行了评价
			userDegrees[compressedRatingMatrix[tempIndex][0]]++;
			itemDegrees[compressedRatingMatrix[tempIndex][1]]++;

			if (tempIndex > 0) {
				// Starting to read the data of a new user.
				if (compressedRatingMatrix[tempIndex][0] != compressedRatingMatrix[tempIndex - 1][0]) {
					//记录每个不同的用户开始的索引位置
					userStartingIndices[compressedRatingMatrix[tempIndex][0]] = tempIndex;
				}
			} 
			tempIndex++;
		} // of while
		tempBufReader.close();
		
		//tempUserTotalScore是用于统计一个用户给电影评分的总和
		//tempItemTotalScore是用于统计一部电影的评分总和
		double[] tempUserTotalScore = new double[numUsers];
		double[] tempItemTotalScore = new double[numItems];
		for (int i = 0; i < numRatings; i++) {
			tempUserTotalScore[compressedRatingMatrix[i][0]] += compressedRatingMatrix[i][2];
			tempItemTotalScore[compressedRatingMatrix[i][1]] += compressedRatingMatrix[i][2];
		} //of for i

		for (int i = 0; i < numUsers; i++) {
			//记录用户对于每部电影的平均分
			userAverageRatings[i] = tempUserTotalScore[i] / userDegrees[i];
		} // of for i
		for (int i = 0; i < numItems; i++) {
			//记录每部电影获得的平均分
			itemAverageRatings[i] = tempItemTotalScore[i] / itemDegrees[i];
		} // of for i
	}// of the first constructor

3.3 核心代码

public void leaveOneOutPrediction() {
		double tempItemAverageRating;
		int tempUser, tempItem, tempRating;
		System.out.println("\r\nLeaveOneOutPrediction for radius " + radius);

		numNonNeighbors = 0;
		for (int i = 0; i < numRatings; i++) {
			tempUser = compressedRatingMatrix[i][0];
			tempItem = compressedRatingMatrix[i][1];
			tempRating = compressedRatingMatrix[i][2];

			//预测位置的点,先去掉该点的得分,然后再重新计算它的平均值
			tempItemAverageRating = (itemAverageRatings[tempItem] * itemDegrees[tempItem] -tempRating)/ (itemDegrees[tempItem] - 1);

			int tempNeighbors = 0;
			double tempTotal = 0;
			int tempComparedItem;
			for (int j = userStartingIndices[tempUser]; j < userStartingIndices[tempUser + 1]; j++) {
				tempComparedItem = compressedRatingMatrix[j][1];
				if (tempItem == tempComparedItem) {
					continue;//ignore itself.
				}

				//若误差满足radius
				if (Math.abs(tempItemAverageRating - itemAverageRatings[tempComparedItem]) < radius) {
					tempTotal += compressedRatingMatrix[j][2];
					tempNeighbors++;
				}
			} // of for j

			if (tempNeighbors > 0) {
				predictions[i] = tempTotal / tempNeighbors;
			} else {
				//如果所有的邻居都超过误差值,则默认值为3
				predictions[i] = DEFAULT_RATING;
				numNonNeighbors++;
			} 
		} // of for i
	}// of leaveOneOutPrediction

3.4 算法评价

MAE(平均绝对误差)
	public double computeMAE() throws Exception {
		double tempTotalError = 0;
		for (int i = 0; i < predictions.length; i++) {
			//预测评分减去实际的评分,求绝对值,然后累加起来
			tempTotalError += Math.abs(predictions[i] - compressedRatingMatrix[i][2]);
		} // Of for i

		return tempTotalError / predictions.length;
	}// Of computeMAE
RMSE(平方根误差)
	public double computeRSME() throws Exception {
		double tempTotalError = 0;
		for (int i = 0; i < predictions.length; i++) {
			//预测评分减去实际的评分,求平方,然后累加起来
			tempTotalError += (predictions[i] - compressedRatingMatrix[i][2]) * (predictions[i] - compressedRatingMatrix[i][2]);
		} // Of for i

		double tempAverage = tempTotalError / predictions.length;

		return Math.sqrt(tempAverage);
	}// Of computeRSME

4.运行结果

在这里插入图片描述

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-05-08 08:26:50  更:2022-05-08 08:26:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 11:31:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码