This is a bilingual snapshot page saved by the user at 2024-6-27 7:04 for https://aibydoing.com/notebooks/appendix01-01-linear-algebra-with-python, provided with bilingual support by Immersive Translate. Learn how to save?

88. Python 线性代数基础#
88. Basics of Linear Algebra in Python

88.1. 介绍# 88.1. Introduction

线性代数是数学的一个分支,它研究向量空间和线性映射。线性代数广泛应用于科学和工程中,因为它可以用来解决很多问题。在这个教程中,我们将学习一些基本的线性代数知识,包括向量、矩阵、行列式、特征值和特征向量等。同时,我们将使用 Python 代码来实现这些常见的线性代数操作。
Linear algebra is a branch of mathematics that studies vector spaces and linear mappings. Linear algebra is widely used in science and engineering because it can be used to solve many problems. In this tutorial, we will learn some basic knowledge of linear algebra, including vectors, matrices, determinants, eigenvalues, and eigenvectors. At the same time, we will use Python code to implement these common linear algebra operations.

88.2. 知识点# 88.2. Knowledge Point #

  • 向量、标量和张量 Vectors, Scalars, and Tensors

  • 矩阵运算 Matrix operations

  • Python 的广播机制 Python's broadcasting mechanism

  • 单位矩阵 Identity matrix

  • 矩阵的转置和逆 Transpose and inverse of a matrix

  • 特征值分解和奇异值分解 Eigenvalue decomposition and singular value decomposition

  • 主成分分析法 Principal Component Analysis

88.3. 向量、标量、矩阵和张量# 88.3. Vectors, Scalars, Matrices, and Tensors

在数学中我们接触到的变量,一般分为以下几种: In mathematics, the variables we encounter are generally divided into the following types:

  • 标量:简单的说,标量其实就是一个单独的数字,如 x=5, x 即为一个标量,它没有任何物理意义。
    Scalar: Simply put, a scalar is actually a single number, such as x=5 or x , which has no physical meaning.

  • 向量:一列或者一行有序排列的数(多个标量组成一个向量)。如 X=[x1x2xn], X 即为一个向量。
    Vector: A sequence of numbers arranged in an ordered row or column (multiple scalars form a vector). For example, X=[x1x2xn] , X is a vector.

  • 矩阵:由多个向量组成的二维数组,如:X=[x11x12x13x21x22x23]X 即为一个 2×3 ( 行数 × 列数 ) 矩阵。其中,第 i 行,第 j 列的元素可以记作 Xi,j
    Matrix: A two-dimensional array composed of multiple vectors, such as: X=[x11x12x13x21x22x23] , X is a 2×3 (number of rows × number of columns) matrix. Among them, the element in the i row and j column can be denoted as Xi,j .

  • 张量:3 维或者以上的高维数组。我们可以把张量 A 中,坐标为 (i,j,k) 的元素,记作 Ai,j,k
    Tensor: A high-dimensional array of 3 dimensions or more. We can denote the element in tensor A with coordinates (i,j,k) as Ai,j,k .

综上,我们可以很容易地通过数组的维度来区分向量(1 维数组)、矩阵(2 维数组)和张量(高维数组)。
In summary, we can easily distinguish vectors (1-dimensional arrays), matrices (2-dimensional arrays), and tensors (high-dimensional arrays) by the dimensions of the arrays.

我们也可以使用同一个函数来初始化这些变量(只需要传入的维度不同即可),代码如下:
We can also use the same function to initialize these variables (just with different dimensions passed in), the code is as follows:

import numpy as np
# 向量
a = np.array([1, 2])
# 矩阵
b = np.array([[1, 2, 3], [4, 5, 6]])
#  在二维矩阵的基础上再加了一维, 形成张量
c = np.array([b, b])
print("向量 a 的大小:", a.shape)
print("矩阵 b 的大小:", b.shape)
print("张量 c 的大小:", c.shape)
向量 a 的大小: (2,)
矩阵 b 的大小: (2, 3)
张量 c 的大小: (2, 2, 3)

