人工稚能之sklearn数据降维

人工稚能之sklearn数据降维

机器学习模型拟合的输入数据往往是多维数据,这个维度可能会非常庞大。比如统计一篇文章中的单词频率,就可以把文章看成单词的向量。而单词的数量又是非常庞大,每个单词都是一个维度,这样大维度的数据在拟合时会非常耗费计算资源,也就是说出现了维度灾难。

遇到维度灾难,我们一般都会使用降维算法来压缩数据量,以减少模型训练消耗的存储资源和计算资源。

对于维度大的数据,维度之间往往会存在相关性,这种相关性导致数据产生了冗余。比如两条信息,一条说这个人是个男的,第二条说这个人不是女的,那这两条信息就是相关的,就可以灭掉一条。降维的作用就是消除这种冗余信息。降维还可以用来剔去信息量小的信息,来实现信息的压缩。比如图片就可以使用降维算法来实现压缩。

一种比较常用的降维算法是PCA算法【主成分分析】,它的原理是数学上的SVD矩阵分解算法。具体的公式这里不能细说,因为我也不想吓跑一半读者。

打个比方说一张女人图片,我们如何判定这个女人是不是美女呢。我们会看比较关键的一些特征,比如说脸好不好看,胸好不好看,屁股怎么样,腿怎么样,至于衣服上是某个花纹还是手臂上有一个小痔还是,这些特征我们都是不关心的,就可以过滤掉。我们关心的是主成分,也就是对结果贡献系数较大的特征。SVD算法的作用就是来告诉你哪些特征是重要的,有多重要,哪些特征是不重要的,是可以忽略的。

接下来我们使用sklearn提供的TruncatedSVD模块来对美女图片进行压缩。

首先我们使用matplotlib显示一张美女png图片,png图片的格式非常简单,每一个像素有三个维度的颜色值RGB,整个图片就是一个「height x width x 3」维的矩阵。

我们先使用matplotlib显示一下美女图片

# -*- coding: utf-8 -*-

import matplotlib.pyplot as plt
import matplotlib.image as img

# 读入图片矩阵600*900*3
img_matrix = img.imread('beauty.png')

plt.imshow(img_matrix)
plt.show()

接下来我们进行SVD转换,先将图像RGB三个通道数据分别转换到特征空间,再从特征空间还原会通道数据,然后将三个处理后的通道数据合并成图像数据显示出来,对比和原始图像的差异。

# -*- coding: utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as img
from sklearn.decomposition import TruncatedSVD

# 加载png数据矩阵
img_array = img.imread('beauty.png')

shape = img_array.shape
# 高度、宽度、RGB通道数=3
height, width, channels = shape[0], shape[1], shape[2]

# 转换成numpy array
img_matrix = np.array(img_array)

# 存储RGB三个通道转换后的数据
planes = []

# RGB三个通道分别处理
for idx in range(channels):
    # 提取通道
    plane = img_matrix[:, :, idx]
    # 转成二维矩阵
    plane = np.reshape(plane, (height, width))
    # 保留10个主成分
    svd = TruncatedSVD(n_components=10)
    # 拟合数据,进行矩阵分解,生成特征空间,剔去无关紧要的成分
    svd.fit(plane)
    # 将输入数据转换到特征空间
    new_plane = svd.transform(plane)
    # 再将特征空间的数据转换会数据空间
    plane = svd.inverse_transform(new_plane)
    # 存起来
    planes.append(plane)

# 合并三个通道平面数据
img_matrix = np.dstack(planes)
# 显示处理后的图像
plt.imshow(img_matrix)

plt.show()

保留10个主成分效果图,马赛克有点严重,能看得出轮廓,只是看不清人脸了

保留50个主成分,有点像老式彩电的效果,差不多能辨识出是个美女了

保留100个主成分,基本很清晰了

那这个图像在不同的主成分数量下的压缩比例大概是多少呢?

这个例子中图像的大小是600 x 900,压缩后变成了两个矩阵,一个矩阵是600 x n_components,另一个矩阵是ncomponents x 900,还有其它一些微量的变量信息。那这个压缩比大约是 n_components x 15 / 5400,那么当保留50个主成分时,压缩率约为14%。当保留100个主成分时,压缩率约为28%。

阅读相关文章,关注公众号【码洞】