特征值和奇异值分解(SVD)

特征值分解和奇异值分解两者有着很紧密的关系,两者的目的都是为了提取矩阵最重要的特征。本节先解释特征值分解。先用一个实例来说明特征值和特征向量的起因和实际意义,然后给出定义,计算方法,python代码以及其他解释。

特征值分解

实例

某城市有10000名女性,其中8000名已婚,2000名未婚。每年有30%的已婚女性离婚,有20%的未婚女性结婚。计算若干年后该城市已婚女性和未婚女性的数量。

10000名女性可以用一个向量来表示,即 w 0 = [ 8000 , 2000 ] T ,每年的婚姻情况变化可以用矩阵来表示。

A = [ 0.7 0.2 0.3 0.8 ]

这样,一年后已婚人数和未婚人数可以表示为
w 1 = A w 0 = [ 0.7 0.2 0.3 0.8 ] [ 8000 2000 ] = [ 6000 4000 ]

一直这么变化下去,从第12年开始已婚未婚人数就稳定下来,到达一个稳态(steady state)。
w 12 = A 12 w 0 = [ 0.7 0.2 0.3 0.8 ] 12 [ 8000 2000 ] = [ 0.4 0.4 0.6 0.6 ] [ 8000 2000 ] = [ 4000 6000 ]

这里会提出一个疑问,如果一开始已婚和未婚人数不是 w 0 = [ 8000 , 2000 ] T ,结果还会是 w 12 = [ 4000 , 6000 ] T 吗?从上式可以看出,只要 A n 收敛到等式中的值,不管初值是多少,结果总会是 [ 4000 , 6000 ] T 。如果我们把初值就设置为向量 [ 4000 , 6000 ] T ,那么结果也会是 [ 4000 , 6000 ] T 。根据这一点我们可以得到以下等式,设置向量 x 1 = [ 2 , 3 ] T
A x 1 = A [ 2 3 ] = 1 [ 2 3 ]

接下来看另一个等式,设置向量 x 2 = [ 1 , 1 ] T

A x 2 = A [ 1 1 ] = 1 / 2 [ 1 1 ]

假设初始状态,未婚女性人数为 p ,已婚女性人数为 10000 p ,即 w 0 = [ p , 10000 p ] T 使用向量 x 1 , x 2 来表示,引入两个变量 c 1 , c 2 ,则有
w 0 = c 1 x 1 + c 2 x 2
w 1 = A w 0 = c 1 x 1 + ( 1 2 ) c 2 x 2
w n = A n w 0 = c 1 x 1 + ( 1 2 ) n c 2 x 2
展开 x 1 , x 2 得到以下方程,可以解得 c 1 = 2000
(5) 2 c 1 c 2 = p (6) 3 c 1 + c 2 = 10000 p

这样, w n 可以得到以下分解
w n = A n w 0 = 2000 [ 2 3 ] + ( 1 2 ) n ( 4000 p ) [ 1 1 ]

w n 由两部分组成,第一部分是稳态部分,变换 A 对其不会造成影响。第二部分是瞬态部分,变换 A 会对其造成衰减。这样,变换 A w 0 的作用就可以分解成两个部分,分别由特征向量 x 1 , x 2 ,和特征值 λ 1 , λ 2 来表示。

定义

如果说一个向量 v 是方阵 A 的特征向量,将一定可以表示成下面的形式:

A v = λ v

这时候 λ 就被称为特征向量 v 对应的特征值,矩阵的特征向量是一组正交向量。特征值分解是将一个矩阵分解成下面的形式:
A = Q Σ Q 1

其中 Q 是这个矩阵 A 的特征向量组成的矩阵, Σ 是一个对角阵,每一个对角线上的元素就是一个特征值。求特征值和特征向量分别使用以下方程
(1) d e t ( A λ I ) = 0
(2) ( A λ I ) x = 0

计算

计算过程是先求解行列式 ( 1 ) ,得到特征值 λ ,然后分别将特征值代入方程 ( 2 ) 求得对应的特征向量 x

[ 0.7 λ 0.2 0.3 0.8 λ ] = 0

解方程得到 λ = [ 0.5 , 1 ]
λ = 0.5 时,有
[ 0.2 0.2 0.3 0.3 ] [ x 1 x 2 ] = 0

解得 x 1 = x 2 ,即属于特征值 λ 1 = 0.5 有特征向量 [ 0.707 , 0.707 ] T ,这里做了归一化,要求 | | x | | = 1 。同理可以求得属于特征值 λ 2 = 1 的特征向量 [ 0.5547 , 0.832 ] T

代码

python 代码和输出结果如下

import numpy as np
A = np.array([[0.7, 0.2],[0.3, 0.8]])
eigenvalues, eigenvectors = np.linalg.eig(A)
print('eigenvlues are', eigenvalues)
print('eigenvectors are \n',eigenvectors)
eigenvlues are [0.5 1. ]
eigenvectors are 
 [[-0.70710678 -0.5547002 ]
 [ 0.70710678 -0.83205029]]

其他解释

(以下部分来自其他人的博客)
首先,要明确的是,一个矩阵其实就是一个线性变换,因为一个矩阵乘以一个向量后得到的向量,其实就相当于将这个向量进行了线性变换。比如说下面的一个矩阵:

M = [ 3 0 0 1 ]

它其实对应的线性变换是下面的形式:
这里写图片描述
因为这个矩阵 M 乘以一个向量 [ x , y ] T 的结果是:
[ 3 0 0 1 ] [ x y ] = [ 3 x y ]

上面的矩阵是对称的,所以这个变换是一个对 x y 轴的方向一个拉伸变换(每一个对角线上的元素将会对一个维度进行拉伸变换,当值 > 1 时拉长,当值 < 1 时缩短),当矩阵不是对称的时候,假如说矩阵是下面的样子:
M = [ 1 1 0 1 ]

它所描述的变换是下面的样子:
这里写图片描述

这其实是在平面上对一个轴进行的拉伸变换(如蓝色的箭头所示),在图中,蓝色的箭头是一个最主要的变化方向(变化方向可能有不止一个),如果我们想要描述好一个变换,那我们就描述好这个变换主要的变化方向就好了。反过头来看看之前特征值分解的式子,分解得到的Σ矩阵是一个对角阵,里面的特征值是由大到小排列的,这些特征值所对应的特征向量就是描述这个矩阵变化方向(从主要的变化到次要的变化排列)

当矩阵是高维的情况下,那么这个矩阵就是高维空间下的一个线性变换,这个线性变化可能没法通过图片来表示,但是可以想象,这个变换也同样有很多的变换方向,我们通过特征值分解得到的前N个特征向量,那么就对应了这个矩阵最主要的N个变化方向。我们利用这前N个变化方向,就可以近似这个矩阵(变换)。也就是之前说的:提取这个矩阵最重要的特征。总结一下,特征值分解可以得到特征值与特征向量,特征值表示的是这个特征到底有多重要,而特征向量表示这个特征是什么,可以将每一个特征向量理解为一个线性的子空间,我们可以利用这些线性的子空间干很多的事情。不过,特征值分解也有很多的局限,比如说变换的矩阵必须是方阵。

猜你喜欢

转载自blog.csdn.net/s09094031/article/details/80814283
今日推荐