线性代数:行列式计算

线性代数是机器学习中非常重要的基础知识,但是,往往这句话,咱们开始是听不进去的。就好比说,小学的时候,没有哪一个老师不告诉你学习很重要,但是若干年后,大部分的人都会或多或少有些懊悔,觉得当时没有好好听话。同样的道理,在入门阶段,如果不学好线代,那么以后做相关方面的学习和开发的时候,看文档就会变得异常吃力,许多推导式都感觉看不懂,或者当时感觉看懂了,过一会儿又不会了。

正所谓“少壮不努力,开发徒伤悲”,不过也不必要太丧,天大的窟窿也能补,虽然并非一朝之功。先从简单的开始吧,本节讲讲行列式。

定义

维基百科中给出的定义是:行列式是一个函数,将一个nnn\cdot n的矩阵映射到一个标量。

这个标量表示经过这个矩阵所代表的线性变换之后,矩阵的“体积”在空间当中发生的变化。

翻译成人话就是,输入一个矩阵,然后输出一个经过处理算法生成的数字。我们把行列式用det()\det()来表示。如果AA是一个nnn\cdot n的矩阵,那么det(A)\det(A)即表示该矩阵的行列式。

计算

二阶行列式

假设

A=a11a12a21a22A=\begin{vmatrix}a_{11}&a_{12}\\a_{21}&a_{22}\end{vmatrix}

那么,

det(A)=a11a22a12a21\det(A)=a_{11}\cdot a_{22}-a_{12}\cdot a_{21}

也就是对角相乘,然后左斜减去右斜。

三阶行列式

假设

B=a11a12a13a21a22a23a31a32a33B=\begin{vmatrix}a_{11}&a_{12}&a_{13}\\a_{21}&a_{22}&a_{23}\\a_{31}&a_{32}&a_{33}\end{vmatrix}

那么,

det(B)=a11a22a33+a12a23a31+a13a21a32a11a23a32a12a21a33a13a22a31\begin{aligned}\det(B)=&a_{11}\cdot a_{22}\cdot a_{33}+a_{12}\cdot a_{23}\cdot a_{31}+a_{13}\cdot a_{21}\cdot a_{32}\\-&a_{11}\cdot a_{23}\cdot a_{32}-a_{12}\cdot a_{21}\cdot a_{33}-a_{13}\cdot a_{22}\cdot a_{31}\end{aligned}

刚看感觉怎么这么复杂,其实仔细一看,还是和二阶的套路差不多,不过是多了个维度罢了。

我们刚刚列举出来了二阶和三阶的具体计算方法,那么按照学数学的常规路径,应该是要推导一下nn阶的行列式怎么计算,或者有什么规律之类的。不过在这之前,我们先要了解一下另一个概念——逆序数

逆序数

假设现在我们有一个数组A,理想情况下它是一个有序数组,不过在现实生活中并不太常见这种理想情况,大多都是乱序的。那么如果我们想要知道当前的这个数组(序列)距离有序到底有多大的差距,也就是量化这个差距,那么会很自然地想到,可以遍历这个数组里面的所有AiA_iAjA_j组合,然后记下次序有误的次数。那么这个次数就叫做逆序数

放在代码里面,就非常好懂了:

count = 0
for i in range(n):
    for j in range(i):
        if A[i] < a[j]:
            count += 1

也就是说,对于数组A中的每一个数,我们都计算出了它前面的比它大的数。那么对于每一个AiA_i,我们计算出的前面比它大的数的个数记作tit_i,那么逆序数就可以表达为:

t=t1+t2+t3++tn=i=1ntit=t_1+t_2+t_3+\ldots+t_n=\sum_{i=1}^nt_i

n阶行列式

接下来,就回归我们刚刚的话题。有了逆序数的概念,我们就可以很方便地写出n阶行列式的公式。

假设

D=a11a12a1na21a22a2nan1an2annD=\begin{vmatrix}a_{11}&a_{12}&\cdots&a_{1n}\\a_{21}&a_{22}&\cdots&a_{2n}\\\vdots&\vdots&&\vdots\\a_{n1}&a_{n2}&\cdots&a_{nn}\end{vmatrix}

设自然数1,2,3n1,2,3\ldots n 的一个排列为j1,j2,j3jnj_1,j_2,j_3\ldots j_n,这个排列的逆序数为tt,那么,

det(D)=j1j2jn(1)ta1j1a2j2anjn\det(D)=\sum_{j_1j_2\ldots j_n}(-1)^ta_{1_{j1}}a_{2_{j2}}\ldots a_{n_{jn}}