在这些变量类型中,使用最多的就是矩阵。我们拍摄的图片是矩阵、我们存在 Excel 中的数据是矩阵、我们从数据库展示出来的数据也是矩阵。并且我们学习过的每个机器学习算法都要直接或间接用到了矩阵。因此,矩阵的学习至关重要。
Among these variable types, the most frequently used is the matrix. The pictures we take are matrices, the data we store in Excel are matrices, and the data we display from databases are also matrices. Moreover, every machine learning algorithm we have studied uses matrices directly or indirectly. Therefore, learning about matrices is crucial.

88.4. 矩阵的运算法则# 88.4. Matrix Operations Rules

88.5. 矩阵与标量之间的运算# 88.5. Operations Between Matrices and Scalars

无论是加、减、乘、除的任何一种运算,标量和矩阵之间的运算都可以表示为:该标量和矩阵中的每个元素都进行了一次运算。代码如下:
Whether it is addition, subtraction, multiplication, or division, the operation between a scalar and a matrix can be expressed as: each element in the matrix undergoes the operation with the scalar. The code is as follows:

# 矩阵
a = np.array([[1, 2, 3], [4, 5, 6]])
print("a:\n", a)
print("a+2:\n", a+2)
print("a-2:\n", a-2)
print("a*2:\n", a*2)
print("a/2:\n", a/2)
a:
 [[1 2 3]
 [4 5 6]]
a+2:
 [[3 4 5]
 [6 7 8]]
a-2:
 [[-1  0  1]
 [ 2  3  4]]
a*2:
 [[ 2  4  6]
 [ 8 10 12]]
a/2:
 [[0.5 1.  1.5]
 [2.  2.5 3. ]]

88.6. 矩阵与矩阵之间的加法、减法和除法#
88.6. Addition, subtraction, and division between matrices

条件:只有两个大小相等的矩阵才能加减,即当一个矩阵大小为 m×n 时,另一个矩阵的大小也必须为 m×n
Condition: Only two matrices of equal size can be added or subtracted, that is, when one matrix is of size m×n , the other matrix must also be of size m×n .

运算方式:每个矩阵中对应位置的元素发生运算。拿加法举例,如下所示:
Operation method: The elements in corresponding positions in each matrix are operated on. Taking addition as an example, as shown below:

[a11a1nam1amn]+[b11b1nbm1bmn]=[a11+b11a1n+b1nam1+bm1amn+bmn]

代码测试:和常数加减一样,直接使用 +,-,/ 号即可:
Code testing: Just like adding and subtracting constants, you can directly use + , - , / numbers:

# 矩阵
a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([[1, 2, 3], [4, 5, 6]])
print("{}\n+\n{}\n=\n{}".format(a, b, a+b))
print("==============")
print("{}\n ÷ \n{}\n=\n{}".format(a, b, a/b))
[[1 2 3]
 [4 5 6]]
+
[[1 2 3]
 [4 5 6]]
=
[[ 2  4  6]
 [ 8 10 12]]
==============
[[1 2 3]
 [4 5 6]]
 ÷ 
[[1 2 3]
 [4 5 6]]
=
[[1. 1. 1.]
 [1. 1. 1.]]

88.7. 传统的矩阵乘积# 88.7. Traditional Matrix Multiplication

条件:只有在 A 的大小为 m×n , B 的大小为 n×f 时(即 A 的列数等于 B 的行数),A 矩阵才能和 B 矩阵相乘,且相乘的结果大小必定为 m×f
Condition: Only when the size of A is m×n , and the size of B is n×f (i.e., the number of columns of A is equal to the number of rows of B), can matrix A be multiplied by matrix B, and the size of the resulting product will definitely be m×f .

运算方式:假设 C=AB,则具体的操作定义如下:
Calculation method: Assuming C= A B , the specific operation is defined as follows:

Ci,j=kAi,kBk,j

