Welcome to my GitHub

https://github.com/zq2599/blog_demos

Content: Classification and summary of all original articles and supporting source code, involving Java, Docker, Kubernetes, DevOPS, etc.;

Overview of this article

  • As the fifth article in the "DL4J Actual Combat" series, after having a certain understanding of deep learning, this article will suspend deep learning-related operations and turn to basic exercises: matrix operations, that is, the basic usage of the INDArray interface
  • The class diagram of INDArray is as follows. Since BaseNDArray is an abstract class, in actual use, we all use instances of NDArray:

在这里插入图片描述

  • The reason why I use an article to learn matrix operation is because it is everywhere in the actual combat process, and it is inseparable from it everywhere. If you are not skilled, it will be difficult to do it.
  • There are many APIs involved in this article, so do the classification first. The following code will be clearer to write according to the classification. There are five categories: matrix attributes, creation operations, read operations, write operations, matrix calculations, and then use The mind map lists the common APIs of each category
  • Matrix properties:

在这里插入图片描述

  • Create operation:

在这里插入图片描述

  • Read operation:

在这里插入图片描述

  • Write operation:

在这里插入图片描述

  • Matrix calculation:

在这里插入图片描述

Source download

nameLinkRemark
Project homepagehttps://github.com/zq2599/blog_demosThe project's homepage on GitHub
git warehouse address (https)https://github.com/zq2599/blog_demos.gitThe warehouse address of the source code of the project, https protocol
git warehouse address (ssh)git@github.com:zq2599/blog_demos.gitThe warehouse address of the source code of the project, ssh protocol
  • There are multiple folders in this git project. The source code of the "DL4J Actual Combat" series is under the <font color="blue">dl4j-tutorials</font> folder, as shown in the red box below:

在这里插入图片描述

  • There are multiple sub-projects in the <font color="blue">dl4j-tutorials</font> folder. The actual combat code is in the <font color="blue">ndarray-experience</font> directory, as shown in the red box below :

在这里插入图片描述

Create project

  • Create a new subproject named <font color="blue">ndarray-experience</font> under the parent project <font color="blue">dl4j-tutorials</font>, and its pom.xml is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>dlfj-tutorials</artifactId>
        <groupId>com.bolingcavalry</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>ndarray-experience</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.nd4j</groupId>
            <!--注意要用nd4j-native-platform,否则容器启动时报错:no jnind4jcpu in java.library.path-->
            <artifactId>${nd4j.backend}</artifactId>
        </dependency>

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
        </dependency>
    </dependencies>

</project>
  • The following code is written in the <font color="blue">ndarray-experience</font> project

The most basic method

  • List the two most basic methods first, and you will use them frequently when you learn later:
  • rand: rank, dimension, for example, a two-dimensional matrix with 2 rows and 3 columns, the return value of the rand method is equal to 2
  • shape: the size of each dimension of the matrix, such as a two-dimensional matrix with 2 rows and 3 columns, the return value of the shape method is equal to <font color="blue">[2, 3]</font>
  • Prepare a static method to print out the details of the INDArray instance, using the rand and shape methods:
    private static void disp(String type, INDArray indArray) {
        StringBuilder stringBuilder = new StringBuilder("*****************************************************\n");
        stringBuilder.append(type)
                     .append("\n维度 : ").append(indArray.rank())
                     .append("\n形状 : ").append(Arrays.toString(indArray.shape()))
                     .append("\n完整矩阵 : \n").append(indArray);

        System.out.println(stringBuilder);
    }

Create matrix

  1. All zero matrix: zeros
// 创建2行3列的全零矩阵
INDArray indArray0 = Nd4j.zeros(2, 3);
disp("全零矩阵", indArray0);
  • Results of the
全零矩阵
维度 : 2
形状 : [2, 3]
完整矩阵 : 
[[         0,         0,         0], 
 [         0,         0,         0]]
  1. All 1 matrix: ones
// 创建2行3列的全一矩阵
INDArray indArray1 = Nd4j.ones(2, 3);
disp("全一矩阵", indArray1);
  • Results of the