当然,也可以把(i,j)(i,j)元素所在的行和列的所有元素全部去除之后,剩下的新的n1n-1阶的行列式被称为(i,j)(i,j)元的代数余子式,记为MijM_{ij}

如:

E=a11a12a13a14a21a22a23a24a31a32a33a34a41a42a43a44E=\begin{vmatrix}a_{11}&a_{12}&a_{13}&a_{14}\\a_{21}&a_{22}&a_{23}&a_{24}\\a_{31}&a_{32}&a_{33}&a_{34}\\a_{41}&a_{42}&a_{43}&a_{44}\end{vmatrix}

其中(2,2)(2,2)元的代数余子式为:

M22=a11a13a14a31a33a34a41a43a44M_{22}=\begin{vmatrix}a_{11}&a_{13}&a_{14}\\a_{31}&a_{33}&a_{34}\\a_{41}&a_{43}&a_{44}\end{vmatrix}

那么EE矩阵的行列式就可以表达为:

det(E)=i=1na1iM1i\det(E)=\sum_{i=1}^na_{1i}M_{1i}

实际上就是计算的时候提取公因式罢了。假设一个三阶行列式:

det(X)=a11(a22a33a23a32)+a12(a23a31a21a33)+a13(a21a32a22a31)\det(X)=a_{11}(a_{22}a_{33}-a_{23}a_{32})+a_{12}(a_{23}a_{31}-a_{21}a_{33})+a_{13}(a_{21}a_{32}-a_{22}a_{31})

那么把这些代数余子式写出来:

a11a12a13a21a22a23a31a32a33=a11a22a23a32a33+a12a21a23a31a33+a13a21a22a31a32\begin{vmatrix}a_{11}&a_{12}&a_{13}\\a_{21}&a_{22}&a_{23}\\a_{31}&a_{32}&a_{33}\end{vmatrix}=\begin{vmatrix}a_{11}&&\\&a_{22}&a_{23}\\&a_{32}&a_{33}\end{vmatrix}+\begin{vmatrix}&a_{12}&\\a_{21}&&a_{23}\\a_{31}&&a_{33}\end{vmatrix}+\begin{vmatrix}&&a_{13}\\a_{21}&a_{22}&\\a_{31}&a_{32}&\end{vmatrix}

化简,就是上面的结果。

克拉默法则

可能有许多初学者会觉得行列式的定义和计算都过于繁琐,并且好像还感觉没什么用。

那么除了用在机器学习的模型之中,还能够用来判断线性方程组是否有解。

对于一个有nn个未知数的nn个线性方程组:

{a11x1+a12x2++a1nxn=b1a21x1+a22x2++a2nxn=b2an1x1+an2x2++annxn=bn\begin{cases}a_{11}x_1+a_{12}x_2+\ldots+a_{1n}x_n=b_1\\a_{21}x_1+a_{22}x_2+\ldots+a_{2n}x_n=b_2\\\ldots\\a_{n1}x_1+a_{n2}x_2+\ldots+a_{nn}x_n=b_n\\\end{cases}

它的解可以用nn阶行列式表示。

如果这个nn阶的行列式不等于0,即:

det(X)=det(a11a1nan1ann)=0\det(X)=\det\left(\begin{matrix}a_{11}&\cdots&a_{1n}\\\vdots&&\vdots\\a_{n1}&\cdots&a_{nn}\end{matrix}\right)\not=0

那么这个nn阶方程组有唯一解:

x1=X1Xx2=X2Xx3xn=XnXx_1=\dfrac{X_1}X\cdot x_2=\dfrac{X_2}X\cdot x_3\ldots x_n=\dfrac{X_n}X

其中Xj(j=1,2n)X_j(j=1,2\ldots n)是把XX中第jj列替换成方程常数项得到的新的行列式:

Xj=a11ai,j1b1a1,j+1a1nan1an,j1bnan,j+1annX_j=\begin{vmatrix}a_{11}&\cdots&a_{i,j-1}&b_1&a_{1,j+1}&\cdots&a_{1n}\\\vdots&&\vdots&\vdots&\vdots&&\vdots\\a_{n1}&\cdots&a_{n,j-1}&b_n&a_{n,j+1}&\cdots&a_{nn}\end{vmatrix}

行列式除了上面的内容意外,还有许多很好用的特性以及一些推导计算方法。不过对于算法领域的帮助并不大,有兴趣的同学可以自己研究下。