矩阵

浅谈矩阵分解在推荐系统中的应用

纵饮孤独 提交于 2020-01-22 21:43:59
  为了方便介绍,假设推荐系统中有用户集合有6个用户,即U={u1,u2,u3,u4,u5,u6},项目(物品)集合有7个项目,即V={v1,v2,v3,v4,v5,v6,v7},用户对项目的评分结合为R,用户对项目的评分范围是[0, 5]。R具体表示如下: 推荐系统的目标就是预测出符号“?”对应位置的分值。推荐系统基于这样一个假设:用户对项目的打分越高,表明用户越喜欢。因此,预测出用户对未评分项目的评分后,根据分值大小排序,把分值高的项目推荐给用户。怎么预测这些评分呢,方法大体上可以分为基于内容的推荐、协同过滤推荐和混合推荐三类,协同过滤算法进一步划分又可分为基于基于内存的推荐(memory-based)和基于模型的推荐(model-based),本文介绍的矩阵分解算法属于基于模型的推荐。 矩阵分解算法的数学理论基础是矩阵的行列变换。在《线性代数》中,我们知道矩阵A进行行变换相当于A左乘一个矩阵,矩阵A进行列变换等价于矩阵A右乘一个矩阵,因此矩阵A可以表示为A=PEQ=PQ(E是标准阵)。 矩阵分解目标就是把用户-项目评分矩阵R分解成用户因子矩阵和项目因子矩阵乘的形式,即R=UV,这里R是n×m, n =6, m =7,U是n×k,V是k×m。直观地表示如下: 高维的用户-项目评分矩阵分解成为两个低维的用户因子矩阵和项目因子矩阵,因此矩阵分解和PCA不同,不是为了降维

垒骰子(矩阵快速幂)

本小妞迷上赌 提交于 2020-01-22 19:26:42
题目描述: 赌圣atm晚年迷恋上了垒骰子,就是把骰子一个垒在另一个上边,不能歪歪扭扭,要垒成方柱体。 经过长期观察,atm 发现了稳定骰子的奥秘:有些数字的面贴着会互相排斥! 我们先来规范一下骰子:1 的对面是 4,2 的对面是 5,3 的对面是 6。 假设有 m 组互斥现象,每组中的那两个数字的面紧贴在一起,骰子就不能稳定的垒起来。 atm想计算一下有多少种不同的可能的垒骰子方式。 两种垒骰子方式相同,当且仅当这两种方式中对应高度的骰子的对应数字的朝向都相同。 由于方案数可能过多,请输出模 10^9 + 7 的结果。 不要小看了 atm 的骰子数量哦~ 输入格式: 第一行两个整数 n m n表示骰子数目 接下来 m 行,每行两个整数 a b ,表示 a 和 b 数字不能紧贴在一起。 输出格式: 一行一个数,表示答案模 10^9 + 7 的结果。 样例输入: 2 1 1 2 样例输出: 544 数据范围: 对于 30% 的数据:n <= 5 对于 60% 的数据:n <= 100 对于 100% 的数据:0 < n <= 10^9, m <= 36 题目思路: from: https://blog.csdn.net/qq_34594236/article/details/53616283 简单矩阵快速幂的应用,求出递推矩阵,编程实现即可。 重点是利用相对的面构造 6×6 的转移矩阵

关于Unity中Shader的使用

你离开我真会死。 提交于 2020-01-22 19:08:44
在游戏的开发过程中,程序员不太会自己去写shader,因为写起来很麻烦,而且只有Unity会报错,编译器也没有什么提示。 通常是拿别人的shader改一改,当然,程序员还是要能看懂和会一点shader Unity坐标系转换 1: transform.localToWorldMatrix 局部转世界的矩阵; 2: transfrom.worldToLocalMatrix 世界坐标转局部坐标矩阵;  MultiplyPoint, MultiplyPoint3x4 MultiplayVector 来进行坐标变换; 4: shader中 左乘_World2Object矩阵来实现世界坐标转局部坐标变换; 5: shader中左乘_Object2World矩阵来实现局部转世界的转换; 6: UNITY_MATRIX_MV 基本变换矩阵 x 摄像机矩阵; 7: UNITY_MATRIX_MVP 基本变换矩阵x摄像机矩阵x投影矩阵; 8: UNITY_MATRIX_V 摄像机矩阵; 9: UNITY_MATRIX_P 投影矩阵; 10: UNITY_MATRIX_VP摄像机矩阵x投影矩阵; 11: UNITY_MATRIX_T_MV (基本变换矩阵 x 摄像机矩阵) 转置矩阵; 12: UNITY_MATRIX_IT_MV(基本变换矩阵 x 摄像机矩阵) 的逆转置矩阵; 13: UNITY