简单的说,C 矩阵的第 i 行,第 j 列的值等于 A 矩阵第 i 行的所有值和 B 矩阵第 j 列的所有值的乘积之和。 举个例子如下:
簡單的說, C 矩陣的第 i 行,第 j 列的值等於 A 矩陣第 i 行的所有值和 B 矩陣第 j 列的所有值的乘積之和。 舉個例子如下:

C=AB=(123456)(142536)=(1×1+2×2+3×31×4+2×5+3×64×1+5×2+6×34×4+5×5+6×6)=(14323277)

从上面的例子中,我们可以看出,当 A 矩阵大小为 2×3B 矩阵大小为 3×2 时,所生成的乘积矩阵 C 的大小则为 2×2。且 C12 的值是 A 矩阵的第 1 行与 B 矩阵的第 2 列的元素的乘积和,即:1×4+2×5+3×6=32 。其他位置计算方法类似。
從上面的例子中,我們可以看出,當 A 矩陣大小為 2×3B 矩陣大小為 3×2 時,所生成的乘積矩陣 C 的大小則為 2×2 。且 C12 的值是 A 矩陣的第 1 行與 B 矩陣的第 2 列的元素的乘積和,即: 1×4+2×5+3×6=32 。其他位置計算方法類似。

矩阵乘法满足结合律和分配率,但是不满足交换律。如上,AB 的乘积矩阵大小为 2×2,但是 BA 的大小却变成了 3×3
矩陣乘法滿足結合律和分配率,但是不滿足交換律。如上, AB 的乘積矩陣大小為 2×2 ,但是 BA 的大小卻變成了 3×3

我们可以使用 dot 函数来实现矩阵乘法:
我們可以使用 dot 函數來實現矩陣乘法:

a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([[1, 4], [2, 5], [3, 6]])
# a 乘以 b
c = a.dot(b)
# b 乘以 a
d = b.dot(a)
print("ab的大小为:", c.shape)
print("值为:\n", c)
print("===========")
print("ba的大小为:", d.shape)
print("值为:\n", d)
ab的大小为: (2, 2)
值为:
 [[14 32]
 [32 77]]
===========
ba的大小为: (3, 3)
值为:
 [[17 22 27]
 [22 29 36]
 [27 36 45]]

88.8. 拓展运算:Hadamard 乘积#
88.8. 拓展運算:Hadamard 乘積 #

根据上面知识,可以知道传统的矩阵的乘积 不是 指矩阵中的相同位置的元素的乘积。不过,有时候,我们确实需要这种对应元素之间的乘积。因此,数学家又提出了一种叫做 Hadamard 的乘积方式来表示对应元素之间的乘积,记作 AB
根據上面知識,可以知道傳統的矩陣的乘積不是指矩陣中的相同位置的元素的乘積。不過,有時候,我們確實需要這種對應元素之間的乘積。因此,數學家又提出了一種叫做 Hadamard 的乘積方式來表示對應元素之間的乘積,記作 AB

当然,如果要使用这种乘积,那么必须保证 A 矩阵和 B 矩阵的大小相同,这样才能保证每个元素都有对应元素可以乘。
當然,如果要使用這種乘積,那麼必須保證 A 矩陣和 B 矩陣的大小相同,這樣才能保證每個元素都有對應元素可以乘。

我们可以使用 np.multiply() 来进行实现:
我們可以使用 np.multiply() 來進行實現:

a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([[1, 2, 1], [2, 2, 1]])
np.multiply(a, b)
array([[ 1,  4,  3],
       [ 8, 10,  6]])

根据结果可以看出,这种方式和矩阵加减除一致。但是请注意,一般在机器学习中所说的矩阵乘法都是传统的矩阵乘积。只有刻意标注了 Hadamard 矩阵乘积时,才使用这种乘积方式。
根據結果可以看出,這種方式和矩陣加減除一致。但是請注意,一般在機器學習中所說的矩陣乘法都是傳統的矩陣乘積。只有刻意標註了 Hadamard 矩陣乘積時,才使用這種乘積方式。

88.9. 拓展运算:广播机制# 88.9. 拓展運算:廣播機制 #

