机器学习之PCA实战(图像压缩还原)

PCA是机器学习的入门算法之一,涉及到线性代数中矩阵的相关知识,基础理论比较多,主要涉及到奇异值分解。基础理论这里不多说了,大家可以去以下博客学习,用例子说明是最轻松的理解过程。
主成分分析原理详解https://blog.csdn.net/program_developer/article/details/80632779
这篇文章从基向量变换的方向说明降维,更加直白理解pca:https://blog.csdn.net/shizhixin/article/details/51181379
如果你看完了上面的pca基础理论,并且学习了一些小基础,想找个练手的例子,那么来这里看就对了。
第一个例子,自己写pca函数实现图像的降维。这里是对图像的列进行降维,即宽度上进行压缩。
网上找的喵主子是这样的:在这里插入图片描述
首先我们用载入函数将它转换成灰度图像

def loadImage(path):
    img = Image.open(path)
    # 将图像转换成灰度图
    img = img.convert("L")
    # 图像的大小在size中是(宽,高)
    # 所以width取size的第一个值,height取第二个
    width = img.size[0]
    height = img.size[1]
    data = img.getdata()
    # 为了避免溢出,这里对数据进行一个缩放,缩小100倍
    data = np.array(data).reshape(height,width)/100
    # 查看原图的话,需要还原数据
    new_im = Image.fromarray(data*100)
    new_im.show()
    return data

转换之后是这样的
在这里插入图片描述
接着我们定义我们的pca函数,如果你看了上面的推荐的博客的话,你应该知道这里对列进行降维应该用到哪个矩阵,在奇异值分解中,对任意矩阵A,有 A = USVT ,其中U对应是在行即高度上进行降维,V是对应在列上降维的正定矩阵。要求得V,采用方阵的特征值分解,构造ATA(AT表示A的转置)= VS2VT , 类似的求U, 有 AAT= US2UT。详情请看上面推荐的博客内容。所以注意到pca函数中这里的代码

这里用的矩阵的转置乘矩阵,对应求V
matrix_ = np.dot(np.transpose(normal_data),normal_data)
def pca(data,k):
    ""
    :param data:  图像数据
    :param k: 保留前k个主成分
    :return: 
    """
    n_samples,n_features = data.shape
    # 求均值
    mean = np.array([np.mean(data[:,i]) for i in range(n_features)])
    # 去中心化
    normal_data = data - mean
    # 得到协方差矩阵
    matrix_ = np.dot(np.transpose(normal_data),normal_data)
    # 有时会出现复数特征值,导致无法继续计算,这里用了不同的图像,有时候会出现复数特征,但是经过
    sklearn中的pca处理同样图像可以得到结果,如果你知道,请留言告诉我。
    我能知道的是协方差矩阵肯定是实对称矩阵的
    eig_val,eig_vec = np.linalg.eig(matrix_)
   # print(matrix_.shape)
   #  print(eig_val)
    # 第一种求前k个向量
   #  eig_pairs = [(np.abs(eig_val[i]),eig_vec[:,i]) for i in range(n_features)]
   #  eig_pairs.sort(reverse=True)
   #  feature = np.array([ele[1] for ele in eig_pairs[:k]])
   #  new_data = np.dot(normal_data,np.transpose(feature))
    # 第二种求前k个向量
    eigIndex = np.argsort(eig_val)
    eigVecIndex = eigIndex[:-(k+1):-1]
    feature = eig_vec[:,eigVecIndex]
    new_data = np.dot(normal_data,feature)
    # 将降维后的数据映射回原空间
    rec_data = np.dot(new_data,np.transpose(feature))+ mean
    # print(rec_data)
    # 压缩后的数据也需要乘100还原成RGB值的范围
    newImage = Image.fromarray(rec_data*100)
    newImage.show()
    return rec_data

当我们保留前10个主成分时,得到如下图像

在这里插入图片描述
虽然得到了降维后的图像,但是怎么知道我们降维后的图像保留了多小信息呢?根据pca的误差计算方式,编写函数如下

def error(data,recdata):
    sum1 = 0
    sum2 = 0
    # 计算两幅图像之间的差值矩阵
    D_value = data - recdata
    # 计算两幅图像之间的误差率,即信息丢失率
    for i in range(data.shape[0]):
        sum1 += np.dot(data[i],data[i])
        sum2 += np.dot(D_value[i], D_value[i])
    error = sum2/sum1
    print(sum2, sum1, error)

当k=10时,我们得到这个值,最后一个数值是误差比,也就是说,我们降维后的数据保留了99%的原始信息,当k=20时,这个数大概是0.005.你们可以自己运行一下。

23076.032446296413   2261348.8400000017  0.010204543429175834

通过自己编写pca的实现代码可以加深印象,但是python的强大在于各种第三方库,sklearn是机器学习最重要的一个库,里面包含了pca函数,我们试着调用一下

import numpy as np
from sklearn.decomposition import PCA

import numpy as np
from PIL import Image

def loadImage(path):...

def error(data, recdata):...

if __name__ == '__main__':
    data = loadImage("timg.jpg")
    pca = PCA(n_components=10).fit(data)
    # 降维
    x_new = pca.transform(data)
    # 还原降维后的数据到原空间
    recdata = pca.inverse_transform(x_new)
    # 计算误差
    error(data, recdata)
    # 还原降维后的数据
    newImg = Image.fromarray(recdata*100)
    newImg.show()
    # error(data, recdata)

得到的值课我们自己写的差不多

23076.032452099163   2261348.8400000017   0.010204543431741892

好了,例子就到这里了。欢迎留言反馈

参考文章
【1】主成分分析(PCA)原理详解
【2】机器学习算法笔记系列之深入理解主成分分析PCA-原理篇
【3】【机器学习】Sklearn库主成分分析PCA降维的运用实战

  • 14
    点赞
  • 106
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值