银行家算法

…衆ロ難τιáo~ 提交于 2020-01-22 10:06:12
在了解银行家算法之前,我们先了解一下 死锁 的概念和它的相关知识。 死锁 概念 :多个进程相互等待,互不相让,导致所有进程无限期等待。 死锁分为 资源死锁 和 通信死锁 。 资源死锁 :每个进程都在等待其他进程释放资源。资源死锁时最常见的死锁类型。 通信死锁 :由于信息丢失,导致通信双方互相等待对方发送消息。一般可以设置超时时间来解决。 资源死锁条件 1) 互斥条件 :一个进程不能被两个以上的进程同时占有。 2) 占有和等待 :已经得到某个资源的进程可以申请新的资源。 3) 不可抢占条件 :已经分配给一个进程的资源不能被强制性抢占,他只能被占有它的进程显式释放。 4) 环路等待 :死锁发生时,系统中一定有两个及两个以上的进程形成一条环路。 死锁处理 1)忽略问题。 2)检测死锁并恢复 3)避免死锁 4)防止死锁发生 今天我们要说的就是死锁避免的策略— 银行家算法 银行家算法是最有代表性的避免死锁的算法。在避免死锁方法中允许进程动态的申请资源,但系统在进行资源分配之前,应该先计算此次分配资源的安全性,若果分配不会导致系统进入不安全状态,则分配,否则等待。 先说一下算法中需要的数据结构: 1.可利用资源向量 Available :他是一个一维数组。其中的每一个元素代表一类可利用的资源数目。它的数值会根据资源的分配和回收发生改变。比如Available[i]=k

最大联通子数组和

