1 数据结构

userCount:用户数
itemCount:项目数
user_ratings:ArrayList<ArrayList>,
问:此处为什么要用二维数组?
答:第1维是用户,第2维是用户对所有项目的评分。
testRatings:ArrayList
问:此处为什么只用一维数组?
答:个人认为这个处理有问题,因为每个用户有1-2个评分作为测试集,如果用一维数组,则数组的下标就不能和用户id(userId)一一对应。

2 读取评分:ReadRatings_HoldOneOut

步骤如下:

  1. 从文件中一行行读取,然后存入user_ratings中,存储后如下:
    用户0:
    [<0,0,4.0,0>,<0,1,4.0,0>,…,<0,64,5.0,0>,<0,65,3.0,0>][<0,0,4.0,0>, <0,1,4.0,0>, \dots, <0,64,5.0,0>, <0,65,3.0,0>][<0,0,4.0,0>,<0,1,4.0,0>,…,<0,64,5.0,0>,<0,65,3.0,0>]
    注:<userId, itemId, score, timestamp>,<0,0,4.0,0><0,0,4.0,0><0,0,4.0,0>可以解读为用户0对项目0在0时刻评分为4.0分。
    用户1:
    [<1,0,5.0,0>,<1,66,4.0,0>,…,<1,192,1.0,0>,<1,193,5.0,0>][<1,0,5.0,0>, <1,66,4.0,0>, \dots, <1,192,1.0,0>, <1,193,5.0,0>][<1,0,5.0,0>,<1,66,4.0,0>,…,<1,192,1.0,0>,<1,193,5.0,0>]
    用户2:
    [<2,0,5.0,0>,<2,194,5.0,0>,…,<2,202,5.0,0>,<2,203,5.0,0>][<2,0,5.0,0>, <2,194,5.0,0>, \dots, <2,202,5.0,0>, <2,203,5.0,0>][<2,0,5.0,0>,<2,194,5.0,0>,…,<2,202,5.0,0>,<2,203,5.0,0>]
  2. 利用user_ratings构造训练集和测试集testRatings
    [<0,65,3.0,0>,<0,64,5.0,0>,<1,193,5.0,0>,<1,192,1.0,0>,<2,203,5.0,0>,<2,202,5.0,0>,<3,278,5.0,0>,<3,277,4.0,0>,<4,290,4.0,0>,<4,289,5.0,0>,<5,328,2.0,0>,<5,327,5.0,0>,<6,394,4.0,0>,<6,393,5.0,0>,<7,406,5.0,0>,<7,405,2.0,0>,<8,420,3.0,0>,<8,419,3.0,0>,<9,482,5.0,0>,<9,481,4.0,0>,…][<0,65,3.0,0>, <0,64,5.0,0>, <1,193,5.0,0>, <1,192,1.0,0>, <2,203,5.0,0>, <2,202,5.0,0>, <3,278,5.0,0>, < 3,277,4.0,0>, <4,290,4.0,0>, <4,289,5.0,0>, <5,328,2.0,0>, <5,327,5.0,0>, <6,394,4.0,0>, <6,393,5.0,0>, <7,406,5.0,0>, <7,405,2.0,0>, <8,420,3.0,0>, <8,419,3.0,0>, <9,482,5.0,0>, <9,481,4.0,0>, \dots][<0,65,3.0,0>,<0,64,5.0,0>,<1,193,5.0,0>,<1,192,1.0,0>,<2,203,5.0,0>,<2,202,5.0,0>,<3,278,5.0,0>,<3,277,4.0,0>,<4,290,4.0,0>,<4,289,5.0,0>,<5,328,2.0,0>,<5,327,5.0,0>,<6,394,4.0,0>,<6,393,5.0,0>,<7,406,5.0,0>,<7,405,2.0,0>,<8,420,3.0,0>,<8,419,3.0,0>,<9,482,5.0,0>,<9,481,4.0,0>,…]
    问:这种方式有问题没有?
    答:有,测试集由于是一个一维的列表,导致利用testRatings.get(u).itemId这个代码来取数据的时候,u并不是指代某个用户id,而是列表中某个位置的下标,容易误解为用户id和项目id不匹配。

上面的不匹配是由于下面的代码导致的,由于每一个用户将最后两个评分加入到测试集,导致用户id和列表的下标对应不上。

//if (i == ratings.size() - 1) { // test
if (i == ratings.size() - 1 || i == ratings.size() - 2) { // testtestRatings.add(ratings.get(i));//the size of testing =    the number of users.
} else { // traintrainMatrix.setValue(userId, itemId, ratings.get(i).score);
}//of if

方案(1):改成如下代码即可,使得每个用户只有一个评分加入测试集,即测试集大小和用户数一致

