线性代数组织(III)确定特征值和特征向量
接线性代数整理(二)
行列式
行列式是方阵的一个属性
矩阵可以表示一组向量,方阵表示n个n维向量,用一个数字表示这些向量组的不同?
比方说在二维平面中,这里有三组二维向量,每组都有两个向量,那么每组向量的面积就可以表示它们的不同。当然这里说面积是针对二维平面来说的,在三维空间中,就是体积;在更高维度中,可能就是一个体,但这个体比较抽象
行列式描述的就是n个n维向量所组成的这样一个体的属性。我们从二维空间入手,来看一看行列式是怎么计算的
像这样的两个向量所组成的行列式,我们记作
,这里我们可以看到,这两个向量,在行列式中,我们是按行来排列的。但其实按行排列还是按列排列都是可以的,是无所谓的。对于行列式,也可以表示成
,而求它的值,实际上就是求上图中平行四边形的面积。
通过做绿色的辅助线,可得这个平行四边形的面积=(a + c)(b + d) - 2bc - cd - ab = ad - bc
则
对于二阶方阵来说,它的行列式的值为主对角线上的乘积减去非主对角线上的乘积。
反过来,则
,由此,我们可以看出
行列式表示向量组在空间中形成的有向体积
对于二维空间,我们往往是先从x轴看向y轴,则对于上面的u和v两个向量来说,从u到v的逆时针方向上,我们就认为它的行列式就是正的。而从u到v的顺时针方向上,我们就认为它的行列式是负的。
但是在三维或以上的空间中,体积的方向将变得极其复杂。简单说,在行列式中,向量排列的顺序是有意义的。在n阶行列式中,任意交换两行,则行列式的值取反。
行列式的基本性质
- 单位矩阵的行列式等于1,即det I = 1
- 交换行列式的两行,则行列式的值取反。
- 方阵的某一行乘以一个数k,则其对应的行列式也缩放了k倍,即
,比如
(a,b)这个向量扩展了两倍,则这个平行四边形的面积也扩展了两倍。这里需要注意的是,是其中的某一行,而不是所有行,这和矩阵的数量乘法是不一样的。
(其中A为方阵);而正确的写法为
,,其中n是指A为n阶方阵。
- 方阵中的某一行加上一行数,则有:
,它其实表示的是一个向量相加,当然我们也可以直接代进公式,左边 = (a + a')d - (b + b')c = ad + a'd - bc - b'c。右边= ad - bc + a'd - b'c,说明左边=右边
这里的第4和第3条是行列式的加法和数量乘法,这是非常有意义的两种基本运算。
行列式和矩阵的逆
性质一:如果行列式的两行相同,则行列式的值为0。
证明: 假设方阵A交换两行后为A'
det(A) = -det(A'),因为两行相同,所以A = A'
det(A) = -det(A) 则det(A) = 0,得证
从直观上考虑:二维空间中,两个向量共线,面积为0;在三维空间中,两个向量共线,形成一个平面,体积为0;n维空间中,两个向量共线,则退化成一个n-1维的体,它的n维的体积为0。
性质二:如果行列式的一行是另一行的k倍,则行列式的值为0.
证明:
这一条跟上面一条在直观上理解是一样的,因为它们共线。
性质三:如果行列式有一行为0,则行列式的值为0。
证明:
在直观上理解,就是一个n维体中,有一个零向量,则这个n维体退化成了n-1维体,它的n维的体积为0
性质四:如果行列式的一行是其他行的线性组合,则行列式的值为0。
证明:
这是根据行列式的加法以及性质二来证明的。从n维空间的角度考虑,如果有两行线性相关,则无法构成n维空间的一组基,就算其他行都线性无关,也退化成n-1维空间,它的n维空间的体积为0.
行列式形成一个向量组,如果这组向量线性相关,则行列式的值为0,det(A)=0
矩阵不可逆
如果这组向量线性无关,则行列式的值不为0,det(A)≠0
矩阵可逆
现在对于方阵A的等价命题又可以增加一条
- 对于方阵A,矩阵A可逆,A是非奇异矩阵
- 线性系统Ax=0(齐次线性方程组)只有唯一解,x=0
- 矩阵的行最简形式rref(A)=I
- A可以表示成一系列初等矩阵的乘积
- Ax=b只有唯一解
- 方阵A的列向量线性无关
- 方阵A的列向量可以生成n维空间
- 方阵A的列向量是n维空间的基
- 方阵A为满秩矩阵(秩=n)
- 方阵A的行秩为n
- 方阵A的列秩为n
- 方阵A的行空间为
- 方阵A的列空间为
- 方阵A的零空间为{O},维度为0
- det(A)≠0
计算行列式的算法
如果一个行列式的一行加(减)另一行的k倍,行列式的值不变。
证明:
这条性质是计算行列式的值的基础。
一个方阵行列式的值
- 等于其进行高斯消元法后的结果
上三角矩阵U
- 等于其进行高斯-约旦消元法后的结果
对角矩阵D(只有主对角线上的元素为非零元素,其他位置上的元素都为0)
但是这个高斯-约旦消元法跟之前讲线性系统时候的有所不同,它不能进行归一化操作。因为一旦进行归一化操作,行列式的值就发生了变化,这跟矩阵的性质是不一样的,归一化的本质就是某一行乘以了某个常数k,行列式的值就扩大了k倍。并且进行行置换和列置换需要改变行列式的正负号,因为任意交换两行,行列式的值取反。如果消元结果有零行,行列式的值为0。
对角矩阵的行列式
上三角矩阵的行列式
其实上三角矩阵的行列式跟对角矩阵的行列式的值是相同的,也是
,这是因为在进行约旦消元法的过程中,将主元列上面的数减去主元值乘以一个系数,全部化成0,也就变成了对角矩阵,而主元列的主元值都不变。
下三角矩阵的行列式
跟上三角矩阵的求法类似,进行高斯消元法就好,最后依然是一个对角矩阵,而主元列的主元值不变,依然为
所以上面的计算行列式的值不需要进行约旦消元法,只需要进行高斯消元法即可。
简单用2阶行列式进行验证
新增一个接口Formula
public interface Formula<T extends Number> {
/**
* 求行列式的值
* @return
*/
T result(Addr<T> addr);
}
行列式实现类
@ToString
public class Determinant<T extends Number> implements Formula<T> {
//原始方阵
private Ranks<T> source;
//高斯消元法后的方阵
private Ranks<T> matrix;
@SuppressWarnings("unchecked")
public Determinant(Ranks<T> matrix) throws CloneNotSupportedException {
if (matrix.rowNum() != matrix.colNum()) {
throw new IllegalArgumentException("矩阵必须为方阵");
}
this.source = matrix;
this.matrix = ((Matrix) matrix).clone();
}
@Override
public T result(Addr<T> addr) {
T res = addr.one();
int times = forword(addr);
for (int i = 0; i < matrix.rowNum(); i++) {
res = addr.mul(res,matrix.get(new int[]{i,i}));
}
//交换次数为奇数,结果取负
if ((times & 1) == 1) {
return addr.neg(res);
}
return res;
}
/**
* 高斯消元,此处不可做归一化处理
* @param addr
* @return
*/
@SuppressWarnings("unchecked")
private int forword(Addr<T> addr) {
int i = 0;
int k = 0;
//交换位置的次数
int times = 0;
while (i < matrix.rowNum() && k < matrix.colNum()) {
int maxRow = maxRow(i, k, matrix.rowNum(), addr);
T[] temp = (T[]) new Number[matrix.colNum()];
if (maxRow != i) {
times++;
}
//每一行无论是否有主元,都与主元最大值所在行进行交换
for (int j = 0; j < matrix.colNum(); j++) {
temp[j] = matrix.get(new int[]{i, j});
matrix.set(new int[]{i, j}, matrix.get(new int[]{maxRow, j}));
matrix.set(new int[]{maxRow, j}, temp[j]);
}
if (addr.equals(matrix.get(new int[]{i,k}),addr.zero())) {
k++;
}else {
//将主元所在行以下的行的所有非主元数据全部变成0
for (int m = i + 1; m < matrix.rowNum(); m++) {
T u1 = matrix.get(new int[]{m, k});
for (int l = 0; l < matrix.colNum(); l++) {
matrix.set(new int[]{m, l}, addr.sub(matrix.get(new int[]{m, l}),
addr.mul(matrix.get(new int[]{i, l}),
addr.div(u1,matrix.get(new int[]{i,k})))));
}
}
i++;
}
}
return times;
}
/**
* 获取主元最大值所在的行
* @param addr
* @return
*/
private int maxRow(int indexI,int indexJ,int n,Addr<T> addr) {
T best = matrix.get(new int[]{indexI,indexJ});
int ret = indexI;
for (int i = indexI + 1; i < n; i++) {
if (addr.compair(matrix.get(new int[]{i,indexJ}),best) == 1) {
best = matrix.get(new int[]{i,indexJ});
ret = i;
}
}
return ret;
}
public static void main(String[] args) throws CloneNotSupportedException {
Addr<Double> addr = new Addr<Double>() {
@Override
public Double zero() {
return 0.0;
}
@Override
public Double one() {
return 1.0;
}
@Override
public Double add(Double lhs, Double rhs) {
return lhs + rhs;
}
@Override
public Double sub(Double lhs, Double rhs) {
return lhs - rhs;
}
@Override
public Double mul(Double k, Double hs) {
return k * hs;
}
@Override
public Double square(Double hs) {
return hs * hs;
}
@Override
public double prescription(Double hs) {
return Math.sqrt(hs);
}
@Override
public double div(Double hs, double nhs) {
return hs / nhs;
}
@Override
public Double div(Double hs, Double nhs) {
return hs / nhs;
}
@Override
public double acos(double hs) {
return Math.acos(hs);
}
@Override
public double toDegree(double hs) {
return Math.toDegrees(hs);
}
@Override
public int compair(Double lhs, Double rhs) {
if (lhs - rhs > 0) {
return 1;
}else if (lhs - rhs < 0) {
return -1;
}else {
return 0;
}
}
@Override
public boolean equals(Double lhs, Double rhs) {
double dis = 1e-8;
if (Math.abs(lhs - rhs) < dis) {
return true;
}
return false;
}
@Override
public Double neg(Double hs) {
return -hs;
}
};
Ranks<Double> matrix = new Matrix<>(new Double[][]{{7.0,3.0},{2.0,5.0}});
Formula<Double> determinant = new Determinant<>(matrix);
System.out.println(determinant.result(addr));
System.out.println(determinant);
}
}
运行结果
29.000000000000004
Determinant(source=Matrix{values=[[7.0, 3.0],[2.0, 5.0]]}, matrix=Matrix{values=[[7.0, 3.0],[0.0, 4.142857142857143]]})
Python代码
from ._global import is_zero
from .Matrix import Matrix
class Determinant:
def __init__(self, matrix):
assert matrix.row_num() == matrix.col_num(), "矩阵必须为方阵"
self._source = matrix
self._matrix = [matrix.row_vector(i) for i in range(matrix.row_num())]
def result(self):
# 求行列式的值
res = 1
times = self._forword()
for i in range(len(self._matrix)):
res *= self._matrix[i][i]
if times % 2 == 1:
return -res
return res
def _forword(self):
# 高斯消元,此处不可做归一化处理
i, k, times = 0, 0, 0
while i < len(self._matrix) and k < len(self._matrix[0]):
# 看matrix[i][k]位置是否可以为主元
max_row = self._max_row(i, k, len(self._matrix))
if max_row != i:
times += 1
self._matrix[i], self._matrix[max_row] = self._matrix[max_row], self._matrix[i]
if is_zero(self._matrix[i][k]):
k += 1
else:
for j in range(i + 1, len(self._matrix)):
self._matrix[j] = self._matrix[j] - self._matrix[j][k] * (self._matrix[i] / self._matrix[i][k])
i += 1
return times
def _max_row(self, index_i, index_j, n):
# 主元最大值所在的行
best, ret = self._matrix[index_i][index_j], index_i
for i in range(index_i + 1, n):
if self._matrix[i][index_j] > best:
best, ret = self._matrix[i][index_j], i
return ret
def __repr__(self):
return "Determinant({},{})".format(self._source, Matrix(self._matrix))
__str__ = __repr__
from playLA.Determinant import Determinant
from playLA.Matrix import Matrix
if __name__ == "__main__":
matrix = Matrix([[7, 3], [2, 5]])
determinant = Determinant(matrix)
print(determinant.result())
print(determinant)
运行结果
29.000000000000004
Determinant(Matrix([[7, 3], [2, 5]]),Matrix([[7, 3], [0.0, 4.142857142857143]]))
初等矩阵与行列式
之前我们讲的性质都可以从几何方面来进行理解,但是对于这个性质对于几何来讲就没什么用了,因为对于两个空间体体积的乘积,在几何上的意义就不那么明确了。所以我们要从纯代数的角度出发,来进行证明。
首先,如果A或者B中的某一行和其他行线性相关,则
,假设A中某一行和其他行线性相关,则
的结果矩阵中依然会保持线性相关性。
,所以在这种情况下,等式的两边成立。
现在我们来看A和B中的所有行都线性无关,从方阵的等价命题中
- 对于方阵A,矩阵A可逆,A是非奇异矩阵
- 线性系统Ax=0(齐次线性方程组)只有唯一解,x=0
- 矩阵的行最简形式rref(A)=I
- A可以表示成一系列初等矩阵的乘积
- Ax=b只有唯一解
- 方阵A的列向量线性无关
- 方阵A的列向量可以生成n维空间
- 方阵A的列向量是n维空间的基
- 方阵A为满秩矩阵(秩=n)
- 方阵A的行秩为n
- 方阵A的列秩为n
- 方阵A的行空间为
- 方阵A的列空间为
- 方阵A的零空间为{O},维度为0
- det(A)≠0
我们可以看到第4条,这表示A或者B都能表示为一系列初等矩阵的乘积。而初等矩阵是对单位矩阵进行初等变换(行操作),则我们把A拆解成一系列初等矩阵
,进而我们需要研究一下初等矩阵的行列式
初等矩阵的变换一共有三种形式
- 如果E是单位矩阵的某一行乘以k,很明显 det(E) = k
- 如果E是单位矩阵的某两行交换位置,很明显 det(E) = -1
- 如果E是单位矩阵的某行加(减)另一行的k倍 det(E) = 1
现在我们需要先证明这个命题
现在我们依然分三种情况来证明
- 如果E是单位矩阵的某一行乘以k,方阵EB是B中的某一行乘以k,则
,而等式右边
,左右相等,在该种情况下得证。
- 如果E是单位矩阵的某两行交换位置,方阵EB是B中某两行交换位置,
,等式右边
,左右相等,在该种情况下得证。
- 如果E是单位矩阵的某行加(减)另一行的k倍,方阵EB是B中的某行加(减)另一行的k倍,
,等式右边
,左右相等,在该种情况下得证。
从而,下面的式子就可以进行转化
将A拆成一系列的初等矩阵的乘积,就有
而A本身的行列式为
最终得到
得证
我们将B替换成A的逆,则有
这里可以计算A的逆的行列式的值,而A的行列式的值由于在分母的位置,所以它不能为0,换句话说,如果A的行列式的值为0,A的逆的行列式的值不存在,进而A的逆不存在。这进而说明了方阵A的等价命题中A若存在逆,det(A)≠0。
矩阵的LDU分解,PLU分解,PLUP分解
- LDU分解
之前我们讲过矩阵的LU分解,将一个矩阵分解成了一个单位下三角矩阵L和一个上三角矩阵U
在不做归一化处理的高斯消元法中,将矩阵A化成一个上三角矩阵U,同时产生一个初等矩阵的逆矩阵L。现在如果我们想把U也化成一个单位上三角矩阵的话,L不变,等于我们进行高斯消元法的时候进行归一化处理,此时也相当于进行了一系列的初等矩阵的变换,我们同样要获取这些初等矩阵的逆矩阵D
我们可以看到D是一个对角矩阵。此时
- PLU分解
我们再来看一个矩阵的高斯消元的过程
此时它的这两步操作的初等矩阵的逆矩阵L为
,当我们要对第二行的主元进行消元的时候,我们发现,第二行第二列的元素为0,如果按照正常的高斯消元法,我们会替换第二行和第三行。
但同时会产生一个交换操作,之前的初等矩阵的逆矩阵L
也要交换位置,此时这个矩阵将不再是单位下三角矩阵。在不动L的情况下,我们需要新产生一个初等矩阵的逆矩阵
,我们称这个矩阵为置换矩阵P,虽然有了矩阵P,但由于我们还是交换了位置,矩阵L也就变成了
最终得到
- PLUP分解
PLU分解并不能解决所有的矩阵的问题,比如
我们在进行高斯消元的过程中,第1列1下面两个0,这个没有问题,但是在对第二列进行消元的过程中,第二行和第三行的值都是0,即便进行行交换也没有用。则PLU分解的方法就失效了。为了继续高斯消元,需要交换矩阵的两列。但是初等矩阵中没有交换矩阵两列的初等变换,只能交换矩阵的两行。例如
要交换矩阵的两列,需要右乘以置换矩阵,比如
所以A需要去右乘一个置换矩阵,完成列交换,而这个置换矩阵我们称之为P',再根据之前的PLU分解,最后可得
这里的A可以是任意矩阵。
行式就是列式
对于一个方阵,无论它其中的向量是行排列还是列排列,它们的行列式的值相等。
即为
之前我们讲解了任意A可以分解成PLUP'四个矩阵,其中P是一个行变换矩阵,P'是一个列变换矩阵,则
在这里,L、U的行列式的值和它们转置的行列式的值肯定是相等的,因为L是下三角矩阵,U是上三角矩阵,它们的行列式都等于对角矩阵的行列式的值,而L转置后是一个上三角矩阵,U转置后是一个下三角矩阵,它们的行列式同样等于对角矩阵的行列式的值。
P和P'是单位矩阵经过几次交换位置的初等变换的初等矩阵的结果,所以我们可以先证明这个命题
如果E表示单位矩阵两行交换位置det(E) = -1,而一个单位矩阵的两行交换了位置之后再进行转置,转置的结果还是两行交换了位置,它的行列式的值同样为-1,得证。
由于P和P'和它们的转置后的行交换的次数是一样的,所以P和P'的行列式的值和它们转置后的行列式的值是相等的,
得证。
我们之前讲的所有性质,都是基于行的。换成列一样存在。
- 交换行列式的两列,则行列式的值取反。
- 方阵的某一列乘以一个数k,则其对应的行列式也缩放了k倍,即
- 方阵中的某一列加上一列数,则有:
- 如果行列式的两列相同,则行列式的值为0。
- 如果行列式的一列是另一列的k倍,则行列式的值为0。
- 如果行列式的一列是其他列的线形组合,则行列式的值为0。
- 如果一个方阵加(减)另一列的k倍,行列式的值不变。
特征值和特征向量
特征值和特征向量也是方阵的一个属性,描述的是方阵的"特征",把方阵当作变换的时候的一个"特征"
我们之前已经知道矩阵看作变换,可以把空间中的一个向量(一个点)转换成另外一个向量(一个点)
图中就是把(1,4)这个蓝色的向量转换到了(-4,5)这个绿色的向量。当然它也是一个基变换,从(4,1)、(-2,1)组成的一组基到标准基的变换。
我们再来看一组转换
在这组转换里面,转换后的向量和转换前的向量在方向上并没有发生改变,只不过变成了原来的向量的某一个常数倍,满足
这里
称为A的特征值(eigenvalue)
称为A对应于
的特征向量(eigenvector)
求解特征值和特征向量
这里需要注意的是,零向量肯定满足。是平凡解。既然是A的特征,零向量自然无法反映A的特征。如果是零向量就跟A无关了,A可以任意取。所以,特征向量不考虑零向量。但
=0并不平凡,此时等式就变成了
,由于
不能为零向量,该方程变成了一个齐次线性方程组。
根据方阵的等价命题中
- 对于方阵A,矩阵A可逆,A是非奇异矩阵
- 线性系统Ax=0(齐次线性方程组)只有唯一解,x=0
- 矩阵的行最简形式rref(A)=I
- A可以表示成一系列初等矩阵的乘积
- Ax=b只有唯一解
- 方阵A的列向量线性无关
- 方阵A的列向量可以生成n维空间
- 方阵A的列向量是n维空间的基
- 方阵A为满秩矩阵(秩=n)
- 方阵A的行秩为n
- 方阵A的列秩为n
- 方阵A的行空间为
- 方阵A的列空间为
- 方阵A的零空间为{O},维度为0
- det(A)≠0
的第2条,我们知道,A可逆的话,
只能为零向量,所以A一定不可逆。
所以这里特征值可以为0
我们再对这个等式进行一系列的变形(由于矩阵不能与常数相减,所以将常数乘以一个单位矩阵,等式两边依然成立)
我们其实是希望
这个齐次线性方程组有非零解,根据方阵的等价命题中的2和15可知,其实就是
不可逆,必然
的行列式等于0,即
,我们称该方程为特征方程
我们依然以
为例来说明该行列式的计算过程
这里A是二阶方阵,所以I为二阶单位矩阵,根据矩阵的加减法,代入得
由于我们知道了
可以为2或者3,依次代入齐次线性方程组,就可以求出相应的特征向量
经过高斯消元,它们都有零行,u是一个二维向量,表示未知数的个数为2,而系数矩阵的非零行为1,小于未知数个数,表示它们都有无数解,这里的s表示可以取任意的实数。可以理解成(1,1)、(2,1)都是一维空间的基,它们所生成的一维空间的所有的向量都是该齐次线性方程组的解。
特征值和特征向量的相关概念
如果u是A对应于
的一个特征向量,则ku也是一个特征向量。这里的k≠0。
这里的k其实就等于上面的s,它可以取任意值,这里我们也来证明一下。
它同样满足
的基本式,所以得证
该命题同样也说明了
有无数解
特征向量组成了
这个方阵的零空间。当然这里要刨除零向量。
准确的说这个零空间
称为
对应的特征空间
特征方程
是一个关于
的n次方程,
有n个解(这个范围是一个复数范围,而不仅仅是实数内)
之前我们例子中的
它就是一个二次方程的两个解,我们称为简单特征值
但也有可能
这个二次方程的两个解相同,我们称为多重特征值,它的重数为2
这个二次方程的两个解为复数,我们称为复数特征值,不过复数特征值和多重特征值我们讨论的比较少,而应用最多的依然是简单特征值
特征值和特征向量的性质
之前我们已经介绍过,如果特征值为0,A一定不可逆,则现在我们可以为方阵A的等价命题再增加一条
- 对于方阵A,矩阵A可逆,A是非奇异矩阵
- 线性系统Ax=0(齐次线性方程组)只有唯一解,x=0
- 矩阵的行最简形式rref(A)=I
- A可以表示成一系列初等矩阵的乘积
- Ax=b只有唯一解
- 方阵A的列向量线性无关
- 方阵A的列向量可以生成n维空间
- 方阵A的列向量是n维空间的基
- 方阵A为满秩矩阵(秩=n)
- 方阵A的行秩为n
- 方阵A的列秩为n
- 方阵A的行空间为
- 方阵A的列空间为
- 方阵A的零空间为{O},维度为0
- det(A)≠0
- 0不是A的特征值
根据特征值和特征向量的定义和特征方程
如果A是一个对角矩阵,它的行列式为
那么
的行列式为
由此可见,对角矩阵的特征值是其对角线上的元素
同理,如果A是一个上三角矩阵,它的行列式为
那么
的行列式为
则上三角矩阵的特征值是其对角线上的元素
同理,如果A是一个下三角矩阵,它的行列式为
那么
的行列式为
则下三角矩阵的特征值是其对角线上的元素
若
是A的特征值,则
是
的特征值
这里我们可以采用数学归纳法来证明
当m=1时,