本秂侑毒 提交于 2020-01-22 08:40:58
设计题目:求一个二维数组的连通的数组中和最大的最大值。 设计思路: 先建立二维数组并遍历二维数组,将所有的正整数进行分块,然后验证是否联通,如果不联通,则判断路径。 代码: package demo; import java.util.*; public class Lmax { static Scanner scanner = new Scanner(System.in); public static void main(String args[]){ int m,n; int b; Scanner scanner = new Scanner(System.in); System.out.println("请输入二维数组的列数:"); m = scanner.nextInt(); System.out.println("请输入二维数组的行数:"); n = scanner.nextInt(); int arr[][] = new int[n][m]; System.out.println("请输入:"); for(int i = 0;i<n;i++) for(int j=0;j<m;j++) { arr[i][j] = scanner.nextInt(); } System.out.println("\n"); b = maxArrSum(arr); System.out

搜索二维矩阵

和自甴很熟 提交于 2020-01-22 08:17:40
编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性: 每行中的整数从左到右按升序排列。 每行的第一个整数大于前一行的最后一个整数。 示例 1: 输入: matrix = [ [1, 3, 5, 7], [10, 11, 16, 20], [23, 30, 34, 50] ] target = 3 输出: true mark 解决思路: 使用二分查找,m行n列的矩阵matrix共有mn个元素,其中第x个元素对应matrix中位置为[x/n][x%n]。 实现代码如下: public static boolean searchMatrix(int[][] matrix, int target) { int m = matrix.length; if (m == 0) return false; int n = matrix[0].length; int N = m*n; int l=0,h=N-1; int mid = (l+h)/2; int i,j; while(l<=h) { i = mid/n; j = mid%n; if (matrix[i][j] == target) return true; else if (target>matrix[i][j]) l = mid+1; else h = mid-1; mid = (l+h)/2; }

剑指offer:二维数组查找【每日一题】

谁说我不能喝 提交于 2020-01-22 05:10:00
描述 在一个二维数组中,每一行都按照从左到右递增的顺序排列,每一列都按照从上到下递增顺序排列。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。 测试用例: 1 2 8 9 2 4 9 12 4 7 10 13 6 8 11 15 查找7输出 9,因为9 = 4*2+1 第三行第二列 思路 根据剔除行和列来进行查找,起点右上角或者左下角 如果 该数字大于查找数字,则删除行 如果 该数字小于查找数字,则删除列 终止条件: 行小于length,列大于零(从右上角查找) 代码 # include <stdio.h> //二维数组假设以行列存储,实际是一维指针 int Find ( int * Array , int rowLen , int colLen , int find ) { if ( Array == NULL ) { return - 1 ; } if ( rowLen >= 0 && colLen >= 0 ) { //右上角开始 for ( int i = 0 ; i < rowLen ; ) { for ( int j = colLen - 1 ; j >= 0 ; ) { if ( Array [ i * colLen + j ] == find ) return i * colLen + j ; else if ( Array [ i *

矩阵连乘问题

ⅰ亾dé卋堺 提交于 2020-01-22 03:15:11
由于矩阵乘法运算满足结合率,如果有矩阵A、B、C、D连续相乘,那么 A(BCD) = (AB)(CD) = … 。 所以可以找到一个好的加括号顺序使得计算量减少。可以使用动态规划问题解决。 动态规划解题步骤: 1, 找到最优子结构 即子问题最优可以令父问题也达到最优。本例中,若想(ABCDEFG)*(HIJKLMN)计算步骤最少,那么ABCDEFG加括号方式一定是最优的,同理HIJKLMN加括号也是最优的。可以尝试使用分治法(递归)先求出最优解。 2,使用空间换时间 使用一个空间保存子问题的解,另一个空间保存求解过程,计算某个子问题时,先判断子问题是否已经解决,如果已经解决,则直接返回已保存的解,否则计算这个子问题的解并存下。即,将上一步分治的计算结果存在一个数组里,并将分治的过程保存在另一个数组里。 3,找到最优解 根据保存的求解过程,找到最优解。 运行结果: 代码如下 # include <iostream> using namespace std ; /* 递归求解最优的加括号方式 * i 子问题下界 * j 子问题上界 * k 存储子问题的解 * s 存储子问题求解过程 * */ int mulSqlAct ( int w [ ] , int h [ ] , int i , int j , int * * k , int * * s ) { if ( j - i <= 1

重学数据结构 --- 分类+稀疏数组

若如初见. 提交于 2020-01-22 02:15:33
一、数据结构的分类 1. 数据结构两大类 线性结构 和 非线性结构 1) 线性结构 线性结构是最常见的数据结构,特点是元素间存在一对一的线性关系。 线性结构又分两种,一种是顺序存储(称为顺序表),另外一种是链式存储(称为链表)。顺序表中的存储元素的连续的。链表中的存储元素不一定是连续的,元素节点中存放数据元素以及相邻元素的地址信息。 常见的线性结构有:数组、队列、链表和栈(这里只是讲个大概,具体内容后面的文章会展开阐述)。 2) 非线性结构 非线性结构就是结点元素可能存在多个直接前趋和多个直接后续(联想一下二叉树就懂了,但是非线性结构不仅仅只有二叉树)。 非线性结构包括:多维数组、广义表、树结构、图结构。 二、稀疏数组 1. 稀疏数组(sparse array) 1) 分析场景 有这么一个场景,需要实现一个 10*10 的围棋的步数记录。那么最简单的就可以使用一个二维数组int[10][10]便可,但是在棋盘伊始,这个二维数组几乎没有意义的数据。假如能找到将这个二维数组压缩,只记录有用的数据的方法就好了。这时候稀疏数组就可以派上用场了。 2) 稀疏数组 像上述棋盘,开始的时候,数据中记录的大部分元素为 0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组。 3) 稀疏数组的处理方法是: 记录数组一共有几行几列,有多少个不同的值

C++中二维数组传参的方法详解

巧了我就是萌 提交于 2020-01-21 23:29:31
C++中二维数组传参的方法详解 首先需要明确,C++中其实没有多维数组,所谓的多维数组,其实就是数组的数组; 另外,数组中元素的个数也是数组类型的一部分。 当一个数组的元素仍然是数组时,通常使用2个维度来定义它,一个数组表示数组本身的大小,另一个维度表示其元素大小(它的元素也是数组): int ia[3][4]; //大小为3的数组,每个元素是含有4个整数的数组 int (*p)[4] = ia;//p指向含有4个整数的数组(指向第一个内层数组) 1 将给定第二维长度的二维数组作为形参传递 #include<iostream> using namespace std; void outputArray1(int ia[][4]) { for (int i = 0; i != 3; ++i) { for (int j = 0; j != 4; ++j) { cout << ia[i][j] << endl; } } } int main() { int ia[3][4] = { {1, 2, 8, 9 }, {2, 4, 9, 12}, {4, 7, 10, 13} }; //输出数组中所有元素 outputArray1(ia); return 0; } 2 使用给定第二维长度的指针作为形参传递 #include<iostream> using namespace std; void