通过了上面的学习,我们可以知道,一个二维数组和一个一维数组是无法相加的。因为它们的位置无法一一对应。但是 NumPy 为我们提供了一种可以实现大小不同的数组相加的机制叫做广播机制。
通過了上面的學習,我們可以知道,一個二維數組和一個一維數組是無法相加的。因為它們的位置無法一一對應。但是 NumPy 為我們提供了一種可以實現大小不同的數組相加的機制叫做廣播機制。

当然值得注意的是,这种机制 不存在 于数学中,只是为了方便编程,才引入的这种机制。
當然值得注意的是,這種機制不存在於數學中,只是為了方便編程,才引入的這種機制。

简单的说,广播机制就是在两个大小不同的数组进行运算之前,将较小的数组的形状扩展成较大的数组形状,然后再进行运算。如下所示:
簡單的說,廣播機制就是在兩個大小不同的數組進行運算之前,將較小的數組的形狀擴展成較大的數組形狀,然後再進行運算。如下所示:

https://cdn.aibydoing.com/hands-on-ai/images/bd460f19c157886e5a89b411e86ff42b-0.jpg

如上所示: As shown above:

  • 当一个一维向量和一个数字进行运算时,这个数字会被复制多份,直到和该向量的长度相等时,才进行计算。
    當一個一維向量和一個數字進行運算時,這個數字會被複製多份,直到和該向量的長度相等時,才進行計算。

  • 当一个二维数组和一个一维向量进行运算时,如果这个向量的长度和二维数组的某个维度相等,那么就会对该向量进行赋值,直到大小和二维数组相同。再进行运算。
    當一個二維數組和一個一維向量進行運算時,如果這個向量的長度和二維數組的某個維度相等,那麼就會對該向量進行賦值,直到大小和二維數組相同。再進行運算。

在我们编写代码时,NumPy 会自动使用这种机制:
在我們編寫代碼時,NumPy 會自動使用這種機制:

a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([[1, 2, 3]])
a+b
array([[2, 4, 6],
       [5, 7, 9]])

值得注意的是,并不是所有大小不同的矩阵相加都可以进行广播。如果两个数组的尺寸在任何维度都不相同,且都不等于 1,那么就无法进行广播。NumPy 就会返回 operands could not be broadcast together with shapes 的错误。
It is worth noting that not all matrices of different sizes can be broadcasted. If the dimensions of the two arrays are not the same in any dimension and are not equal to 1, then broadcasting cannot be performed. NumPy will return an error of operands could not be broadcast together with shapes .

# 两个数组的尺寸在任何维度都不相同,且都不等于 1
a_ = np.array([[1, 2, 3], [4, 5, 6]])
b_ = np.array([[1, 2]])
a_+b_
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[7], line 4
      2 a_ = np.array([[1, 2, 3], [4, 5, 6]])
      3 b_ = np.array([[1, 2]])
----> 4 a_+b_

ValueError: operands could not be broadcast together with shapes (2,3) (1,2) 

88.10. 矩阵的性质# 88.10. 矩陣的性質 #

88.11. 矩阵的转置# 88.11. 矩陣的轉置 #

将矩阵的行列互换得到的新矩阵称为转置矩阵,记作 AT。例子如下:
The new matrix obtained by interchanging the rows and columns of a matrix is called the transpose matrix, denoted as AT . An example is as follows:

A=(A1,1A1,2A2,1A2,2A3,1A3,2)AT=(A1,1A2,1A3,1A1,2A2,2A3,2)

如上所示,矩阵的转置就是把原矩阵的第 1 行的向量,变成了 1 列的向量。把原矩阵的第 2 行的向量,变成了 2 列的向量,直到所有的行向量变为列向量为止。
如上所示,矩陣的轉置就是把原矩陣的第 1 行的向量,變成了 1 列的向量。把原矩陣的第 2 行的向量,變成了 2 列的向量,直到所有的行向量變為列向量為止。

