在做实验、编写算法时我们经常需要涉及到矩阵的相关计算,包括加、减、乘、除、转置、求逆等等等等。在查阅相关资料后,我了解到一个名为 Efficient Java Matrix Library(EJML,高效矩阵运算包)的第三方库,并将其运用到了我的一个机器学习实验代码中(为什么不用python,我也不知道)。现在对我所用到的类和方法来做一个简单的总结。
Efficient Java Matrix Library(EJML)称为高效矩阵运算包,你可以在下面这个链接中获取到它的介绍,源代码,API文档、使用方法等等。
EJML直通车:Efficient Java Matrix Library (ejml.org)
http://ejml.org/wiki/index.php?title=Main_Page
以下是相关介绍,感兴趣的同学可以自己看看:

关于如何下载和配置第三库,可以看如下博客:
SimpleMatrix类(大概就称之为简单矩阵吧)包含了基本上所有的基础矩阵运算(加、减、乘、除、转置、求逆等),以下是对其中部分构造方法与成员方法的介绍:
1.1 创建一个空行矩阵
//创建一个2x4的空矩阵matrix(全部为0) // SimpleMatrix(int numRows, int numCols) // 行数 列数 SimpleMatrix matrix0 = new SimpleMatrix(2,4);
1.2 通过数组创建矩阵
//通过二维数组创建矩阵 //可以理解成将数组变成相同结构的矩阵 //1、以double型的二维数组构造相同结构的矩阵 // SimpleMatrix(double[][] data) double[][] arrayDouble2 = new double[2][4]; SimpleMatrix matrixDouble2 = new SimpleMatrix(arrayDouble2); System.out.println("matrixDouble2:\n"+matrixDouble2); //2、以float型的二维数组构造相同结构的矩阵 // SimpleMatrix(float[][] data) double[][] arrayFloat2 = new double[2][4]; SimpleMatrix matrixFloat2 = new SimpleMatrix(arrayFloat2); System.out.println("matrixFloat2:\n"+matrixFloat2);//通过一维数组创建矩阵 //可以理解成将一维数组的数据按照每一行(每一列)的顺序填入给定大小的矩阵 /* SimpleMatrix(int numRows, int numCols, boolean rowMajor, float/double[] data) 行数 列数 true(按行) false(按列) 数据源 */ double[] arrayDouble1 = {1,2,3,4,5,7,8,9};//double也行 //1.按照每一行填入数据 SimpleMatrix matrixDoubleRow = new SimpleMatrix(4,2,true,arrayDouble1); System.out.println("matrixDoubleRow:\n"+matrixDoubleRow); //2.按照每一列填入数据 SimpleMatrix matrixDoubleCol = new SimpleMatrix(4,2,false,arrayDouble1); System.out.println("matrixDoubleCol:\n"+matrixDoubleCol); /* matrixDoubleRow: 4x2 matrixDoubleCol: 4x2 [1,2] [1,5] [3,4] [2,6] [5,6] [3,7] [7,8] [4,8] */注意:通过一维数组创建矩阵时,一维数组的数据个数必须大于等于行列数需要数据个数。
先创建4x4的矩阵A和4x4的矩阵B,将矩阵A的所有元素都设置为1,将B的所有元素设置为2。
// void fill(double val) 将矩阵的所有元素都用val填充
// 如 matrix.fill(0.1) 表示将matrix的所有元素都设为0.1
SimpleMatrix matrixA = new SimpleMatrix(4,4); //创建4x4的矩阵A
SimpleMatrix matrixB = new SimpleMatrix(4,4); //创建4x4的矩阵B
matrixA.fill(1); //将A的所有元素设为1
matrixB.fill(2); //将B的所有元素设为2
System.out.println(matrixA);
System.out.println(matrixB);
/* 加、减法 T plus(double b) C = A + b 将矩阵A所有元素都加上b(如需减,则将b设为负) T plus(double beta, T B) C = A + betaB 将B的所有元素都乘以beta,再让加上A(如需减,则将beta设置为负) T plus(T B) C = A + B 矩阵A加上矩阵B T minus(double b) C = A - b 将矩阵A所有元素都减去b T minus(T B) C = A - B 矩阵A加上矩阵B */ matrixC.fill(1); matrixC = matrixA.plus(0.6); //A的所有元素乘以0.6 System.out.println(matrixC); matrixC.fill(1); matrixC = matrixA.plus(0.2,matrixB); // A + 0.2*B System.out.println(matrixC); matrixC.fill(1); matrixC = matrixA.plus(matrixB); // A + B System.out.println(matrixC); matrixC.fill(1); matrixC = matrixA.minus(6); // A的所有元素减6 System.out.println(matrixC); matrixC.fill(1); matrixC = matrixA.minus(matrixB); // A - B System.out.println(matrixC);
/* 乘法 1. 矩阵与矩阵相乘(行列式) T mult(T B) C = A * B 矩阵A与矩阵B相乘并返回 2. 数乘 T negative() C = -A 矩阵A的所有元素乘以-1 T scale(double val) C = val*A 矩阵A的所有元素乘以val */ matrixC = matrixA.mult(matrixB); // C = A * B System.out.println(matrixC); matrixC = matrixA.negative(); // C = -A System.out.println(matrixC); matrixC = matrixA.scale(9.99); // C = A*9.99 System.out.println(matrixC);
// 除法
// T divide(double val) C = A/val 将矩阵A的所有元素都除以val
matrixC = matrixA.divide(50); //C = A的所有元素都除以50所得的矩阵
System.out.println(matrixC);
/* 矩阵的转置
T transpose() 返回给定矩阵的转置
*/
int val = 1;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
matrixC.set(i, j, val);
val++;
}
} //设置矩阵的值
System.out.println(matrixC);
SimpleMatrix matrixC_transpose = matrixC.transpose(); //矩阵的转置
System.out.println(matrixC_transpose);
输出结果如图:

/* 矩阵的逆阵
T invert() 求可逆矩阵的逆阵
T pseudoInverse() 求摩尔彭若斯广义逆(对于可逆矩阵与上行方法一致)
*/
SimpleMatrix matrixD = new SimpleMatrix(4, 4);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (i == j) {
matrixD.set(i, j, i + 1);
} else {
matrixD.set(i, j, 0);
}
}
}
System.out.println("矩阵D:\n"+matrixD);
SimpleMatrix D_invert = matrixD.invert();
System.out.println("矩阵D的逆阵:\n"+D_invert);
SimpleMatrix D_pseudoInverse = matrixD.pseudoInverse();
System.out.println("矩阵D的广义逆阵:\n"+D_pseudoInverse);
输出结果如图:

3.1 创建N阶单位矩阵
//创建n阶单位矩阵 identity matrix
int n =7;
SimpleMatrix tempMatrix = new SimpleMatrix(n,1); //创建nx1的列向量
tempMatrix.fill(1); //所有元素置为1
SimpleMatrix I = tempMatrix.diag();
//A.diag()方法,如果A是矩阵,则返回一个由该矩阵的对角线上的值组成的列向量
// 如果A是列向量,则将其扩展为一个矩阵,矩阵的对角线的值就是该列向量
System.out.println(I);
3.2 其他操作(一)
SimpleMatrix matrix = new SimpleMatrix(8,8);
matrix.fill(4); //将矩阵元素都设置为4
matrix.zero(); //将矩阵元素都设置为0
matrix.set(1,4,3); //将第一行第四列元素设置为3
matrix.set(0,8); //将第零个元素设置为8
matrix.rows(1,2); //获取矩阵的部分行,第一个数表示开始的那一行,第二个数表示结束那一行加一(这里表示获取第一行)
matrix.cols(2,8); //获取矩阵的部分列,第一个数表示开始的那一列,第二个数表示结束那一列加一(这里表示获取第2,3,4,5,6,7行)
matrix.get(2,3); //获取第二行第三个数
matrix.get(2); //获取第二个元素
matrix.copy(); //复制一个矩阵
matrix.createLike(); //创建一个与matrix相同行列数且元素相同的矩阵
matrix.numRows(); //获取矩阵的行数
matrix.numCols(); //获取矩阵的列数
matrix.getNumElements(); //获取矩阵的元素个数(行数乘以列数)
matrix.elementMaxAbs(); //获取矩阵中所有元素绝对值的最大值
matrix.elementMinAbs(); //获取矩阵中所有元素绝对值的最小值
matrix.elementSum(); //计算矩阵中所有元素的和
matrix.normF(); //计算矩阵的二范数(所有元素平方和开根号,可以理解成向量的模)
matrix.determinant(); //计算矩阵行列数值
3.3 其他操作(二)(“乘”、“除”、“乘方”等等)
matrixC = matrixA.elementDiv(matrixB); // 对应相除 C(i,j) = A(i,j) / B(i,j)
matrixC = matrixA.elementMult(matrixB); // 对应相乘 C(i,j) = A(i,j) * B(i,j)
matrixC = matrixA.elementExp(); // C(i,j) = e 的 A(i,j)次方
matrixC = matrixA.elementLog(); // C(i,j) = ln(C(i,j))
matrixC = matrixA.elementPower(2); // C(i,j) = A(i,j)^2 (对应元素的n次方)
matrixC = matrixA.elementPower(matrixB); // C(i,j) = A(i,j)^(B(i,j)) (对应元素的对应次方)
以下是EJML提供的API文档,链接如下:
SimpleBase (ejml.org)
http://ejml.org/javadoc/org/ejml/simple/SimpleBase.htmlSimpleMatrix (ejml.org)
http://ejml.org/javadoc/org/ejml/simple/SimpleMatrix.html(SimpleMatrix继承了SimpleBase,所以很多方法声明在SimpleBase中)
感谢阅读!!!
import org.ejml.simple.SimpleMatrix;
public class test {
public static void main(String[] args) {
//-------------------------------------------------------------------
//创建一个2x4的矩阵matrix(全部为0)
// SimpleMatrix(int numRows, int numCols)
// 行数 列数
SimpleMatrix matrix0 = new SimpleMatrix(2, 4);
//-------------------------------------------------------------------
//通过二维数组创建矩阵
//可以理解成将数组变成相同结构的矩阵
//1、以double型的二维数组构造相同结构的矩阵
// SimpleMatrix(double[][] data)
double[][] arrayDouble2 = new double[2][4];
SimpleMatrix matrixDouble2 = new SimpleMatrix(arrayDouble2);
System.out.println("matrixDouble2:\n" + matrixDouble2);
//2、以float型的二维数组构造相同结构的矩阵
// SimpleMatrix(float[][] data)
double[][] arrayFloat2 = new double[2][4];
SimpleMatrix matrixFloat2 = new SimpleMatrix(arrayFloat2);
System.out.println("matrixFloat2:\n" + matrixFloat2);
//---------------------------------------------------------------------
//通过一维数组创建行列数
//可以理解成将一维数组的数据按照每一行(每一列)的顺序填入给定大小的矩阵
/* SimpleMatrix(int numRows, int numCols, boolean rowMajor, float/double[] data)
行数 列数 true(按行) false(按列) 数据源
*/
double[] arrayDouble1 = {1, 2, 3, 4, 5, 6, 7, 8, 9};//double也行
//1.按照每一行填入数据
SimpleMatrix matrixDoubleRow = new SimpleMatrix(4, 2, true, arrayDouble1);
System.out.println("matrixDoubleRow:\n" + matrixDoubleRow);
//2.按照每一列填入数据
SimpleMatrix matrixDoubleCol = new SimpleMatrix(4, 2, false, arrayDouble1);
System.out.println("matrixDoubleCol:\n" + matrixDoubleCol);
/* matrixDoubleRow: 4x2 matrixDoubleCol: 4x2
[1,2] [1,5]
[3,4] [2,6]
[5,6] [3,7]
[7,8] [4,8]
*/
//-------------------------------------------------------------------
SimpleMatrix matrixA = new SimpleMatrix(4, 4); //创建4x4的矩阵A
SimpleMatrix matrixB = new SimpleMatrix(4, 4); //创建4x4的矩阵B
SimpleMatrix matrixC = new SimpleMatrix(4, 4); //创建5x5的矩阵C
matrixA.fill(1); //将A的所有元素设为1
matrixB.fill(2); //将B的所有元素设为2
System.out.println(matrixA);
System.out.println(matrixB);
/* 加、减法
T plus(double b) C = A + b 将矩阵A所有元素都加上b(如需减,则将b设为负)
T plus(double beta, T B) C = A + betaB 将B的所有元素都乘以beta,再让加上A(如需减,则将beta设置为负)
T plus(T B) C = A + B 矩阵A加上矩阵B
T minus(double b) C = A - b 将矩阵A所有元素都减去b
T minus(T B) C = A - B 矩阵A加上矩阵B
*/
matrixC.fill(1);
matrixC = matrixA.plus(0.6); //A的所有元素乘以0.6
System.out.println(matrixC);
matrixC.fill(1);
matrixC = matrixA.plus(0.2,matrixB); // A + 0.2*B
System.out.println(matrixC);
matrixC.fill(1);
matrixC = matrixA.plus(matrixB); // A + B
System.out.println(matrixC);
matrixC.fill(1);
matrixC = matrixA.minus(6); // A的所有元素减6
System.out.println(matrixC);
matrixC.fill(1);
matrixC = matrixA.minus(matrixB); // A - B
System.out.println(matrixC);
/* 乘法
1. 矩阵与矩阵相乘(行列式)
T mult(T B) C = A * B 矩阵A与矩阵B相乘并返回
2. 数乘
T negative() C = -A 矩阵A的所有元素乘以-1
T scale(double val) C = val*A 矩阵A的所有元素乘以val
*/
matrixC = matrixA.mult(matrixB); // C = A * B
System.out.println(matrixC);
matrixC = matrixA.negative(); // C = -A
System.out.println(matrixC);
matrixC = matrixA.scale(9.99); // C = A*9.99
System.out.println(matrixC);
/* 除法
T divide(double val) C = A/val 将矩阵A的所有元素都除以val
*/
matrixC = matrixA.divide(50); //C = A的所有元素都除以50所得的矩阵
System.out.println(matrixC);
/* 矩阵的转置
T transpose() 返回给定矩阵的转置
*/
int val = 1;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
matrixC.set(i, j, val);
val++;
}
}
System.out.println(matrixC);
SimpleMatrix matrixC_transpose = matrixC.transpose();
System.out.println(matrixC_transpose);
/* 矩阵的逆阵
T invert() 求可逆矩阵的逆阵
T pseudoInverse() 求摩尔彭若斯广义逆(对于可逆矩阵与上行方法一致)
*/
SimpleMatrix matrixD = new SimpleMatrix(4, 4);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (i == j) {
matrixD.set(i, j, i + 1);
} else {
matrixD.set(i, j, 0);
}
}
}
System.out.println("矩阵D:\n"+matrixD);
SimpleMatrix D_invert = matrixD.invert();
System.out.println("矩阵D的逆阵:\n"+D_invert);
SimpleMatrix D_pseudoInverse = matrixD.pseudoInverse();
System.out.println("矩阵D的广义逆阵:\n"+D_pseudoInverse);
//---------------------------------------------------------------------
//创建n阶单位矩阵 identity matrix
int n =7;
SimpleMatrix tempMatrix = new SimpleMatrix(n,1); //创建nx1的列向量
tempMatrix.fill(1); //所有元素置为1
SimpleMatrix I = tempMatrix.diag();
//A.diag()方法,如果A是矩阵,则返回一个由该矩阵的对角线上的值组成的列向量
// 如果A是列向量,则将其扩展为一个矩阵,矩阵的对角线的值就是该列向量
System.out.println(I);
//---------------------------------------------------------------------
SimpleMatrix matrix = new SimpleMatrix(8,8);
matrix.fill(4); //将矩阵元素都设置为4
matrix.zero(); //将矩阵元素都设置为0
matrix.set(1,4,3); //将第一行第四列元素设置为3
matrix.set(0,8); //将第零个元素设置为8
matrix.rows(1,2); //获取矩阵的部分行,第一个数表示开始的那一行,第二个数表示结束那一行加一(这里表示获取第一行)
matrix.cols(2,8); //获取矩阵的部分列,第一个数表示开始的那一列,第二个数表示结束那一列加一(这里表示获取第2,3,4,5,6,7行)
matrix.get(2,3); //获取第二行第三个数
matrix.get(2); //获取第二个元素
matrix.copy(); //复制一个矩阵
matrix.createLike(); //创建一个与matrix相同行列数且元素相同的矩阵
matrix.numRows(); //获取矩阵的行数
matrix.numCols(); //获取矩阵的列数
matrix.getNumElements(); //获取矩阵的元素个数(行数乘以列数)
matrix.elementMaxAbs(); //获取矩阵中所有元素绝对值的最大值
matrix.elementMinAbs(); //获取矩阵中所有元素绝对值的最小值
matrix.elementSum(); //计算矩阵中所有元素的和
matrix.normF(); //计算矩阵的二范数(所有元素平方和开根号,可以理解成向量的模)
matrix.determinant(); //计算矩阵行列数值
//---------------------------------------------------------------------
matrixC = matrixA.elementDiv(matrixB); // 对应相除 C(i,j) = A(i,j) / B(i,j)
matrixC = matrixA.elementMult(matrixB); // 对应相乘 C(i,j) = A(i,j) * B(i,j)
matrixC = matrixA.elementExp(); // C(i,j) = e 的 A(i,j)次方
matrixC = matrixA.elementLog(); // C(i,j) = ln(C(i,j))
matrixC = matrixA.elementPower(2); // C(i,j) = A(i,j)^2 (对应元素的n次方)
matrixC = matrixA.elementPower(matrixB); // C(i,j) = A(i,j)^(B(i,j)) (对应元素的对应次方)
}
}
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我
什么是ruby的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht
点向量坐标矩阵的几何意义介绍旋转矩阵的几何含义之前,先介绍一下点向量坐标矩阵的几何含义点:在一维空间下就是一个标量,如同一条直线上,以任意某一个位置为0点,以一定的尺度间隔为1,2,3...,相反方向为-1,-2,-3...;如此就形成了一维坐标系,这时候任何一个点都可以用一个数值表示,如点p1=5,即即从原点出发沿着x轴正方向移动5个尺度;点p2=-3,负方向移动3个尺度; 在一维坐标系上过原点做垂直于一维坐标系的直线,则形成了二维坐标系,此时描述一个点需要两个数值来表示点p3=(3,2),即从原点出发沿着x轴正方向移动3个尺度,在此基础上沿着y轴正方向移动两个尺度的位置就是点p3。
这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/
HashMap中为什么引入红黑树,而不是AVL树呢1.概述开始学习这个知识点之前我们需要知道,在JDK1.8以及之前,针对HashMap有什么不同。JDK1.7的时候,HashMap的底层实现是数组+链表JDK1.8的时候,HashMap的底层实现是数组+链表+红黑树我们要思考一个问题,为什么要从链表转为红黑树呢。首先先让我们了解下链表有什么不好???2.链表上述的截图其实就是链表的结构,我们来看下链表的增删改查的时间复杂度增:因为链表不是线性结构,所以每次添加的时候,只需要移动一个节点,所以可以理解为复杂度是N(1)删:算法时间复杂度跟增保持一致查:既然是非线性结构,所以查询某一个节点的时候
遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg
我基本上来自Java背景并且努力理解Ruby中的模运算。(5%3)(-5%3)(5%-3)(-5%-3)Java中的上述操作产生,2个-22个-2但在Ruby中,相同的表达式会产生21个-1-2.Ruby在逻辑上有多擅长这个?模块操作在Ruby中是如何实现的?如果将同一个操作定义为一个web服务,两个服务如何匹配逻辑。 最佳答案 在Java中,模运算的结果与被除数的符号相同。在Ruby中,它与除数的符号相同。remainder()在Ruby中与被除数的符号相同。您可能还想引用modulooperation.