欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

机器学习实战——PCA实现图像压缩

程序员文章站 2024-02-03 21:17:34
...

1.主成分分析概述

主成分分析是最为简单粗暴的一种数据降维方式,顾名思义就是找到数据中最为主要的方面,用这些方面来替代原始数据。具体来说,假设我们有一个具有n维特征的数据集,共有m个样本点,我们希望将这m个样本的特征维度从n维降到b维,希望b维数据尽可能的替代原始数据集。
其中最为重要的因素就是如何保证减少维度后数据损失尽可能的小
如下图所示,我们试图将二维数据降到一维,图中列出两个维度PC1和PC2,显然PC1维度可以更加好的代表原始数据,因为把数据投影到PC1后,它们之间的方差最大,即PC1这个方向上包含了更多的信息量。这个PC1就是第一主成分,与PC1正交的PC2包含较少的信息量,为第二主成分,如果第一主成分包含的信息量足够大,那么光用第一主成分就可以很好的表示原始数据。
机器学习实战——PCA实现图像压缩
以此类推,PCA算法就是希望找到原始数据中最重要的维度,然后把原始数据投影到这些维度上,即把高维数据映射到低维度空间表示,由于映射后新生成的样本点之间方差最大,样本间的差异也最大限度的保存下来。

算法过程

  1. 对变量进行z-score标准化操作,消除变量间不同量纲造成的影响
  2. 计算数据的协方差矩阵
  3. 计算所得协方差的特征值(即主成分方差)与特征向量
  4. 将所得的特征值从大到小排序,并选择最大的k个特征值,即前k个主成分对应的特征向量。具体k如何选择,需要计算前k个特征值的累计贡献率来决定
  5. 将原始数据投影到所选取的k个特征向量组成的低维度空间,转化为新样本。通过原始数据乘以这k个特征向量即可得到

函数原型及参数说明

sklearn.decomposition.PCA(n_components=None, copy=True, whiten=False)

参数说明:

n_components:

意义:PCA算法中所要保留的主成分个数n,也即保留下来的特征个数n
类型:int 或者 string,缺省时默认为None,所有成分被保留。
          赋值为int,比如n_components=1,将把原始数据降到一个维度。
          赋值为string,比如n_components='mle',将自动选取特征个数n,使得满足所要求的方差百分比。

copy:

类型:bool,True或者False,缺省时默认为True。

意义:表示是否在运行算法时,将原始训练数据复制一份。
若为True,则运行PCA算法后,原始训练数据的值不会有任何改变,因为是在原始数据的副本上进行运算;
若为False,则运行PCA算法后,原始训练数据的值会改,因为是在原始数据上进行降维计算。

whiten:

类型:bool,缺省时默认为False

意义:白化,使得每个特征具有相同的方差。

2、PCA对象的属性

components_ :返回具有最大方差的成分。
explained_variance_ratio_:返回 所保留的n个成分各自的方差百分比。
n_components_:返回所保留的成分个数n。
mean_:
noise_variance_:

3、PCA对象的方法

fit(X,y=None)

fit()可以说是scikit-learn中通用的方法,每个需要训练的算法都会有fit()方法,它其实就是算法中的“训练”这一步骤。因为PCA是无监督学习算法,此处y自然等于None。

fit(X),表示用数据X来训练PCA模型。

函数返回值:调用fit方法的对象本身。比如pca.fit(X),表示用X对pca这个对象进行训练。

fit_transform(X)

用X来训练PCA模型,同时返回降维后的数据。
newX=pca.fit_transform(X),newX就是降维后的数据。

inverse_transform()

将降维后的数据转换成原始数据,X=pca.inverse_transform(newX)

transform(X)

将数据X转换成降维后的数据。当模型训练好后,对于新输入的数据,都可以用transform方法来降维。

此外,还有get_covariance()、get_precision()、get_params(deep=True)、score(X, y=None)等方法,以后用到再补充吧。

示例:利用PCA进行图像压缩

采用的数据集是MNIST手写数据集,选择划分后的训练集样本作为数据集,共有60000个手写数据,每个样本的形状为(28,28)。

import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
import tensorflow as tf

# 导入数据集
data = tf.keras.datasets.mnist
(x_train, y_train), (_,_) = data.load_data()
x_trainnew = x_train.reshape(60000, 784)
pca = PCA()
pca.fit(x_trainnew)
# 显示数据集的64个数据
plt.figure()
fig, ax = plt.subplots(8, 8, figsize=(6, 6), dpi=600)  # ax是一个(8,8)的数组
for i, axi in enumerate(ax.flat):  # enumerate()函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。i是数据下标,axi是数据
    axi.imshow(x_train[i], cmap='binary')
    axi.set(xticks=[], yticks=[])  # 取消子图X,Y轴的刻度
# 计算各个N下的累计贡献率,找出累计贡献率大于90%时对应的K值
cumsum = np.cumsum(pca.explained_variance_ratio_)
d = np.argmax(cumsum >= 0.9)
# 进行数据降维,并且根据降维后的数据生成原始数据
xr = []
for n in [5, 30, d]:
    pca = PCA(n_components=n)
    x_reduced = pca.fit_transform(x_trainnew)
    x_recovered = pca.inverse_transform(x_reduced)
    xr.append(x_recovered)
instances=[]
for i in range(5):
    # 在列表instances中增加训练集中标签为i的第一个数据
    instances.append(x_train[y_train == i][0])
    print(x_train[y_train == i].shape)
    for j in range(3):
        # 将降维后的训练集中标标签为i的第一个数据增加到instances中,xr也是列表,包含三个数组(即三个降维后的训练集)
        instances.append(xr[j][y_train == i][0])
        print(xr[j][y_train == i][0])

images = [instance.reshape(28, 28) for instance in instances]
plt.figure()
fix, ax = plt.subplots(5, 4, dpi=600)
for i, axi in enumerate(ax.flat):
    axi.imshow(images[i], cmap='binary')
    axi.set(xticks=[], yticks=[])
plt.show()

显示的原始数据集:
机器学习实战——PCA实现图像压缩

压缩后的数据,分为为原始数据,主成分数量为5,30,86时对应的压缩后的数据:可以看出当主成分数量为86时,压缩后的图片比较清晰。
机器学习实战——PCA实现图像压缩