当然,如果使用 NumPy 来实现它的话是非常简单的,我们只需要在变量后面加上 .T 即可。如下:
當然,如果使用 NumPy 來實現它的話是非常簡單的,我們只需要在變量後面加上 .T 即可。如下:

print("a:")
print(a)
print("a 的转置矩阵:")
print(a.T)
a:
[[1 2 3]
 [4 5 6]]
a 的转置矩阵:
[[1 4]
 [2 5]
 [3 6]]

88.12. 单位矩阵# 88.12. 單位矩陣 #

单位矩阵:n 阶单位矩阵,是一个 n×n 的方形矩阵(即行数和列数相同的矩阵),其主对角线元素为 1,其余元素为 0。单位矩阵一般用 In 表示。形式如下:
Identity matrix: An n-order identity matrix is a square matrix (i.e., a matrix with the same number of rows and columns) with 1s on its main diagonal and 0s elsewhere. The identity matrix is generally denoted by I. It is represented as follows:

I1=[1],I2=[1001],I3=[100010001].............In=[100010001]

可以直接用 np.identity() 来定义一个单位矩阵:
You can directly use np.identity() to define an identity matrix:

# 传入大小 n
np.identity(4)
array([[1., 0., 0., 0.],
       [0., 1., 0., 0.],
       [0., 0., 1., 0.],
       [0., 0., 0., 1.]])

88.13. 矩阵的逆# 88.13. Inverse of a Matrix

方阵 A 的逆矩阵记作 A1,且该矩阵满足如下条件:
The inverse matrix of matrix A is denoted as A1 , and this matrix satisfies the following conditions:

A1A=In

也就是说,如果一个矩阵和 A 的乘积(传统乘积)为一个单位矩阵,那么这个矩阵就是 A 的逆矩阵。
In other words, if the product (traditional product) of a matrix and A is an identity matrix, then this matrix is the inverse matrix of A .

关于 A 的逆矩阵在数学上的 具体求法,这里就不做阐述了。我们直接使用 NumPy 对其进行求取:
Regarding the specific method of finding the inverse matrix of A in mathematics, it will not be elaborated here. We will directly use NumPy to obtain it:

a = np.array([[1, 2], [3, 4]])
# 通过 np.linalg.inv() 求取逆矩阵
print(np.linalg.inv(a))
print("=================")
# 矩阵对象可以通过 ‘.I’ 属性,更方便的求逆
A = np.matrix(a)
print(A.I)
[[-2.   1. ]
 [ 1.5 -0.5]]
=================
[[-2.   1. ]
 [ 1.5 -0.5]]

如上,我们提供了两种逆矩阵的求取方式。 As mentioned above, we have provided two methods for finding the inverse matrix.

我们一般把上面这种可逆的矩阵称之为非奇异矩阵,把那些不可逆的矩阵称之为奇异矩阵。而区分矩阵是否可逆的方法有很多中,其中用的最多的就是判断该矩阵的行列式。
We generally refer to the reversible matrix mentioned above as a non-singular matrix, and those irreversible matrices as singular matrices. There are many methods to distinguish whether a matrix is reversible, among which the most commonly used is to determine the determinant of the matrix.

  • 如果该矩阵为一个方阵且方阵的行列式不等于 0 ,则表示该矩阵可逆。
    If the matrix is a square matrix and its determinant is not equal to 0, it means the matrix is invertible.

  • 否则,不可逆(即为奇异矩阵)。 Otherwise, it is irreversible (i.e., a singular matrix).

88.14. 矩阵的行列式# 88.14. Determinant of a Matrix

行列式是方阵(即行数和列数相等的矩阵)才有的一种特征,记作 det(A),也记作 |A|。它的计算公式较为复杂,是很多同学上学时的噩梦。当然作为一个程序员来说,我们不需要对该行列式的具体计算步骤了然于心,我们只需要知道如何求它用它即可。
The determinant is a characteristic of a square matrix (i.e., a matrix with an equal number of rows and columns), denoted as det(A) or |A| . Its calculation formula is quite complex and is a nightmare for many students during their school years. Of course, as a programmer, we do not need to be thoroughly familiar with the specific calculation steps of the determinant; we only need to know how to find and use it.

