【2019-11-29】土人说土话-机器学习基础-PCA-SVD
土人说土话系列1-通俗理解-没有公式(建议配合其他文章一起食用)
机器学习-PCA-SVD 如何用土话理解
主要成分分析法是降维比较常用的算法
那么什么是 主要成分分析法(SVD方法) 呢?
先说结论(SVD):
1.第一步旋转矩阵到另外一个坐标系
2.在另外那个坐标系进行放缩(可以放弃放缩不明显的维度,关键)
3.再转回来
无标题.png
完毕!!!
什么?没听懂?
解释一下:
网上常见的图片,原理来的矩阵= 旋转到特征特征向量的位置,放缩,然后再转回来:
![](https://img.haomeiwen.com/i16442181/686e56c3382acf6f.jpg)
旋转
矩阵在线性代数里面代表的是旋转放缩
但是有的放缩会让原来的矩阵的夹角发生变化,例如:
![](https://img.haomeiwen.com/i16442181/ff888667a282d41c.jpg)
那么问题来了,有没有可以做到不会改变夹角的呢?
如果按坐标系的进行放缩,那么是不是就不会改变夹角了呢
扩展一下,就变成找正交的坐标系,也就是正交矩阵了
![](https://img.haomeiwen.com/i16442181/ac9814fd4b8250d8.jpg)
旋转到这变应该是没什么问题了吧
如果还有问题:线性代数的本质 - 系列合集 看一下大神视频
放缩
SVD 的s矩阵是个对角矩阵
|5 0 0|
|0 3 0|
|0 0 1|
什么意思呢,矩阵乘完后就是说对于每个向量都进行了放缩
![](https://img.haomeiwen.com/i16442181/d3391f75694ca766.jpg)
有些放缩是不明显(向量在基的投影很短),这时候就可以把这些放缩给省略掉,达到较少计算的目的
import numpy as np
import matplotlib.pyplot as plt
import os
import imageio
m=np.array(
[[60, 40, 65],
[61, 82, 78],
[69, 95, 75],
[70, 77, 81],
[64, 47, 53]]
)
U, S, V = np.linalg.svd(m)
print(U)
print(S*np.eye(3))
print(V)
#旋转
[[-0.35672442 -0.66281097 0.36273147 -0.3393367 -0.43209466]
[-0.48152119 0.30125544 0.41771491 -0.38994684 0.59231598]
[-0.52005108 0.5114878 -0.38602628 -0.18607474 -0.53318571]
[-0.49538551 -0.02730932 0.23701757 0.83524415 -0.00610569]
[-0.35358889 -0.45558886 -0.69910408 -0.02314023 0.42205651]]
#放缩
[[266.12913135 0. 0. ]
[ 0. 29.89261007 0. ]
[ 0. 0. 12.27669792]]
#旋转
[[-0.54096467 -0.59340339 -0.59601145]
[-0.5743479 0.7783313 -0.2536235 ]
[-0.61439541 -0.20511657 0.76186972]]
SVD本质就是用“简单的矩阵”去把“复杂的矩阵”给线性表示出来,而这些“简单的钜阵”,恰好又是其对应特征向量的张量积(或者说外积其自身)的运算结果。
SVD与离散傅里叶变换,SVD与泰勒公式 非常相似,可以慢慢体会一下过程
下面我们用直观的方式展示出来:
针对不同的放缩的省略来做的
代码中的r指的是 取r个维度来计算
取不同的对应的值生成的图片如下
原图:
![](https://img.haomeiwen.com/i16442181/c44e286dcaf606d5.jpg)
代码
import numpy as np
import matplotlib.pyplot as plt
import os
import imageio
im = plt.imread('Hydrangeas.jpg')
if not os.path.exists('svd'):
os.mkdir("svd")
for r in range(10, 122 ,10):
svd_image = []
for ch in range(3):
im_ch = im[:, :, ch]
U, D, V = np.linalg.svd(im_ch)
imx = np.matmul(np.matmul(U[:, :r], np.diag(D[:r])), V[:r, :])
for k in imx:
for m in range(0,k.shape[0]):
k[m]=max(min(255,k[m]),0)
svd_image.append(imx.astype('uint8'))
img = np.stack((svd_image[0], svd_image[1], svd_image[2]), 2)
imageio.imwrite('svd/%02d.jpg' % r,img)
![](https://img.haomeiwen.com/i16442181/4e841abad9305db5.jpg)
![](https://img.haomeiwen.com/i16442181/3e9dab0562becc8a.jpg)
![](https://img.haomeiwen.com/i16442181/2fb6afede16543b8.jpg)
![](https://img.haomeiwen.com/i16442181/334eb09b0c005d1e.jpg)
![](https://img.haomeiwen.com/i16442181/d091f6ede7b46d2b.jpg)
![](https://img.haomeiwen.com/i16442181/3bb4078af9a1da4d.jpg)
![](https://img.haomeiwen.com/i16442181/4ed9e4144ad6aa4d.jpg)
![](https://img.haomeiwen.com/i16442181/b7d84c5487c0e531.jpg)
![](https://img.haomeiwen.com/i16442181/946bb3336deb361a.jpg)
![](https://img.haomeiwen.com/i16442181/3a9d7c07eeaf726f.jpg)
![](https://img.haomeiwen.com/i16442181/eef4580a8ad37e7a.jpg)
![](https://img.haomeiwen.com/i16442181/41393b1e264dfcb5.jpg)
直观理解PCA
其实就是不操作第三步骤(转回来)
图片片的颜色代表的是放缩的程度,亮度越高越数值越高,越黑代表越没用
如果我们放弃后面黑的其实对图片也没多大效果影响,所以上面的图片取到120左右的时候跟原来图片其实没多大区别(在120列往后其实颜色基本上是黑的了)
如果不旋转回去,那就是PCA降维的结果了
你问我怎么降维?取前面不是黑色的就完事了
import numpy as np
import matplotlib.pyplot as plt
import os
import imageio
im = plt.imread('Hydrangeas.jpg')
if not os.path.exists('svd'):
os.mkdir("svd")
r=648
svd_image = []
for ch in range(3):
im_ch = im[:, :, ch]
U, D, V = np.linalg.svd(im_ch)
imx = np.matmul(np.matmul(U[:, :r], np.diag(D[:r])), V[:r, :])
imx =np.matmul(U[:, :r], np.diag(D[:r]))#加了这行 变成降维度操作
for k in imx:
for m in range(0,k.shape[0]):
k[m]=max(min(255,k[m]),0)
svd_image.append(imx.astype('uint8'))
img = np.stack((svd_image[0], svd_image[1], svd_image[2]), 2)
imageio.imwrite('svd/pca.jpg' ,img)
![](https://img.haomeiwen.com/i16442181/6e94650ce9685723.jpg)
如果我们不要前面10个特征向量(中间矩阵的10个参数)会怎么样呢?
如图:图片虽然有细节,但是失去了大部分的颜色,可以说图片失去了主要成分!
反过来说,后面的特征向量虽然不是主要成分,但是也保留了大部分细节,有时候细节才是关键的东西
并不是无脑降维就可以了
![](https://img.haomeiwen.com/i16442181/f4be9ec65e6edbf4.jpg)
反过来说,如果特征值都是一样的,那么就是表达细节了(噪音放大器)
![](https://img.haomeiwen.com/i16442181/2e40f2e068c247e9.jpg)
跟下面这个东西很像:
可以吧一个个的指针想想成这的向量,向量越多拟合的越好
12分钟的傅立叶级数动画