奇异值分解SVD(Singular Value Decomposition)以及应用总结! |
奇异值分解(Singular Value Decomposition
)是线性代数中一种重要的矩阵分解(Matrix Decomposition
),奇异值分解则是特征分解在任意矩阵上的推广。在信号处理、统计学等领域有重要应用。这篇文章主要说下奇异值分解,这个方法在机器学习的一些算法里占有重要地位。
如果一个矩阵满足以下几个条件,则此矩阵就是正交矩阵:
如果 A A A为一个正交矩阵,则A满足以下条件:
如果对于 所有的非零实系数向量 z z z,都有 z T A z > 0 z ^ { T } A z > 0 zTAz>0,则称矩阵 A A A 是正定的。正定矩阵的行列式必然大于 0, 所有特征值也必然大于0。相对应的,半正定矩阵的行列式必然大于等于0。对于 n n n 阶实对称矩阵 A A A,下列条件是等价的:
根据正定矩阵的定义及性质,判别对称矩阵 A A A 的正定性有两种方法:
例: 判断矩阵是否正定
Q = { 6 − 3 1 − 3 2 0 1 0 4 } Q=\left\{\begin{array}{ccc}{6} & {-3} & {1} \\ {-3} & {2} & {0} \\ {1} & {0} & {4}\end{array}\right\} Q=⎩⎨⎧6−31−320104⎭⎬⎫
注意: E E E在这里表示单位阵,式 ( 1 ) (1) (1) 的具体求解过程就不多叙述了,可以回忆一下大学时的线性代数。简单地有如下关系: A q i = λ i q i , q i T q j = 1 ( i ≠ j ) Aq_i = \lambda_i q_i, \quad q_i^T q_j = 1(i \ne j) Aqi=λiqi,qiTqj=1(i=j)。
上面的特征值分解,对矩阵有着较高的要求,它需要被分解的矩阵 A A A 为实对称矩阵,但是现实中,我们所遇到的问题一般不是实对称矩阵。那么当我们碰到一般性的矩阵,即有一个 m × n m×n m×n 的矩阵 A A A,它是否能被分解成上面的式 ( 1 ) (1) (1) 的形式呢?当然是可以的,这就是我们下面要讨论的内容。
有一个 m × n m×n m×n 的实数矩阵 A A A,我们想要把它分解成如下的形式
A = U Σ V T (2) A=U \Sigma V^{T} \tag{2} A=UΣVT(2)
其中 U U U 和 V V V 均为单位正交阵(任意2行互相垂直,长度为1,列也是一样),即有 U U T = E UU^T=E UUT=E 和 V V T = E VV^T=E VVT=E, U U U 称为左奇异矩阵, V V V 称为右奇异矩阵, Σ \Sigma Σ 仅在主对角线上有值,我们称它为奇异值。其它元素均为 0 0 0。上面矩阵的维度分别为 U ∈ R m × m , Σ ∈ R m × n , V ∈ R n × n U \in R^{m\times m},\ \Sigma \in R^{m\times n},\ V \in R^{n\times n} U∈Rm×m, Σ∈Rm×n, V∈Rn×n。一般地 Σ Σ Σ有如下形式:
Σ = [ σ 1 0 0 0 0 0 σ 2 0 0 0 0 0 ⋱ 0 0 0 0 0 ⋱ 0 ] m × n \Sigma=\left[ \begin{array}{ccccc}{\sigma_{1}} & {0} & {0} & {0} & {0} \\ {0} & {\sigma_{2}} & {0} & {0} & {0} \\ {0} & {0} & {\ddots} & {0} & {0} \\ {0} & {0} & {0} & {\ddots} & {0}\end{array}\right]_{m \times n} Σ=⎣⎢⎢⎡σ10000σ20000⋱0000⋱0000⎦⎥⎥⎤m×n
其中: σ i \sigma_{i} σi 为奇异值,特征值开根号就是奇异值。
对于奇异值分解,我们可以利用上面的图形象表示,图中方块的颜色表示值的大小,颜色越浅,值越大。对于奇异值矩阵 Σ Σ Σ,只有其主对角线有奇异值,其余均为 0 0 0。
正常求上面的 U , V , Σ U,V,\Sigma U,V,Σ 不便于求,我们可以利用如下性质:
A A T = U Σ V T V Σ T U T = U Σ Σ T U T A T A = V Σ T U T U Σ V T = V Σ T Σ V T (3,4) \begin{aligned} A A^{T} &=U \Sigma V^{T} V \Sigma^{T} U^{T}=U \Sigma \Sigma^{T} U^{T} \tag{3,4}\\\ A^{T} A &=V \Sigma^{T} U^{T} U \Sigma V^{T}=V \Sigma^{T} \Sigma V^{T} \end{aligned} AAT ATA=UΣVTVΣTUT=UΣΣTUT=VΣTUTUΣVT=VΣTΣVT(3,4) 这样的话, A A T A A^{T} AAT 和 A T A A^{T}A ATA 都变成了对称矩阵,就可以利用第二部分中的特征值分解,算出特征值,特征向量。
注意:需要指出的是,这里 Σ Σ T \Sigma\Sigma^T ΣΣT 与 Σ T Σ \Sigma^T\Sigma ΣTΣ 在矩阵的角度上来讲,它们是不相等的,因为它们的维数不同 Σ Σ T ∈ R m × m \Sigma\Sigma^T \in R^{m \times m} ΣΣT∈Rm×m,而 Σ T Σ ∈ R n × n \Sigma^T\Sigma \in R^{n \times n} ΣTΣ∈Rn×n,但是它们在主对角线的奇异值是相等的,即有:
Σ Σ T = [ σ 1 2 0 0 0 0 σ 2 2 0 0 0 0 ⋱ 0 0 0 0 ⋱ ] m×m Σ T Σ = [ σ 1 2 0 0 0 0 σ 2 2 0 0 0 0 ⋱ 0 0 0 0 ⋱ ] n × n \Sigma \Sigma^{T}=\left[ \begin{array}{cccc}{\sigma_{1}^{2}} & {0} & {0} & {0} \\ {0} & {\sigma_{2}^{2}} & {0} & {0} \\ {0} & {0} & {\ddots} & {0} \\ {0} & {0} & {0} & {\ddots}\end{array}\right]_{\operatorname{m×m}} \Sigma^{T} \Sigma=\left[ \begin{array}{cccc}{\sigma_{1}^{2}} & {0} & {0} & {0} \\ {0} & {\sigma_{2}^{2}} & {0} & {0} \\ {0} & {0} & {\ddots} & {0} \\ {0} & {0} & {0} & {\ddots}\end{array}\right]_{n \times n} ΣΣT=⎣⎢⎢⎡σ120000σ220000⋱0000⋱⎦⎥⎥⎤m×mΣTΣ=⎣⎢⎢⎡σ120000σ220000⋱0000⋱⎦⎥⎥⎤n×n
可以看到式 ( 3 ) (3) (3) 与式 ( 1 ) (1) (1) 的形式非常相同,进一步分析,我们可以发现 A A T AA^T AAT 和 A T A A^TA ATA 也是对称矩阵,那么可以利用式 ( 1 ) (1) (1),做特征值分解。利用式 ( 3 ) (3) (3) 特征值分解,得到的特征矩阵即为 U U U;利用式 ( 4 ) (4) (4) 特征值分解,得到的特征矩阵即为 V V V;对 Σ Σ T \Sigma\Sigma^T ΣΣT 或 Σ T Σ \Sigma^T\Sigma ΣTΣ 中的特征值开方,可以得到所有的奇异值。
假设我们现在有矩阵 A A A,需要对其做奇异值分解,已知:
A = ( 2 4 1 3 0 0 0 0 ) A=\left( \begin{array}{ll}{2} & {4} \\ {1} & {3} \\ {0} & {0} \\ {0} & {0}\end{array}\right) A=⎝⎜⎜⎛21004300⎠⎟⎟⎞
那么可以求出 A A T AA^T AAT,如下:
A A T = ( 20 14 0 0 14 10 0 0 0 0 0 0 0 0 0 0 ) (5) A A^{T}=\left( \begin{array}{cccc}{20} & {14} & {0} & {0} \\ {14} & {10} & {0} & {0} \\ {0} & {0} & {0} & {0} \\ {0} & {0} & {0} & {0}\end{array}\right) \tag{5} AAT=⎝⎜⎜⎛20140014100000000000⎠⎟⎟⎞(5)
接下来就是求这个矩阵的特征值和特征向量了:
A A T x = λ x ( A A T − λ E ) x = 0 (6) \begin{array}{c}{A A^{T} x=\lambda x} \\ {\left(A A^{T}-\lambda E\right) x=0}\end{array} \tag{6} AATx=λx(AAT−λE)x=0(6)
要想该方程组有非零解(即非零特征值),那么系数矩阵 A A T − λ E A A ^ { T } - \lambda E AAT−λE 的行列式必须为 0 0 0
∣ 20 − λ 14 0 0 14 10 − λ 0 0 0 0 − λ 0 0 0 0 − λ ∣ = 0 (7) \left| \begin{array}{cccc}{20-\lambda} & {14} & {0} & {0} \\ {14} & {10-\lambda} & {0} & {0} \\ {0} & {0} & {-\lambda} & {0} \\ {0} & {0} & {0} & {-\lambda}\end{array}\right|=0 \tag{7} ∣∣∣∣∣∣∣∣20−λ14001410−λ0000−λ0000−λ∣∣∣∣∣∣∣∣=0(7)
求解这个行列式我就不再赘述了,这个直接使用行列式展开定理就可以了,可以得到 λ 1 ≈ 29.86606875 , λ 2 ≈ 0.13393125 , λ 3 = λ 4 = 0 λ1≈29.86606875,λ2≈0.13393125,λ3=λ4=0 λ1≈29.86606875,λ2≈0.13393125,λ3=λ4=0;有 4 个特征值,因为特征多项式 ∣ A A T − λ E ∣ \vert AA^T - \lambda E \vert ∣AAT−λE∣是一个 4 4 4 次多项式。对应的单位化过的特征向量为
( 0.81741556 − 0.57604844 0 0 0.57604844 0.81741556 0 0 0 0 1 0 0 0 0 1 ) (8) \left( \begin{array}{cccc}{0.81741556} & {-0.57604844} & {0} & {0} \\ {0.57604844} & {0.81741556} & {0} & {0} \\ {0} & {0} & {1} & {0} \\ {0} & {0} & {0} & {1}\end{array}\right) \tag{8} ⎝⎜⎜⎛0.817415560.5760484400−0.576048440.817415560000100001⎠⎟⎟⎞(8)
这就是矩阵 U U U 了。 同样的过程求解 A T A A^TA ATA 的特征值和特征向量,求得 λ 1 ≈ 0.13393125 , λ 2 ≈ 29.86606875 λ1≈0.13393125,λ2≈29.86606875 λ1≈0.13393125,λ2≈29.86606875,将特征值降序排列后对应的单位化过的特征向量为:
( 0.4045358 − 0.9145143 0.9145143 0.40455358 ) (9) \left( \begin{array}{cc}{0.4045358} & {-0.9145143} \\ {0.9145143} & {0.40455358}\end{array}\right) \tag{9} (0.40453580.9145143−0.91451430.40455358)(9) 这就是矩阵 V V V 了。 而矩阵 Σ Σ Σ 根据上面说的为特征值的平方根构成的对角矩阵(又大到小排序):
( 5.4649857 0 0 0.36596619 0 0 0 0 ) (10) \left( \begin{array}{cc}{5.4649857} & {0} \\ {0} & {0.36596619} \\ {0} & {0} \\ {0} & {0}\end{array}\right) \tag{10} ⎝⎜⎜⎛5.464985700000.3659661900⎠⎟⎟⎞(10) 到此,SVD 分解就结束了,原来的矩阵 A A A 就被分解成了 3 3 3 个矩阵的乘积。
A 4 × 2 = U 4 × 4 Σ 4 × 2 V 2 × 2 T (11) A_{4 \times 2}=U_{4 \times 4} \Sigma_{4 \times 2} V_{2 \times 2}^{T} \tag{11} A4×2=U4×4Σ4×2V2×2T(11) ( 2 4 1 3 0 0 0 0 ) = ( 0.81741556 − 0.57604844 0 0 0.57604844 0.81741556 0 0 0 0 1 0 0 0 0 1 ) ( 5.4649857 0 0 0.36596619 0 0 0 0 ) ( 0.40453358 − 0.9145143 0.9145143 0.40455358 ) T \left( \begin{array}{cc}{2} & {4} \\ {1} & {3} \\ {0} & {0} \\ {0} & {0}\end{array}\right)=\left( \begin{array}{cccc}{0.81741556} & {-0.57604844} & {0} & {0} \\ {0.57604844} & {0.81741556} & {0} & {0} \\ {0} & {0} & {1} & {0} \\ {0} & {0} & {0} & {1}\end{array}\right)\left( \begin{array}{cc}{5.4649857} & {0} \\ {0} & {0.36596619} \\ {0} & {0} \\ {0} & {0}\end{array}\right) \left( \begin{array}{cc}{0.40453358} & {-0.9145143} \\ {0.9145143}& {0.40455358}\end{array}\right)^{T} ⎝⎜⎜⎛21004300⎠⎟⎟⎞=⎝⎜⎜⎛0.817415560.5760484400−0.576048440.817415560000100001⎠⎟⎟⎞⎝⎜⎜⎛5.464985700000.3659661900⎠⎟⎟⎞(0.404533580.9145143−0.91451430.40455358)T
使用pyhon
中的numpy
包的 linalg.svd()
来求解 SVD
。分别对上面做特征值分解,得到如下结果:
要分解的矩阵 W W W,分解为: W = U Σ V T W=U \Sigma V^{T} W=UΣVT;
W = [ 1 1 0 1 1 0 ] (13) W=\left[ \begin{array}{ll}{1} & {1} \\ {0} & {1} \\ {1} & {0}\end{array}\right]\tag{13} W=⎣⎡101110⎦⎤(13)
首先计算:
C = W T W = [ 1 0 1 1 1 0 ] [ 1 1 0 1 1 0 ] = [ 2 1 1 2 ] (14) C=W^{T} W=\left[ \begin{array}{lll}{1} & {0} & {1} \\ {1} & {1} & {0}\end{array}\right] \left[ \begin{array}{ll}{1} & {1} \\ {0} & {1} \\ {1} & {0}\end{array}\right]=\left[ \begin{array}{ll}{2} & {1} \\ {1} & {2}\end{array}\right]\tag{14} C=WTW=[110110]⎣⎡101110⎦⎤=[2112](14) 求出 C C C 的特征值: λ 1 = 3 , λ 2 = 1 , λ 3 = 0 \lambda_{1}=3, \lambda_{2}=1, \lambda_{3}=0 λ1=3,λ2=1,λ3=0;特征向量:
v ⃗ 1 = [ 1 2 1 2 ] , v ⃗ 2 = [ 1 2 − 1 2 ] \vec{v}_{1}=\left[ \begin{array}{c}{\frac{1}{\sqrt{2}}} \\ {\frac{1}{\sqrt{2}}}\end{array}\right], \vec{v}_{2}=\left[ \begin{array}{c}{\frac{1}{\sqrt{2}}} \\ {\frac{-1}{\sqrt{2}}}\end{array}\right] v1=[2121],v2=[212−1]
其次计算:
B = W W T = [ 1 1 0 1 1 0 ] [ 1 0 1 1 1 0 ] = [ 2 1 1 1 1 0 1 0 1 ] (15) B=W W^{T}=\left[ \begin{array}{ll}{1} & {1} \\ {0} & {1} \\ {1} & {0}\end{array}\right] \left[ \begin{array}{lll}{1} & {0} & {1} \\ {1} & {1} & {0}\end{array}\right]=\left[ \begin{array}{lll}{2} & {1} & {1} \\ {1} & {1} & {0} \\ {1} & {0} & {1}\end{array}\right]\tag{15} B=WWT=⎣⎡101110⎦⎤[110110]=⎣⎡211110101⎦⎤(15)
求出 B B B 的特征值: λ 1 = 3 , λ 2 = 1 , λ 3 = 0 \lambda_{1}=3, \lambda_{2}=1, \lambda_{3}=0 λ1=3,λ2=1,λ3=0,特征向量:
u ⃗ 1 = [ 2 6 1 6 1 6 ] , u ⃗ 2 = [ 0 − 1 2 1 2 ] , u ⃗ 3 = [ − 1 3 1 3 1 3 ] \vec{u}_{1}=\left[ \begin{array}{c}{\frac{2}{\sqrt{6}}} \\ {\frac{1}{\sqrt{6}}} \\ {\frac{1}{\sqrt{6}}}\end{array}\right], \vec{u}_{2}=\left[ \begin{array}{c}{0} \\ {\frac{-1}{\sqrt{2}}} \\ {\frac{1}{\sqrt{2}}}\end{array}\right], \vec{u}_{3}=\left[ \begin{array}{c}{\frac{-1}{\sqrt{3}}} \\ {\frac{1}{\sqrt{3}}} \\ {\frac{1}{\sqrt{3}}}\end{array}\right] u1=⎣⎢⎡626161⎦⎥⎤,u2=⎣⎡02−121⎦⎤,u3=⎣⎢⎡3−13131⎦⎥⎤
最终 W W W矩阵可以分解为如下。注意一下公式中的最后一项是转置,只是这里转置之后,仍然和原来相等。奇异值就是特征值开根号(对角线降序排列) [ 1 1 0 1 1 0 ] = [ 2 6 0 − 1 3 1 6 − 1 2 1 3 1 6 1 2 1 3 ] [ 3 0 0 1 0 0 ] [ 1 2 1 2 1 2 − 1 2 ] (16) \left[ \begin{array}{ll}{1} & {1} \\ {0} & {1} \\ {1} & {0}\end{array}\right]=\left[ \begin{array}{ccc}{\frac{2}{\sqrt{6}}} & {0} & {-\frac{1}{\sqrt{3}}} \\ {\frac{1}{\sqrt{6}}} & {\frac{-1}{\sqrt{2}}} & {\frac{1}{\sqrt{3}}} \\ {\frac{1}{\sqrt{6}}} & {\frac{1}{\sqrt{2}}} & {\frac{1}{\sqrt{3}}}\end{array}\right] \left[ \begin{array}{cc}{\sqrt{3}} & {0} \\ {0} & {1} \\ {0} & {0}\end{array}\right] \left[ \begin{array}{cc}{\frac{1}{\sqrt{2}}} & {\frac{1}{\sqrt{2}}} \\ {\frac{1}{\sqrt{2}}} & {\frac{-1}{\sqrt{2}}}\end{array}\right] \tag{16} ⎣⎡101110⎦⎤=⎣⎢⎡62616102−121−313131⎦⎥⎤⎣⎡300010⎦⎤[2121212−1](16) 其中 3 \sqrt{3} 3和 1 1 1为 2 2 2 个奇异值,等于前面求出来的特征值开根号。
又等于如下:第1个奇异值,配第1列,配第1行,加上第2个奇异值,配第2列,配第2行。就是看做2个矩阵相加! = 3 [ 2 6 1 6 6 6 ] [ 1 2 1 2 ] + [ 0 − 1 2 1 2 ] [ 1 2 − 1 2 ] =\sqrt{3} \left[ \begin{array}{c}{\frac{2}{\sqrt{6}}} \\ {\frac{1}{\sqrt{6}}} \\ {\frac{\sqrt{6}}{\sqrt{6}}}\end{array}\right] \left[ \begin{array}{cc}{\frac{1}{\sqrt{2}}} & {\frac{1}{\sqrt{2}}}\end{array}\right]+\left[ \begin{array}{c}{0} \\ {-\frac{1}{\sqrt{2}}} \\ {\frac{1}{\sqrt{2}}}\end{array}\right] \left[ \begin{array}{cc}{\frac{1}{\sqrt{2}}} & {\frac{-1}{\sqrt{2}}}\end{array}\right] =3⎣⎢⎡626166⎦⎥⎤[2121]+⎣⎡0−2121⎦⎤[212−1]
就是看做矩阵相加! W = U Σ V T = λ 1 u ⃗ 1 ( v ⃗ 1 ) T + λ 2 u ⃗ 2 ( v ⃗ 2 ) T W=U \Sigma V^{T}=\sqrt{\lambda_{1}} \vec{u}_{1}\left(\vec{v}_{1}\right)^{T}+\sqrt{\lambda_{2}} \vec{u}_{2}\left(\vec{v}_{2}\right)^{T} W=UΣVT=λ1u1(v1)T+λ2u2(v2)T
也就是说SVD分解可以把 W W W改写成(拆成)这个样子,这就是SVD分解最想做的事情,以这个例子来说,这2个奇异值都是挺大的,但是在通常有一些例子里面,你的矩阵很大,奇异值很多,你的奇异值有些很大,有些很小。如果你把小的奇异值丢掉,但其实整个算出来的数字并不是差的太多,这是一个好处,可以减小计算。我们可以把一些小的奇异值丢掉,分解完我就可以分解成很多奇异值相加,但是我们把小的丢掉,所以这是SVD分解最实用的部分。
丢掉小的奇异值有以下2个目的:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
# 读取图片
img_eg = mpimg.imread(r"C:\Users\devinzhang\Desktop\timg.jpg")
print(img_eg.shape)
(526, 640, 3)
Process finished with exit code 0
# 奇异值分解
img_temp = img_eg.reshape(526, 640 * 3)
U, Sigma, VT = np.linalg.svd(img_temp)
print(Sigma)
# 取前60个奇异值
sval_nums = 30
img_restruct1 = (U[:,0:sval_nums]).dot(np.diag(Sigma[0:sval_nums])).dot(VT[0:sval_nums,:])
img_restruct1 = img_restruct1.reshape(526, 640,3)
# 取前120个奇异值
sval_nums = 120
img_restruct2 = (U[:,0:sval_nums]).dot(np.diag(Sigma[0:sval_nums])).dot(VT[0:sval_nums,:])
img_restruct2 = img_restruct2.reshape(526, 640,3)
fig, ax = plt.subplots(1,3,figsize = (24,32))
ax[0].imshow(img_eg)
ax[0].set(title = "src")
ax[1].imshow(img_restruct1.astype(np.uint8))
ax[1].set(title = "nums of sigma = 30")
ax[2].imshow(img_restruct2.astype(np.uint8))
ax[2].set(title = "nums of sigma = 120")
plt.show()
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
# 读取图片
img_eg = mpimg.imread(r"C:\Users\devinzhang\Desktop\timg.jpg")
print(img_eg.shape)
# 奇异值分解
img_temp = img_eg.reshape(526, 640 * 3)
U, Sigma, VT = np.linalg.svd(img_temp)
print(Sigma)
# 取前60个奇异值
sval_nums = 30
img_restruct1 = (U[:,0:sval_nums]).dot(np.diag(Sigma[0:sval_nums])).dot(VT[0:sval_nums,:])
img_restruct1 = img_restruct1.reshape(526, 640,3)
# 取前120个奇异值
sval_nums = 120
img_restruct2 = (U[:,0:sval_nums]).dot(np.diag(Sigma[0:sval_nums])).dot(VT[0:sval_nums,:])
img_restruct2 = img_restruct2.reshape(526, 640,3)
fig, ax = plt.subplots(1,3,figsize = (24,32))
ax[0].imshow(img_eg)
ax[0].set(title = "src")
ax[1].imshow(img_restruct1.astype(np.uint8))
ax[1].set(title = "nums of sigma = 30")
ax[2].imshow(img_restruct2.astype(np.uint8))
ax[2].set(title = "nums of sigma = 120")
plt.show()
参考了一下作者的博客,还有一些其它资源,再这里表示感谢!