我们可以使用 np.linalg.det() 对行列式进行求取:
We can use np.linalg.det() to calculate the determinant:

a = np.array([[1, 2], [3, 4]])
b = np.array([[1, 2], [2, 4]])
print("a的行列式为", np.linalg.det(a))
print("b的行列式为", np.linalg.det(b))
a的行列式为 -2.0000000000000004
b的行列式为 0.0

从上面的结果可知,a 矩阵的行列式不为 0 ,为可逆矩阵。而 b 矩阵的行列式为 0 ,为不可逆矩阵。你可以尝试用 np.linalg.inv() 方法求取一下 b 的逆矩阵,观察程序是否报错。
From the above results, it can be seen that the determinant of matrix a is not 0, making it an invertible matrix. However, the determinant of matrix b is 0, making it a non-invertible matrix. You can try using the np.linalg.inv() method to find the inverse of b and observe whether the program reports an error.

88.15. 范数# 88.15. Norms #

在机器学习中我们经常需要使用到范数来衡量向量的大小。范数的形式有很多种,而机器学习中经常使用的是 L2 范数,又称做欧几里得范数。该范数的计算公式如下:
In machine learning, we often need to use norms to measure the size of vectors. There are many forms of norms, and the one frequently used in machine learning is the L2 norm, also known as the Euclidean norm. The calculation formula for this norm is as follows:

||x||2=i=1Nxi2

根据公式,我们不难发现向量的 L2 范数其实就是绝对值的平方和再开方。
According to the formula, it is not difficult to find that the L2 norm of a vector is actually the square root of the sum of the squares of its absolute values.

L2 范数除来被应用于传统机器学习中,如岭回归、贝叶斯推断等,还被广泛应用于深度学习中。如利用 L2 范数进行的正则化,可以很好的缓解神经网络权重的衰减,提高模型的泛化能力。
The L2 norm is not only applied in traditional machine learning, such as ridge regression and Bayesian inference, but also widely used in deep learning. For example, regularization using the L2 norm can effectively alleviate the decay of neural network weights and improve the generalization ability of the model.

我们可以通过 np.linalg.norm() 对 L2 范数进行计算:
We can calculate the L2 norm through np.linalg.norm() :

print("按列向量计算 a 的范数", np.linalg.norm(a, axis=0))  # 按列向量计算范数
print("按行向量计算 a 的范数", np.linalg.norm(a, axis=1))  # 按行向量计算范数
print("计算矩阵 a 的范数", np.linalg.norm(a))  # 按列向量计算范数
按列向量计算 a 的范数 [3.16227766 4.47213595]
按行向量计算 a 的范数 [2.23606798 5.        ]
计算矩阵 a 的范数 5.477225575051661

88.16. 矩阵的迹# 88.16. Trace of the Matrix

矩阵的迹即为矩阵的对角元素(即对角线上的所有元素)之和,记作 Tr(A)。计算公式如下:
The trace of a matrix is the sum of its diagonal elements (i.e., all the elements on the diagonal), denoted as Tr(A) . The formula is as follows:

Tr(A)=A11+A22+A33.....=iAii

我们可以使用 np.trace(),快速的求取一个矩阵的迹,如下:
We can use np.trace() to quickly find the trace of a matrix, as follows:

print("a_00:", a[0][0])
print("a_11:", a[1][1])
print("Tr(a):", np.trace(a))
a_00: 1
a_11: 4
Tr(a): 5

88.17. 特殊的矩阵# 88.17. Special Matrices

对角矩阵:只在主对角线上含有非零元素,其他位置都为零的矩阵。其实这和上面的单位矩阵很像,只是单位矩阵的对角线上必须为 1 ,对角矩阵的对角线上可以为非零的任意值。因此对角矩阵 diag(x) 的形式如下:
Diagonal matrix: A matrix that contains non-zero elements only on the main diagonal, with all other positions being zero. In fact, this is very similar to the identity matrix, except that the diagonal of the identity matrix must be 1, while the diagonal of a diagonal matrix can be any non-zero value. Therefore, the form of the diagonal matrix diag(x) is as follows:

diag(x)=[x1000x2000xn]

可以直接用 np.diag() 来定义一个对角矩阵:
You can directly use np.diag() to define a diagonal matrix:

# 函数传入的是对角线上的值
x = np.diag((1, 2, 3, 4))
x
array([[1, 0, 0, 0],
       [0, 2, 0, 0],
       [0, 0, 3, 0],
       [0, 0, 0, 4]])

有趣的是,该函数除了创造对角矩阵,还能从对角矩阵中提取出对角线上的值:
Interestingly, this function not only creates a diagonal matrix but also extracts the values on the diagonal from a diagonal matrix:

np.diag(x)
array([1, 2, 3, 4])

对称矩阵: 如果矩阵 A 的转置和矩阵 A 相同,则矩阵 A 就是对称矩阵。换句话说,若矩阵 A 满足 Aij=Aji,其中 ij 为任意值,则 A 为对称矩阵。
Symmetric Matrix: If the transpose of matrix A is the same as matrix A , then matrix A is a symmetric matrix. In other words, if matrix A satisfies Aij=Aji , where i and j are arbitrary values, then A is a symmetric matrix.

因为转置相同,所以矩阵 A 的行数必须等于列数,即矩阵必定是方阵。因为对称,所以上三角(对角线上面的三角形内容)和下三角的内容必定对称。如下所示:
Because the transpose is the same, the number of rows of the matrix A must be equal to the number of columns, that is, the matrix must be a square matrix. Because of symmetry, the contents of the upper triangle (the triangular content above the diagonal) and the lower triangle must be symmetrical. As shown below:

https://cdn.aibydoing.com/hands-on-ai/images/b268a1a25089cad4dc781524b699fe45-0.jpg

从上面的实例可以看出,该矩阵的沿着对角线对称,矩阵上三角的内容等于矩阵下三角的内容。

不过,NumPy 中没有现成的库来直接创建对称矩阵,对称矩阵的创建步骤如下:

首先让我们初始化一个 5×5 的矩阵:

# 随机初始化 25 个数,然后将这一组数转换为 5*5 的矩阵
x = np.random.randn(25).reshape(5, 5)
x
array([[-1.76147734, -0.86482382,  0.62757387, -1.30881442, -2.1407301 ],
       [-1.95812775, -0.02321958,  0.6240782 , -0.48150296,  0.90741739],
       [-0.03717522, -1.26331227,  1.10608778,  0.39242673, -1.16064422],
       [ 1.1341177 , -1.81348565,  0.92502167,  1.95435312, -0.05584964],
       [-1.54326738,  1.16051111,  1.1648892 , -2.28413737,  0.50776626]])

然后利用 triu()函数取出矩阵 x 的上三角矩阵:

cov_up = np.triu(x)
cov_up
array([[-1.76147734, -0.86482382,  0.62757387, -1.30881442, -2.1407301 ],
       [ 0.        , -0.02321958,  0.6240782 , -0.48150296,  0.90741739],
       [ 0.        ,  0.        ,  1.10608778,  0.39242673, -1.16064422],
       [ 0.        ,  0.        ,  0.        ,  1.95435312, -0.05584964],
       [ 0.        ,  0.        ,  0.        ,  0.        ,  0.50776626]])

接下来,我们我们需要获得将上三角矩阵转置,即得到与之对称的下三角矩阵,如下:

cov_down = cov_up.T
cov_down
array([[-1.76147734,  0.        ,  0.        ,  0.        ,  0.        ],
       [-0.86482382, -0.02321958,  0.        ,  0.        ,  0.        ],
       [ 0.62757387,  0.6240782 ,  1.10608778,  0.        ,  0.        ],
       [-1.30881442, -0.48150296,  0.39242673,  1.95435312,  0.        ],
       [-2.1407301 ,  0.90741739, -1.16064422, -0.05584964,  0.50776626]])