全一矩阵
维度 : 2
形状 : [2, 3]
完整矩阵 : 
[[    1.0000,    1.0000,    1.0000], 
 [    1.0000,    1.0000,    1.0000]]
  1. A matrix of all specified values: valueArrayOf
// 创建2行3列的全是指定值的矩阵
INDArray indArray2 = Nd4j.valueArrayOf(new int[] {2, 3}, 888);
disp("全是指定值(888)的矩阵", indArray2);
  • Results of the
全是指定值(888)的矩阵
维度 : 2
形状 : [2, 3]
完整矩阵 : 
[[  888.0000,  888.0000,  888.0000], 
 [  888.0000,  888.0000,  888.0000]]
  1. rand: random matrix (random number between 0 and 1)
// 创建2行3列的随机矩阵
INDArray indArray2 = Nd4j.rand(2, 3);
disp("随机矩阵", indArray2);
  • Results of the
随机矩阵
维度 : 2
形状 : [2, 3]
完整矩阵 : 
[[    0.7236,    0.5159,    0.1908], 
 [    0.9458,    0.4413,    0.4173]]
  1. Random Gaussian distribution matrix (mean value is 0, standard deviation is 1): randn
// 创建2行3列的随机高斯分布矩阵
INDArray indArray3 = Nd4j.randn(2, 3);
disp("随机高斯分布矩阵", indArray3);
  • Results of the
随机高斯分布矩阵
维度 : 2
形状 : [2, 3]
完整矩阵 : 
[[   -0.4287,   -0.5790,    0.5004], 
 [   -0.5122,    1.0551,   -0.1998]]
  1. Arithmetic sequence: linspace
// 创建等差数列,
// 从1到6、长度为10的等差数列
INDArray indArray4 = Nd4j.linspace(1,6, 10);
disp("等差数列", indArray4);
  • Results of the
等差数列
维度 : 1
形状 : [10]
完整矩阵 : 
[    1.0000,    1.5556,    2.1111,    2.6667,    3.2222,    3.7778,    4.3333,    4.8889,    5.4444,    6.0000]
  1. Create a matrix based on an array: create(float[] data, int[] shape)
// 根据数组创建2行3列的矩阵
INDArray indArray6 = Nd4j.create(new float[] {1, 2, 3, 4, 5, 6}, new int[]  {2,3});
disp("根据数组创建矩阵", indArray6);
  • Results of the
根据数组创建矩阵
维度 : 2
形状 : [2, 3]
完整矩阵 : 
[[    1.0000,    2.0000,    3.0000], 
 [    4.0000,    5.0000,    6.0000]]
  1. Three-dimensional matrix
// 三维矩阵
INDArray indArray7 = Nd4j.valueArrayOf(new int[] {2, 2, 3}, 888);
disp("三维矩阵", indArray7);

Three-dimensional matrix
Dimensions: 3
Shape: [2, 2, 3]
Complete matrix:
[[[ 888.0000, 888.0000, 888.0000],
[ 888.0000, 888.0000, 888.0000]],

[[ 888.0000, 888.0000, 888.0000],
[ 888.0000, 888.0000, 888.0000]]]


9. 创建正方形二维矩阵,并且对角线上的元素值都是1.0:

// Create a two-dimensional matrix with 3 rows and 3 columns, with a diagonal value of 1.0
INDArray indArray10 = Nd4j.eye(3);
disp("3*3 matrix, and the diagonal is 1.0", indArray10);


- 执行结果

3*3 matrix, and the diagonals are all 1.0
Dimensions: 2
Shape: [3, 3]
Complete matrix:
[[ 1.0000, 0, 0],
[ 0, 1.0000, 0],
[ 0, 0, 1.0000]]


### 读操作

- 接下来试试读取相关的操作,回顾前面用数组创建的2行3列的矩阵,内容如下:

[[ 1.0000, 2.0000, 3.0000],
[ 4.0000, 5.0000, 6.0000]]


1. 读取指定位置:

System.out.println("Read the value of the first column of the first row: "+ indArray6.getDouble(1,1));


- 执行结果

Read the value of the first row and first column position: 5.0


2. 指定行:

System.out.println("Read the first line: "+ indArray6.getRow(1));


- 执行结果

Read the first line: [4.0000, 5.0000, 6.0000]


3. 指定列:

System.out.println("Read the second column: "+ indArray6.getColumn(2));


- 执行结果

Read the second column: [3.0000, 6.0000]


4. 指定多列:

System.out.println("Read the second and third columns: "+ indArray6.getColumns(1,2));


- 执行结果

Read the second and third columns: [[ 2.0000, 3.0000],
[ 5.0000, 6.0000]]


### 写操作

- 接下来试试读取相关的操作,回顾前面用数组创建的2行3列的矩阵,内容如下:

[[ 1.0000, 2.0000, 3.0000],
[ 4.0000, 5.0000, 6.0000]]


1. 修改指定位置,查看了源码后发现,put方法内容实际上是在调用putScalar方法:

indArray6.put(1,1, 123);
indArray6.putScalar(0,0, 456);
disp("a. After modification", indArray6);


- 执行结果

a. After modification
Dimensions: 2
Shape: [2, 3]
Complete matrix:
[[ 456.0000, 2.0000, 3.0000],
[ 4.0000, 123.0000, 6.0000]]


2. 修改整行:

// Prepare a one-dimensional array
INDArray row1 = Nd4j.create(new float[] {9,8,7});

// Replace the entire row of the matrix with a one-dimensional array
indArray6.putRow(1, row1);
disp("b. After modification", indArray6);


- 执行结果

b. After modification
Dimensions: 2
Shape: [2, 3]
Complete matrix:
[[ 456.0000, 2.0000, 3.0000],
[ 9.0000, 8.0000, 7.0000]]


### 矩阵计算

- 矩阵计算,咱们从最基本的四则运算开始
1. 加减乘除,入参是一个标量,会与矩阵中的所有元素做计算

// Prepare the original data, a matrix of 2 rows and 3 columns
indArray6 = Nd4j.create(new float[] {1, 2, 3, 4, 5, 6}, new int[] {2,3});

// addition
disp("Addition", indArray6.add(1));

// subtraction
disp("Subtraction", indArray6.sub(1));

// multiplication
disp("Multiplication", indArray6.mul(2));

// Division
disp("Division", indArray6.div(2));


- 执行结果

addition
Dimensions: 2
Shape: [2, 3]
Complete matrix:
[[ 2.0000, 3.0000, 4.0000],
[ 5.0000, 6.0000, 7.0000]]


Subtraction
Dimensions: 2
Shape: [2, 3]
Complete matrix:
[[ 0, 1.0000, 2.0000],
[ 3.0000, 4.0000, 5.0000]]


multiplication
Dimensions: 2
Shape: [2, 3]
Complete matrix:
[[ 2.0000, 4.0000, 6.0000],
[ 8.0000, 10.0000, 12.0000]]


division
Dimensions: 2
Shape: [2, 3]
Complete matrix:
[[ 0.5000, 1.0000, 1.5000],
[ 2.0000, 2.5000, 3.0000]]


2. 前面的add方法,执行完毕后会生成一个新的NDArray实例,不影响原对象,但如果调用的是<font color="blue">addi</font>,就会修改原对象的内容:

INDArray indArray8 = Nd4j.create(new float[] {1, 2, 3, 4, 5, 6}, new int[] {2,3});
disp("before replacement", indArray8);
indArray8.addi(1);
disp("After replacement", indArray8);


- 执行结果

Before replacement
Dimensions: 2
Shape: [2, 3]
Complete matrix:
[[ 1.0000, 2.0000, 3.0000],
[ 4.0000, 5.0000, 6.0000]]


After replacement
Dimensions: 2
Shape: [2, 3]
Complete matrix:
[[ 2.0000, 3.0000, 4.0000],
[ 5.0000, 6.0000, 7.0000]]


3. 展开:Nd4j.toFlattened,2行3列的二维矩阵展开后成了一维的

disp("Expand", Nd4j.toFlattened(indArray6));


- 执行结果

Unfold
Dimensions: 1
Shape: [6]
Complete matrix:
[ 1.0000, 2.0000, 3.0000, 4.0000, 5.0000, 6.0000]


