日撸代码300行:第55天(基于 M-distance 的推荐 (续))

news2024/11/16 23:46:33

代码来自闵老师”日撸 Java 三百行(51-60天)“,链接:https://blog.csdn.net/minfanphd/article/details/116975957

工作承接第54天的基于M-distance 的推荐,目标是自己实现一下user-based recommendation。原博客中的提示有两种方案,自己选在了便于实现的一个方案,但是算法复杂度较高。另外一个方案需要将包含同一个项目(item_{i})的用户保存,需要添加相应的代码。代码运行下来时间复杂度是比较高。

本人实现的代码如下:

package machinelearning.knn;

/**
 * Recommendation with M-distance.
 * @author WX873
 */
import java.io.*;
import java.util.PrimitiveIterator.OfDouble;


public class MBR {
	
	/**
	 * Default rating for 1-5 points.
	 */
	public static final double DEFAULT_RATING = 3.0;
	
	/**
	 * The total number of users.
	 */
	private int numUsers;
	
	/**
	 * The total number of items.
	 */
	private int numItems;
	
	/**
	 * The total number of ratings (non-zero values)
	 */
	private int numRatings;
	
	/**
	 * The predictions.
	 */
	private double[] predictions;
	
	/**
	 * Compressed rating matrix. User-item-rating triples.
	 */
	private int[][] compressedRatingMatrix;
	
	/**
	 * The degree of users (how many item he has rated).
	 */
	private int[] userDegrees;
	
	/**
	 * The average rating of the current user.
	 */
	private double[] userAverageRatings;
	
	/**
	 * The degree of items (how many users has rated this item).
	 */
	private int[] itemDegrees;
	
	/**
	 * The average rating of the current item.
	 */
	private double[] itemAverageRatings;
	
	/**
	 * The first user start from 0. Let the first user has x ratings, the second
	 * user will start from x. The start index x is for dataset's item.
	 */
	private int[] userStartingIndices;
	
	/**
	 * Number of non-neighbor objects.
	 */
	private int numNonNeighbors;
	
	/**
	 * The radius (delta) for determining the neighborhood.
	 */
	private double radius;
	
	/**
	 * Construct the rating matrix.
	 * 
	 * @param paraFilename   The rating filename.
	 * @param paraNumUsers   Number of users
	 * @param paraNumItems   Number of items
	 * @param paraNumRatings  Number of ratings
	 * @throws Exception
	 */
	public MBR(String paraFilename, int paraNumUsers, int paraNumItems, int paraNumRatings) throws Exception {
		// Step 1. Initialize these arrays
		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];
		
		// 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);
		}//of if
		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[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;
				}//of if
			}//of if
			tempIndex++;
		}//of while
		tempBufReader.close();
		
		double[] tempUserTotalScore = new double[numUsers];
		double[] tempItemTotalScore = new double[numItems];
		for (int i = 0; i < numRatings; i++) {
			tempUserTotalScore[compressedRatingMatrix[i][0]] += compressedRatingMatrix[i][2];  
//compressedRatingMatrix[i][0]的值是用户名,所以相当于tempUserTotalScore[]的地址是用户名,里面存的是该用户的总分
			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
	
	/**
	 * *****************************************
	 * Set the radius (delta).
	 * @param paraRadius
	 * 		The given radius.
	 * *****************************************
	 */
	public void setRadius(double paraRadius) {
		if (paraRadius > 0) {
			radius = paraRadius;
		}else {
			radius = 0.1;
		}//of if
		
	}//of setRadius
	
	/*
	 * ***************************************************************************
	 * Leave-one-out prediction user based. The predicted values are stored in predictions.
	 * 
	 * @see predictions
	 * ***************************************************************************
	 */
	public void leaveOneOutPredictionBsaedUser() {
		double tempUserAverageRating;
		//Make each line of the code shorter.
		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];
			
			//Step 1. Recompute average rating of the current user.
			tempUserAverageRating = (userAverageRatings[tempUser] * userDegrees[tempUser] - tempRating)/(userDegrees[tempUser] - 1);
			
			// Step 2. Recompute neighbors, at the same time obtain the ratings of neighbors.
			int tempNeighbors = 0;
			double tempTotal = 0;
			int tempComparedUser;
			for (int j = 0; j < numRatings; j++) {
				tempComparedUser = compressedRatingMatrix[j][0];
				if (tempUser == tempComparedUser) {
					continue; //Ignore itself
				}//of if
				
				if (Math.abs(tempUserAverageRating - userAverageRatings[tempComparedUser]) < radius) {
					tempTotal += compressedRatingMatrix[j][2];
					tempNeighbors ++;
				}//of if
			}//of for j

			
			//Step 3. Predict as the average value of neighbors.
			if (tempNeighbors > 0) {
				predictions[i] = tempTotal/tempNeighbors;
			}else {
				predictions[i] = DEFAULT_RATING;
				numNonNeighbors++;
			}//of if
		}//of for i
	}//of leaveOneOutPredictionBsaedUser
	
	/****************************************************************
	 * Compute the MAE based on the deviation of each leave-one-out.
	 * 
	 * @return
	 * @throws Exception
	 * **************************************************************
	 */
	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
		
		double tempAverage = tempTotalError / predictions.length;
		return Math.sqrt(tempAverage);
	}//of computeRSME
	
	/****************************************************************
	 * Compute the RSME based on the deviation of each leave-one-out.
	 * 
	 * @return
	 * @throws Exception
	 * **************************************************************
	 */
	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
	
	/***
	 * **************************************************
	 * The entrance of the program.
	 * @param args
	 * **************************************************
	 */
	public static void main(String args[]) {
		try {
			MBR tempRecommender = new MBR("E:/Datasets/UCIdatasets/temp/movielens-943u1682m.txt", 943, 1682, 100000);
			
			for (double tempRadius = 0.2; tempRadius < 0.6; tempRadius += 0.1) {
				tempRecommender.setRadius(tempRadius);
				
				tempRecommender.leaveOneOutPredictionBsaedUser();
				double tempMAE = tempRecommender.computeMAE();
				double tempRSME = tempRecommender.computeRSME();
				
				System.out.println("Radius = " + tempRadius + ", MAE = " + tempMAE + ", RSME = " + tempRSME
						+ ", numNonNeighbors = " + tempRecommender.numNonNeighbors);
			}//of for tempRadius
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println(e);
		}//of try
	}//of main

}//MBR

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/797952.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

