机器学习-SVD分解算法的物理意义
奇异值分解(Singular Value Decomposition),以下简称SVD。
奇异值分解算法是一种在机器学习中经常使用到的一个算法,SVD主要用于数据压缩和数据降维,在图像压缩、推荐系统有着极其重要的作用,
本文将着重理解SVD分解算法的物理意义以及我们将用Python代码将这个过程可视化,数学推导将不是本文的重点,将在它文展示。
一.SVD分解介绍
任何一个形状的矩阵(图像)都可以转化从先旋转、再延伸、再旋转的形式。
公式如下
SVD分解就是将一个矩阵转变为这三个矩阵的表达形式,同时,这三个矩阵分别代表一个旋转、一个伸缩、一个旋转。
为什么呢?
提出问题就解决了一半的问题。为什么一个矩阵可以转变为一个旋转矩阵、一个伸缩矩阵、一个旋转矩阵相乘呢?
让我们来看一个简单的例子
Unit circle 要怎么转换才能转换成为下图中的A的形式呢?(这里要注意点的颜色!)
首先,我们先让Unit circle逆时针旋转135度。
再让旋转后的图像在x轴上伸长6.70820393249937倍(为什么是这个倍数,先不用纠结,这是奇异值分解以后的一个奇异值数),在y轴上伸长2.2360679774997894倍
然后我们再让图像旋转一次,即可得到和A同等的一个图像. U sigma Vt
这样,原图到A的过程就可以转变为将原图先进行一个旋转、再进行一个伸缩、再进行一个旋转。
我们知道,任何的图像的变化都可以用线性代数里的一个矩阵来表示。
实际上,从原图到A的一个变换矩阵就是
A = ∣ 3 0 4 5 ∣ A = \left|\begin{matrix} 3 & 0 \\ 4 & 5 \end{matrix} \right| A=∣∣∣∣3405∣∣∣∣
我们将其拆解以后,第一个转换图像对应的旋转是逆时针旋转135度,我们可以将第一个旋转用矩阵表示为
V = ∣ − 0.71 − 0.71 − 0.71 0.71 ∣ V=\left|\begin{matrix} -0.71 & -0.71 \\ -0.71 & 0.71 \end{matrix} \right| V=∣∣∣∣−0.71−0.71−0.710.71∣∣∣∣
然后进行左乘一个伸缩矩阵(注意里面的数字和上面那个伸缩大小之间)
Σ = ∣ 6.71 0 0 2.24 ∣ \Sigma = \left|\begin{matrix} 6.71 & 0 \\ 0 & 2.24 \end{matrix} \right| Σ=∣∣∣∣6.71002.24∣∣∣∣
然后最后再左乘一个旋转矩阵
U = ∣ − 0.32 − 0.95 − 0.95 0.32 ∣ U = \left|\begin{matrix} -0.32 & -0.95 \\ -0.95 & 0.32 \end{matrix} \right| U=∣∣∣∣−0.32−0.95−0.950.32∣∣∣∣
我们用Python中的Nupmy来协助我们计算一下这三个矩阵相乘后是否等于A
import numpy as np
V =np.array( [[-0.71 ,-0.71],
[-0.71 , 0.71]])
sigma = np.array([[6.71 ,0. ],
[0. , 2.24]])
U = np.array([[-0.32 ,-0.95],
[-0.95 ,0.32]])
res1 = np.matmul(U, sigma)
res1
res2 = np.matmul(res1,V)
res2
array([[3.035392, 0.013632],
[4.016967, 5.034823]])
我们看到矩阵相乘后生成了一个新的矩阵,而这个矩阵正是和A矩阵极其相近的一个矩阵(计算机已经认为一致)
r e s 2 = ∣ 3.035392 0.013632 4.016967 5.034823 ∣ res2 = \left|\begin{matrix} 3.035392 & 0.013632 \\ 4.016967 & 5.034823 \end{matrix} \right| res2=∣∣∣∣3.0353924.0169670.0136325.034823∣∣∣∣
A = ∣ 3 0 4 5 ∣ A = \left|\begin{matrix} 3 & 0 \\ 4 & 5 \end{matrix} \right| A=∣∣∣∣3405∣∣∣∣
现在我们已经可以将一个复杂的变化(或者称之为一个复杂的变化矩阵)转变为三个简易的变化(或者称之为三个简易的变化矩阵)相乘(一个旋转、一个伸缩、一个旋转),然而事实上,任何一个复杂的变化都可以转变为这种分解的形式(在这里我们用二维矩阵来表示,为的是得到一个可视化的变化)我们称之为SVD奇异值分解。
你也看到了, Σ \Sigma Σ是一个特殊的对角矩阵,而且通过刚刚可视化的转化,你知道 Σ \Sigma Σ内对角线上面的数字代表了对矩阵的变化大小程度(对拉伸变化的大小程度)也就是说 Σ \Sigma Σ内对角元素更像是代表了一种权重,比如我们将x轴拉伸为原来的6.71倍,这个变化看起来相较于将y轴变为原来的2.24倍大一点,说明我们在x轴上面进行的操作特征更接近于与原矩阵进行的操作,实际上 Σ \Sigma Σ内对角线的元素从大到小排列,我们通常只需要取出前面的几个特征值就能很好的将原图像的图像表示出来,这同时也与图像压缩相关,因为计算机内的图像实际上是数以百万计的矩阵像素形式。
由于 Σ \Sigma Σ是一个对角矩阵,即对角线上面存在元素,而其他位置的元素为0,根据矩阵相乘的原理,我们可以将 Σ \Sigma Σ内的对角元素提取出来,这个公式就转换成了
其中 σ 1 \sigma1 σ1代表 Σ \Sigma Σ中的第一个对角元素,u1代表U矩阵中的第一行,v1转置代表V矩阵中的第一列
刚刚那个矩阵由于奇异值都相差不是很大,所以说“ Σ \Sigma Σ内的对角元素更多代表一种和原图像相似的一个权重”展示的可能不是那么明显。
如果我们将x轴延申80倍,然后y轴转换为原图的2倍看一看
图像就变为了这样的:
最终的结果:
该图像对应原图的的变换矩阵为:
B = ∣ 17.88854 17.88854 53.66566 53.66565 ∣ B = \left|\begin{matrix} 17.88854 & 17.88854 \\ 53.66566 & 53.66565 \end{matrix} \right| B=∣∣∣∣17.8885453.6656617.8885453.66565∣∣∣∣
这样看来,似乎对y轴的操作看起来微乎其微,因为这些不同颜色的点已经几近贴合为一条线,那如果我们直接舍去对y轴的操作,
图像变为了这样:
我们来看看该图像对应的变换矩阵为:
A = ∣ 19.23018461 16.54690303 53.21841786 54.11284506 ∣ A = \left|\begin{matrix} 19.23018461 & 16.54690303 \\ 53.21841786 & 54.11284506 \end{matrix} \right| A=∣∣∣∣19.2301846153.2184178616.5469030354.11284506∣∣∣∣
B和A极其相似!
也就是说我们现在只保留最大的那个特征值,相乘后的结果与原图差别并不是很大,即该矩阵结果与原来的矩阵相差不是很大,很好的拟合了原矩阵的图像。
所以,现在你应该能够更能理解奇异值的大小更多的代表一种相似权重这个意思吧。
如何用Mathematica 或者 Python中的Numpy计算SVD?
待更