4. 转换:reshape,相当于使用原有数据,但是换一个shape入参

disp("Conversion", indArray6.reshape(3,2));


- 执行结果

Conversion
Dimensions: 2
Shape: [3, 2]
Complete matrix:
[[ 1.0000, 2.0000],
[ 3.0000, 4.0000],
[ 5.0000, 6.0000]]


5. 提取正方形矩阵的对角线:diag,得到的结果是一维的

// Create a square matrix with 3 rows and 3 columns
INDArray indArray9 = Nd4j.create(new float[] {1, 2, 3, 4, 5, 6, 7, 8, 9}, new int[] {3,3});
disp("3*3 matrix", indArray9);
// Extract the diagonal of the square matrix
disp("The diagonal of the 3*3 matrix", Nd4j.diag(indArray9));


- 执行结果如下图,diag方法得到了源对象的对角线

![在这里插入图片描述](/img/bVcVvxp)

6. 基于源矩阵形状创建新矩阵,且值都相通(入参值),然后用此新矩阵减去源矩阵:rsub

// Initialize a matrix with 2 rows and 3 columns
INDArray indArray11 = Nd4j.create(new float[] {1, 2, 3, 4, 5, 6}, new int[] {2,3});
// Refer to the structure of indArray12 to create a matrix with 2 rows and 3 columns. The values of all elements of the matrix are equal to 10 (input parameters),
// Then, subtract indArray11 from the matrix, and the result is returned as the return value of the rsub method
INDArray indArray12 = indArray11.rsub(10);
disp("rsub method", indArray12);


- 执行结果如下,可见所有值都是10减去源矩阵对应位置的值:

rsub method
Dimensions: 2
Shape: [2, 3]
Complete matrix:
[[ 9.0000, 8.0000, 7.0000],
[ 6.0000, 5.0000, 4.0000]]


7. 两个矩阵相加:add,两个形状相通的矩阵,同样位置的值相加:

INDArray indArray13 = Nd4j.create(new float[] {1, 2, 3, 4, 5, 6}, new int[] {2,3});
INDArray indArray14 = Nd4j.create(new float[] {1, 1, 1, 1, 1, 1}, new int[] {2,3});

disp("Matrix addition", indArray13.add(indArray14));


- 执行结果

Matrix addition
Dimensions: 2
Shape: [2, 3]
Complete matrix:
[[ 2.0000, 3.0000, 4.0000],
[ 5.0000, 6.0000, 7.0000]]


8. 叉乘:mmul,2行3列乘以3行2列,

INDArray indArray13 = Nd4j.create(new float[] {1, 2, 3, 4, 5, 6}, new int[] {2,3});
INDArray indArray15 = Nd4j.create(new float[] {1, 2, 3, 4, 5, 6}, new int[] {3,2});
disp("2 rows and 3 columns", indArray13);
disp("3 rows and 2 columns", indArray15);
disp("The cross product of a matrix with 2 rows and 3 columns and a matrix with 3 rows and 2 columns", indArray13.mmul(indArray15));


- 执行结果,可见,2行3列矩阵的每一行的元素,都和3行2列矩阵每一列的元素做两两相乘再相加,一共四个值,所以结果就是2行2列的矩阵:

![在这里插入图片描述](/img/bVcVvxq)

9. 矩阵所有元素值累加:sum

INDArray indArray16 = Nd4j.create(new float[] {1, 2, 3, 4, 5, 6}, new int[] {2,3});
// sum
double sum = indArray16.sum().getDouble();
System.out.println("Accumulated sum of matrix elements: "+ sum);


- 执行结果

Cumulative sum of matrix elements: 21.0


10. 转置操作(不改变源对象):transpose

INDArray indArray16 = Nd4j.create(new float[] {1, 2, 3, 4, 5, 6}, new int[] {2,3});

disp("Before transposition", indArray16);
disp("Transpose operation", indArray16.transpose());
disp("Original value after transpose operation (unchanged)", indArray16);


- 执行结果,可见2行3列转置后变成了3行2列,但是生成了新对象,而源对象未改变