if (i == ratings.size() - 1) { // test
//if (i == ratings.size() - 1 || i == ratings.size() - 2) { // testtestRatings.add(ratings.get(i));//the size of testing =  the number of users.
} else { // traintrainMatrix.setValue(userId, itemId, ratings.get(i).score);
}//of if

方案(2):可以用二维列表来存储测试集。

3 evaluate_for_user的理解

3.1 数据结构

map_item_score:HashMap<Integer, Double>,散列表。HashMap的主干是一个Entry数组,Entry是HashMap的基本组成单元,每一个Entry包含一个key-value键值对。

HashMap<Integer, Double> map_item_score = new HashMap<Integer, Double>();

ignoreSet:HashSet ,HashSet 基于 HashMap 来实现的,一个不允许有重复元素的集合。

3.2 代码解读

 /*** Evaluation for a specific user with given GT item.对具有给定Groud-Truth项目的特定用户的评估* @return:*    result[0]: hit ratio*   result[1]: ndcg*    result[2]: precision*/protected double[] evaluate_for_user(int u, int gtItem) {double[] result = new double[3];HashMap<Integer, Double> map_item_score = new HashMap<Integer, Double>();// Get the score of the test item first.double maxScore = predict(u, gtItem);// Early stopping if there are topK items larger than maxScore.int countLarger = 0;for (int i = 0; i < itemCount; i++) {double score = predict(u, i);//预测用户u对所有项目的评分map_item_score.put(i, score);//将预测评分放入散列表中,key为i,value为score//下面的两句的作用是只要gtItem没有进入TopK则不计算三个评价指标?if (score > maxScore)    countLarger ++;if (countLarger > topK) return result;  // early stopping}// Selecting topK items (does not exclude train items).ArrayList<Integer> rankList = ignoreTrain ? CommonUtils.TopKeysByValue(map_item_score, topK, trainMatrix.getRowRef(u).indexList()) : CommonUtils.TopKeysByValue(map_item_score, topK, null);result[0] = getHitRatio(rankList, gtItem);result[1] = getNDCG(rankList, gtItem);result[2] = getPrecision(rankList, gtItem);return result;}/*** Get the topK keys (by its value) of a map. Does not consider the keys which are in ignoreKeys.* @param map* @return*/public static<K, V extends Comparable<? super V>> ArrayList<K> TopKeysByValue(Map<K, V> map, int topK, ArrayList<K> ignoreKeys) {HashSet<K> ignoreSet;if (ignoreKeys == null) {ignoreSet = new HashSet<K>();} else {ignoreSet = new HashSet<K> (ignoreKeys);//将训练集中用户u购买过的项目放入ignoreSet}//因为map保存的是所有项目,如果要忽略训练集中的项目,则将训练集之外的项目写入topQueueTopKPriorityQueue<K, V> topQueue = new TopKPriorityQueue<K, V>(topK);for (Map.Entry<K, V> entry : map.entrySet()) {if (!ignoreSet.contains(entry.getKey())) {topQueue.add(entry);}}//对topQueue中的元素进行排序,排序后保存在topKeys并返回ArrayList<K> topKeys = new ArrayList<K>();for (Map.Entry<K, V> entry : topQueue.sortedList()) {topKeys.add(entry.getKey());}return topKeys;}public ArrayList<Map.Entry<K, V>> sortedList() {ArrayList<Map.Entry<K, V>> list = new ArrayList<Map.Entry<K, V>>(queue); Collections.sort(list, c.reversed()); return list;}

Collections.sort参考博客https://baijiahao.baidu.com/s?id=1660417080221659283&wfr=spider&for=pc

这里还用到了一个非常重要的接口Comparable。
功能: Comparable接口可用于对象的排序或者对象的分组

介绍: Comparable接口强行对实现它的类的每个实例进行自然排序,该接口的唯一方法compareTo方法被称为自然比较方法
方法: int compareTo(Object o)

利用当前对象和传入的目标对象进行比较:

  • 若是当前对象比目标对象大,则返回1,那么当前对象会排在目标对象的后面
  • 若是当前对象比目标对象小,则返回-1,那么当前对象会排在目标对象的后面
  • 若是两个对象相等,则返回0
import java.util.Arrays;public class User implements Comparable<User> {public int age;public String username;public User(int age, String username) {this.age = age;this.username = username;}@Overridepublic String toString() {return this.username;}@Overridepublic int compareTo(User o) {if(this.age>o.age) {return 1;} else if(this.age<o.age) {return -1;} else {return 0;}}public static void main(String[] args) {User[] arr = new User[3];arr[0] = new User(15,"user1");arr[1] = new User(10,"user2");arr[2] = new User(20,"user3");System.out.println("排序前:" + Arrays.toString(arr));Arrays.sort(arr);System.out.println("排序后:" + Arrays.toString(arr));}
}排序前:[user1, user2, user3]
排序后:[user2, user1, user3]

Fast Matrix Factorization for Online Recommendation with Implicit Feedback论文代码分析相关推荐

  1. BPR: Bayesian Personalized Ranking from Implicit Feedback 论文笔记

    有什么问题欢迎讨论呀! 论文标题:BPR: Bayesian Personalized Ranking from Implicit Feedback BPR 主要采用用户的隐式反馈(如点击.收藏等), ...

  2. 多模态--[GRCN]Graph-Refined Convolutional Network for Multimedia Recommendation with Implicit Feedback

    摘要: (这篇文章就觉得, 它是通过动态图解决了隐式反馈一些偶然的交互边的问题) 将用户的隐式反馈重组为用户-商品交互图有助于图卷积网络(GCNs)在推荐任务中的应用.在交互图中,用户节点与商品节点之 ...

  3. 文论瞎读:Network Embedding as Matrix Factorization: Unifying DeepWalk, LINE, PTE, and node2vec

    Network Embedding as Matrix Factorization: Unifying DeepWalk, LINE, PTE, and node2vec 论文地址:https://a ...

  4. 论文笔记:Probabilistic Matrix Factorization

    一.基本信息 论文题目:<Probabilistic Matrix Factorization> 发表时间:NIPS  2007 论文作者及单位: 论文地址:https://dl.acm. ...

  5. 【论文阅读】 BPR: Bayesian Personalized Ranking from Implicit Feedback

    BPR: Bayesian Personalized Ranking from Implicit Feedback 论文链接:https://arxiv.org/abs/1205.2618 Abstr ...

  6. 论文笔记:BPR-Bayesian Personalized Ranking from Implicit Feedback | 推荐系统BPR算法分析

    BPR:Bayesian Personalized Ranking from Implicit Feedback 论文链接:BPR:Bayesian Personalized Ranking from ...

  7. Matrix Factorization: A Simple Tutorial and Implementation in Python

    本文转自http://www.quuxlabs.com/blog/2010/09/matrix-factorization-a-simple-tutorial-and-implementation-i ...

  8. Non-negative Matrix Factorization 非负矩阵分解

    Non-negative Matrix Factorization 非负矩阵分解 Introduction 定义 非负矩阵分解(non-negative matrix factorization),或 ...

  9. 2021_SIGIR_Social Recommendation with Implicit Social Influence

    [论文阅读笔记]2021_SIGIR_Social Recommendation with Implicit Social Influence 论文下载地址: https://doi.org/10.1 ...

最新文章

  1. linux虚拟实验室关闭了,centos8禁用selinux临时关闭/永久关闭
  2. (技能篇)双机热备之Oracle切换故障处理
  3. 清除element残留表单校验
  4. Xtrabackup备份MySQL
  5. linux跨ip拷贝,Linux的虚拟机拷贝到另外的操作系统时,NAT方式的静态IP无效,一直是获取的DHCP动态地址...
  6. Winsock编程补遗
  7. winxp计算机远程桌面连接,winxp系统远程桌面不能连接指定计算机的解决方法
  8. mysql流程函数if之类
  9. HDU1847 博弈论 水题
  10. 2012最新网上购物排行榜
  11. java 实现屏幕录像_用JAVA捕获屏幕、屏幕录像、播放
  12. 硬件蓝牙测试软件,【原创】聊聊蓝牙测试专用硬件工具-Ubertooth
  13. Pytorch聊天机器人
  14. Python中最快的搜索引擎之一:ThreadSearch(自己开发)(abccdee1)
  15. oracle 日期的常用写法
  16. docker版mongodb数据同步到elasticsearch
  17. FontAwesome-基本样式-1.1
  18. java吐泡泡过关,java代码,鱼吐泡泡程序
  19. 迅雷导出ed2k到eMule链接无效处理
  20. 国密sm2 js加密后台解密,sm3 js、后台加密,sm4 后台加密

热门文章

  1. c可以 char* 赋值但是c++不可以_雷佳音的妻子完全可以女团C位出道,这么有气质的女人,谁能不爱...
  2. php守护进程内存溢出,$serv-close($fd); 服务端主动断开客户端有问题!
  3. 软件工程 团队博客作业 如何评价个人在团队中的绩效
  4. 高中学生计算机软件,中学生计算器
  5. JAVA入门级教学之(package和import)
  6. 一部分 数据 迁移_从虚机到容器,知名架构师告诉你如何平滑进行业务迁移
  7. python字符串_教你快速了解 Python 字符串
  8. 零基础学习java必须要了解的学习路线
  9. java解析excel文件_1.3.1 python解析excel格式文件
  10. python去重语句_Python对列表去重的多种方法(四种方法)