基于Python查看SVD压缩图片的效果

基于Python查看SVD压缩图片的效果

标签: Python 机器学习


机器学习中常用的降维方法是主成分分析(PCA),而主成分分析常用奇异值分解(SVD)。那么SVD的效果到底如何呢?SVD常用来进行图像的压缩,我们就来实验一下。

用到的包:

  • PIL
  • numpy

实验

载入一张彩色图片,分别对其RGB通道进行SVD分解。奇异值的占比公式为:
∑ i = 1 K σ i i ∑ i = 1 n σ i i \dfrac{\sum_{i=1}^K{\sigma_{ii}}}{\sum_{i=1}^n{\sigma_{ii}}} i=1nσiii=1Kσii
分别取和占比为[0.1, 0.2, …, 0.9]的前K个奇异值,进行图片的恢复操作。

from PIL import Image
import numpy as np

def rebuild_img(u, sigma, v, p): #p表示奇异值的百分比
    print p
    m = len(u)
    n = len(v)
    a = np.zeros((m, n))
    
    count = (int)(sum(sigma))
    curSum = 0
    k = 0
    while curSum <= count * p:
        uk = u[:, k].reshape(m, 1)
        vk = v[k].reshape(1, n)
        a += sigma[k] * np.dot(uk, vk)
        curSum += sigma[k]
        k += 1
    print 'k:',k
    a[a < 0] = 0
    a[a > 255] = 255
    #按照最近距离取整数,并设置参数类型为uint8
    return np.rint(a).astype("uint8")
    
if __name__ == '__main__':
    img = Image.open('test.jpg', 'r')
    a = np.array(img)
    
    for p in np.arange(0.1, 1, 0.1):
        u, sigma, v = np.linalg.svd(a[:, :, 0])
        R = rebuild_img(u, sigma, v, p)
        
        u, sigma, v = np.linalg.svd(a[:, :, 1])
        G = rebuild_img(u, sigma, v, p)
        
        u, sigma, v = np.linalg.svd(a[:, :, 2])
        B = rebuild_img(u, sigma, v, p)
        
        I = np.stack((R, G, B), 2)
        #保存图片在img文件夹下
        Image.fromarray(I).save("img\\svd_" + str(p * 100) + ".jpg")

效果

一共10张图,从上到下奇异值和占比为[0.1, 0.2, …, 0.9, 1.0],奇异值和占比[0.7, 0.8, 0.9]的恢复图像还是比较清楚,然而对应的奇异值个数却非常少,如下表所示:
|奇异值和占比|奇异值个数|奇异值个数占比|
|:|||
|0.7|45|0.10|
|0.8|73|0.16|
|0.9|149|0.33|
|1.0|450|1.00|

小结

  • 奇异值分解能够有效的降低数据的维数,以本文的图片为例,从450维降到149维后,还保留了90%的信息
  • 虽然奇异值分解很有效,但是不能滥用,一般情况下要求降维后信息的损失度不能超过5%,甚至是1%
  • Ng的视频中提到常见的错误使用降维的情况,在这里也贴出来:
    • 使用降维解决过拟合问题
    • 不论什么情况,先用降维处理一下数据,即把降维当做模型训练的必须步骤

你可能感兴趣的:(Python,机器学习,python,压缩,机器学习)