Before transposition
Dimensions: 2
Shape: [2, 3]
Complete matrix:
[[ 1.0000, 2.0000, 3.0000],
[ 4.0000, 5.0000, 6.0000]]


Transpose operation
Dimensions: 2
Shape: [3, 2]
Complete matrix:
[[ 1.0000, 4.0000],
[ 2.0000, 5.0000],
[ 3.0000, 6.0000]]


Original value after transpose operation (unchanged)
Dimensions: 2
Shape: [2, 3]
Complete matrix:
[[ 1.0000, 2.0000, 3.0000],
[ 4.0000, 5.0000, 6.0000]]


11. 转置操作(源对象被改变):transposei

INDArray indArray16 = Nd4j.create(new float[] {1, 2, 3, 4, 5, 6}, new int[] {2,3});
disp("Before transposition", indArray16);
disp("Transpose operation", indArray16.transposei());
disp("Original value after transposei operation (changed)", indArray16);


- 执行结果

Before transposition
Dimensions: 2
Shape: [2, 3]
Complete matrix:
[[ 1.0000, 2.0000, 3.0000],
[ 4.0000, 5.0000, 6.0000]]


Transpose operation
Dimensions: 2
Shape: [3, 2]
Complete matrix:
[[ 1.0000, 4.0000],
[ 2.0000, 5.0000],
[ 3.0000, 6.0000]]


Original value after transposei operation (changed)
Dimensions: 2
Shape: [3, 2]
Complete matrix:
[[ 1.0000, 4.0000],
[ 2.0000, 5.0000],
[ 3.0000, 6.0000]]


12. 横向拼接:hstack,要求两个矩阵行数相等

// 2 rows and 3 columns
INDArray indArray17 = Nd4j.create(new float[] {1, 2, 3, 4, 5, 6}, new int[] {2,3});
// 2 rows and 1 column
INDArray indArray18 = Nd4j.create(new float[] {1, 2}, new int[] {2,1});
disp("source matrix", indArray17);
disp("Matrix on splicing", indArray18);
// A matrix of 2 rows and 3 columns, after one column is spliced horizontally, it becomes 2 rows and 4 columns
disp("Horizontal stitching (add one column to each row)", Nd4j.hstack(indArray17, indArray18));


- 执行结果如下图,可见是把indArray18 横着拼到indArray17 的右侧

![在这里插入图片描述](/img/bVcVvxr)

13. 纵向拼接:vstack,要求两个矩阵列数相等

// 2 rows and 3 columns
INDArray indArray19 = Nd4j.create(new float[] {1, 2, 3, 4, 5, 6}, new int[] {2,3});
// 1 row and 3 columns
INDArray indArray20 = Nd4j.create(new float[] {1, 2, 3}, new int[] {1,3});
disp("source matrix", indArray17);
disp("Matrix on splicing", indArray18);
// A matrix of 2 rows and 3 columns, stitched one row vertically, becomes 3 rows and 3 columns
disp("Vertical splicing (add one row)", Nd4j.vstack(indArray19, indArray20));


- 执行结果如下图,可见是把indArray20放在了indArray19的底部

![在这里插入图片描述](/img/bVcVvxs)

- 以上就是矩阵操作的常用API了,希望能给您一些参考,在深度学习的开发中更熟练的操作数据

### 你不孤单,欣宸原创一路相伴
1. [Java系列](https://xinchen.blog.csdn.net/article/details/105068742)
2. [Spring系列](https://xinchen.blog.csdn.net/article/details/105086498)
3. [Docker系列](https://xinchen.blog.csdn.net/article/details/105086732)
4. [kubernetes系列](https://xinchen.blog.csdn.net/article/details/105086794)
5. [数据库+中间件系列](https://xinchen.blog.csdn.net/article/details/105086850)
6. [DevOps系列](https://xinchen.blog.csdn.net/article/details/105086920)

### 欢迎关注公众号:程序员欣宸
> 微信搜索「程序员欣宸」,我是欣宸,期待与您一同畅游Java世界...

程序员欣宸
147 声望24 粉丝

热爱Java和Docker