NLP实验案例100个(6-10)

实验六 数据类型 一、实验目的及要求 熟悉数据的数据类型二、实验设备&#xff08;环境&#xff09;及要求 开发环境&#xff1a;jupyter notebook 开发语言以及相关的库&#xff1a;python开发语言 numpy库 三、实验内容与步骤 1.创建一个array类型的数据&#xff0c;设置…

【ShaderToy中图形效果转译到UnityShaderlab案例分享,纯代码实现卡通心跳_Pattern】

Shader"ShaderToy/Pattern" {Properties{_MainTex("_MainTex", 2D) = "white"{}}SubShader{Pass{CGPROGRAM

性能如何通过分析后台资源确定瓶颈之CPU内存

确定瓶颈之CPU、内存 影响性能的因素 CPU 内存 网络 硬件 i/o 中间件 应用服务器 数据库 家门口的路比较拥堵&#xff1a;解决方案---多来几条路/加宽路/修地铁/修个桥、修整路面、找交警指挥交通/红绿灯、限行、分散周围居民、收费、其他路段的问题 CPU--中央处理器--…

使用go与智能合约交互之函数选择器调用

go与智能合约交互的方式有很多种&#xff0c;其中一种方式可以在不知道合约源码的情况下进行调用&#xff0c;接下来让我们一起学习一下。 1、首先我们安装一下go-ethereum go get -u github.com/ethereum/go-ethereum2、新建main.go文件&#xff0c;添加依赖 import ("…

KEIL 软件学习魔法棒

Device 芯片选型 Target : 晶振设置 Output: 选择中间文件的生成路径 Objects (创建文件夹之后再选择) &#xff0c;创建hex文件 Listing : 创建文件夹之后再选择 USER&#xff1a;改变生成的 hex 文件路径 C/C &#xff1a;宏定义 和 路径选择 &#xff08;目前使用到的&#…

压力测试-商场项目

1.压力测试 压力测试是给软件不断加压&#xff0c;强制其在极限的情况下运行&#xff0c;观察它可以运行到何种程度&#xff0c;从而发现性能缺陷&#xff0c;是通过搭建与实际环境相似的测试环境&#xff0c;通过测试程序在同一时间内或某一段时间内&#xff0c;向系统发送预…

陪诊小程序软件|陪诊系统定制|医院陪诊小程序

开发一个陪诊小程序需要投入一定的费用&#xff0c;具体金额会因项目的复杂程度、功能需求和推广政策而有所差异在投入资金之前&#xff0c;建议进行市场调研和需求分析&#xff0c;制定出合理的预算&#xff0c;并选择专业的开发团队进行合作&#xff0c;那么开发陪诊小程序需…

KingFunsion工程开发规范——关系库使用规范

KingFunsion工程开发规范——关系库使用规范 2023-07-07 20:10雷工笔记 哈喽&#xff0c;大家好&#xff0c;我是雷工。 今天学习KingFunsion工程开发规范之关系库使用规范。 第一章 统一规范 1.1.表字符集默认使用utf8&#xff1b; 1.2.禁止在数据库中存储大文件&#xff0…

新的CoolSiC™槽沟MOSFET技术,用于低栅氧化物应力和高性能

标题&#xff1a;The new CoolSiC™ Trench MOSFET Technology for Low Gate Oxide Stress and High Performance UPS&#xff08;Uninterruptible Power Supply&#xff09;系统也称不间断电源系统&#xff0c;是一种能够提供电力备用的设备&#xff0c;当主电源出现故障或停…

无涯教程-jQuery - jQuery.post( url, data, callback, type)方法函数

jQuery.post(url&#xff0c;[data]&#xff0c;[callback]&#xff0c;[type])方法使用POST HTTP请求从服务器加载页面。 该方法返回XMLHttpRequest对象。 jQuery.post( url, [data], [callback], [type] ) - 语法 $.post( url, [data], [callback], [type] ) 这是此方法使…

3秒钟教你如何配置vscode中的vue3代码快速生成模版

1.首先点击你的vscode左下角的齿轮设置按钮&#xff0c;然后点击配置用户代码片段。 2.输入vue搜索vue.json这个文件&#xff0c;然后点击这个文件 3.接下来只需在原有的注释之下输入粘贴如下代码即可 代码如下&#xff1a; "vue3": {"prefix": "vue3…

前后端分离开发,使用Nginx部署Vue

nginx相关的命令&#xff08;要在nginx报下打开cmd执行相应的命令&#xff09; 开启nginx&#xff1a;start nginx 关闭nginx&#xff1a;nginx.exe -s quit 怎么把现有的前端环境部署在nginx上 安装并配置好Nginx后&#xff0c;您可以通过以下步骤来访问项目的前端页面&#…

软件安全测试:软件产品高质量的守门员

软件安全测试是保障软件产品高质量的重要环节&#xff0c;它扮演着守门员的角色&#xff0c;为软件产品提供安全性与稳定性的保护。在互联网与信息化时代&#xff0c;软件产品的需求日益增长&#xff0c;同时也伴随着对软件安全的重视。 1、软件安全测试的定义与重要性 软件安…

智能网关实现混凝土搅拌机无人自动化

“以前的搅拌站生产时&#xff0c;是需要人工巡检的&#xff0c;运送物料和搅拌时产生的大量粉尘污染和噪音&#xff0c;让工人苦不堪言。但是如果有了物联网搅拌站监测系统智慧园区项目落地后&#xff0c;工人也不用去现场忍受噪音和粉尘了。” 行业痛点 传统模式下的混泥土…

【代码随想录day21】二叉搜索树中的插入操作

题目 给定二叉搜索树&#xff08;BST&#xff09;的根节点 root 和要插入树中的值 value &#xff0c;将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 &#xff0c;新值和原始二叉搜索树中的任意节点值都不同。 注意&#xff0c;可能存在多种有效的插入…

二叉树(C++,代码)

例子&#xff1a;前序输入 AB##CDF#G#E#### (#表示空&#xff0c;不存在&#xff09; #include<iostream> using namespace std; typedef struct BiNode {char data;struct BiNode* lchild, * rchild; }BiNode,*Bitree; char ch; int m, n; t…

(小白必看)详解yolov5训练自己的数据集 使用香烟数据集训练yolov5识别香烟

数据集资源 https://download.csdn.net/download/qq_42864343/88110620?spm1001.2014.3001.5503 https://download.csdn.net/download/qq_42864343/88110686?spm1001.2014.3001.5501 创建数据集目录 在YOLOv5根目录下创建mydata文件夹&#xff08;名字可以自定义&#xf…

如何少走弯路?蚓链助力零售企业实现数字化转型

基于大环境下的数据驱动&#xff0c;创新业务模式成为了后疫情时代下零售企业冲破困局、拓展业务的必然趋势&#xff0c;新零售概念应运而生。新零售结合数字化应用技术为传统零售企业打造线上营销生态链&#xff0c;帮助企业积累数据&#xff0c;盘活数据实现更大营收价值。 …

CTFshow web入门 爆破

web21 bp 攻击模块的迭代器 输入账号密码 抓包 发现下面存在一个base64编码 我输入的是 123 123 发现就是base加密 账号 密码 那我们怎么通过intruder模块 自动变为 base64呢 然后去payload------>custom iterator(自定义迭代器) 位置1导入admin 因为是 账号:密码 这…

三维虚拟电子沙盘数字沙盘态势推演教程第12课

三维虚拟电子沙盘数字沙盘态势推演教程第12课 设置system.ini 如下内容 Server122.112.229.220 userGisTest Passwordchinamtouch.com 该数据库中只提供 成都市火车南站附近的数据请注意&#xff0c;104.0648,30.61658 SDK中自带了一套 导航系统&#xff0c;用的是比较详细的…