然后,我们将上三角矩阵和下三角矩阵相加即可:

cov_up_down = cov_up+cov_down
cov_up_down
array([[-3.52295468, -0.86482382,  0.62757387, -1.30881442, -2.1407301 ],
       [-0.86482382, -0.04643916,  0.6240782 , -0.48150296,  0.90741739],
       [ 0.62757387,  0.6240782 ,  2.21217556,  0.39242673, -1.16064422],
       [-1.30881442, -0.48150296,  0.39242673,  3.90870625, -0.05584964],
       [-2.1407301 ,  0.90741739, -1.16064422, -0.05584964,  1.01553252]])

细心的你可能已经发现,尽管这样可以得到一个对称矩阵,但是我们将对角线的值加了两次(上三角矩阵和下三角矩阵中的对角线的值都存在)。因此,最后,我们需要将得到的 cov_up_down 减去一个对角线的值。

首先,让我们来初始化只有对角线元素有值的对角矩阵:

# 获得对角线的值
d = np.diag(x)
# 获得对角矩阵
dia = np.diag(d)
dia
array([[-1.76147734,  0.        ,  0.        ,  0.        ,  0.        ],
       [ 0.        , -0.02321958,  0.        ,  0.        ,  0.        ],
       [ 0.        ,  0.        ,  1.10608778,  0.        ,  0.        ],
       [ 0.        ,  0.        ,  0.        ,  1.95435312,  0.        ],
       [ 0.        ,  0.        ,  0.        ,  0.        ,  0.50776626]])

最后减去一个对角矩阵,得到最后的对称矩阵:

x = cov_up_down-dia
x
array([[-1.76147734, -0.86482382,  0.62757387, -1.30881442, -2.1407301 ],
       [-0.86482382, -0.02321958,  0.6240782 , -0.48150296,  0.90741739],
       [ 0.62757387,  0.6240782 ,  1.10608778,  0.39242673, -1.16064422],
       [-1.30881442, -0.48150296,  0.39242673,  1.95435312, -0.05584964],
       [-2.1407301 ,  0.90741739, -1.16064422, -0.05584964,  0.50776626]])

我们可以利用 矩阵的转置等于矩阵本身来测试一下 x 是否为对称矩阵:

x == x.T
array([[ True,  True,  True,  True,  True],
       [ True,  True,  True,  True,  True],
       [ True,  True,  True,  True,  True],
       [ True,  True,  True,  True,  True],
       [ True,  True,  True,  True,  True]])

正交矩阵:当方阵 A 满足 ATA=AAT=I 时,A 被叫做正交矩阵。

根据逆矩阵的定义可知,若矩阵可逆,则有 A1A=I。因此结合上面两个式子,若矩阵 A 既为逆矩阵又为正交矩阵,则有:

A1=AT

88.18. 矩阵的分解#

88.19. 特征值与特征分解#

还记得我们高中时学过的力的合成吗? 力 j 和 力 i可 以通过叠加得到力 A,记作 i,j,如下图一所示:

https://cdn.aibydoing.com/hands-on-ai/images/3afce0e479adeff121dc03dbed7328ea-0.jpg

从图 1 可以看到,当以 i,j 为坐标轴时,A 可以被表示为 1i+1j。换句话说,在 i,j 的坐标空间中,A 的坐标为 (1i,1j)

但是,显然利用 ij 来表示的合成力 A 并不能很好的展现物体的作用效果(即该力作用下的物体会向上走多少,向右走多少)。因此,我们常常会再做一次变换,将力分解到横向和竖直两个方向,即将力 A 转换到图二所示的 mn 坐标空间中,那么此时 A 的坐标就不再是 (1i,1j) 了,而是 (λ1m,λ2n)

而特征分解的原理和力的分解类似,也就是将一个方阵 A 转换为新的空间下的矩阵的过程。其中新空间下的坐标轴向量被称之为特征向量(记作 v),而矩阵 A 与特征向量的倍数称之为特征值,记作 λ (即上面的 λ1,λ2... 的集合)。

我们可以用