【Python】使用sklearn PCA对人脸数据降维

1. PCA

PCA(Principal Component Analysis),即主成分分析方法,是一种使用最广泛的数据降维算法。PCA的主要思想是将n维特征映射到k维上,这k维是全新的正交特征也被称为主成分,是在原有n维特征的基础上重新构造出来的k维特征。

1.1 PCA原理

PCA算法步骤是从原始的空间中顺序地找一组相互正交的坐标轴,其中第一个新坐标轴选择是原始数据中方差最大的方向,第二个新坐标轴选取是与第一个坐标轴正交的平面中使得方差最大的,第三个轴是与第1,2个轴正交的平面中方差最大的。以此类推,得到n个这样的坐标轴。通过这种方式获得的新的坐标轴,大部分方差都包含在前面k个坐标轴中,后面的坐标轴所含的方差几乎为0。于是,我们可以忽略余下的坐标轴,只保留前面k个含有绝大部分方差的坐标轴。事实上,这相当于只保留包含绝大部分方差的维度特征,而忽略包含方差几乎为0的特征维度,从而实现对数据特征的降维处理。

1.2 sklearn PCA使用方法

这里介绍一下sklearn中的PCA使用方法。
PCA的一般步骤是:先对原始数据零均值化,然后求协方差矩阵,接着对协方差矩阵求特征向量和特征值,这些特征向量组成了新的特征空间。

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

意义:PCA算法中所要保留的主成分个数n,也即保留下来的特征个数n
类型:

  • int,指定将原始数据降到的维度。比如n_components=2,将原始数据降到二维
  • float,指定主成分的方差和所占的最小比例阈值,让PCA类自己去根据样本特征方差来决定降维到的维度数,此时n_components是一个(0, 1)之间的数
  • string,比如n_components=‘mle’,将自动选取特征个数n,使得满足所要求的方差百分比。
  • 缺省时默认为None,所有成分被保留。

copy:
意义:表示是否在运行算法时,将原始训练数据复制一份。若为True,则运行PCA算法后,原始训练数据的值不 会有任何改变,因为是在原始数据的副本上进行运算;若为False,则运行PCA算法后,原始训练数据的 值会改,因为是在原始数据上进行降维计算。
类型:bool,True或者False,缺省时默认为True。
whiten:
类型:bool,缺省时默认为False
意义:判断是否进行白化。所谓白化,就是对降维后的数据的每个特征进行归一化,让方差都为1.对于PCA降维本身来说,一般不需要白化。如果你PCA降维后有后续的数据处理动作,可以考虑白化。默认值是False,即不进行白化。

PCA常用属性:

  • components_ :返回具有最大方差的成分
  • explained_variance_ratio_:返回所保留的n个成分各自的方差百分比
  • n_components_:返回所保留的成分个数n
  • mean_: 原始数据中每个特征的均值
  • n_features_ : 原始数据中特征的数量
  • noise_variance_:噪声方差

PCA常用方法:

  1. fit(X,y=None):fit(X),表示用数据X来训练PCA模型。
    函数返回值:调用fit方法的对象本身。比如pca.fit(X),表示用X对pca这个对象进行训练。
    拓展:fit()可以说是scikit-learn中通用的方法,每个需要训练的算法都会有fit()方法,它其实就是算法中的“训练”这一步骤。因为PCA是无监督学习算法,此处y自然等于None。
  2. fit_transform(X):用X来训练PCA模型,同时返回降维后的数据。newX=pca.fit_transform(X),newX就是降维后的数据。
  3. inverse_transform():将降维后的数据转换成原始数据,X=pca.inverse_transform(newX)。
  4. transform(X):将数据X转换成降维后的数据。当模型训练好后,对于新输入的数据,都可以用transform方法来降维。

2. 人脸数据降维

这里使用了Orl_faces数据集。ORL人脸数据集共包含40个不同人的400张图像,是在1992年4月至1994年4月期间由英国剑桥的Olivetti研究实验室创建。
此数据集下包含40个目录,每个目录下有10张图像,每个目录表示一个不同的人。所有的图像是以PGM格式存储,灰度图,图像大小宽度为92,高度为112。对每一个目录下的图像,这些图像是在不同的时间、不同的光照、不同的面部表情(睁眼/闭眼,微笑/不微笑)和面部细节(戴眼镜/不戴眼镜)环境下采集的。所有的图像是在较暗的均匀背景下拍摄的,拍摄的是正脸(有些带有略微的侧偏)。

2.1 读取图片

这里读取所有图片,同时将每张图片拉伸为一维数组方便后续使用PCA进行降维。返回一个包含了Orl_faces数据集所有人脸数据的的二维数组,数组大小为(400, 10304)

import os
import cv2
import matplotlib.pyplot as plt
import numpy as np
from sklearn.decomposition import PCA


# 为方便显示图片,采用opencv读取、处理图片,用matplotlib显示图片
# 读取所有图片
root = 'orl_faces'  # 根目录
listdir = os.listdir(root)
listdir.sort(key=lambda s: int(s[1:]))  # listdir读取的目录列表无序,按数字大小进行排序

data = []

# 读取所有图片返回一个(m, n)数组,m为图片数量,n为图片一维size
for i in listdir:
    path = os.path.join(root, i)
    tmp_dir = os.listdir(path)
    tmp_dir.sort(key=lambda s: int(s.split('.')[0]))  # 按图片名称数字大小进行排序
    for j in tmp_dir:
        img_path = os.path.join(path, j)
        img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)
        if img is None:
            print('Failed to load image.')
        else:
            # print(img.shape)
            img = img.reshape(1, -1)
            data.append(img)
# 压缩后的全部图片 (400, 112*92)
data = np.array(data).reshape(len(data), -1)


# 展示其中n张
def show_img(figure_num, n, img_set):
    fig = plt.figure(figure_num)
    for i in range(n):
        tmp_img = img_set[i * 10].reshape(112, 92)
        plt.subplot(int(np.ceil(n/5)), 5, i + 1)
        plt.imshow(tmp_img, cmap='gray')
    plt.show()


show_img(1, 20, data)

这里显示了前20个人的第一张图像。
orl_faces部分人脸数据

2.2 使用PCA进行降维

这里使用PCA对人脸降维,n_components参数设置为0.9,即主成分方差占原始数据的90%。降维后

pca = PCA(n_components=0.9)
new_data = pca.fit_transform(data)

print(data.shape)
print(new_data.shape)

data_inverse = pca.inverse_transform(new_data)

show_img(1, 20, data_inverse)
(400, 10304)
(400, 100)

可以看到原始数据维度从10304降到了100,但将降维后的数据映射回原始数据后,仍能较为清晰地分辨出人脸,说明前100个主成分特征保留了大部分数据信息。

在这里插入图片描述

参考文献

[1] https://blog.csdn.net/qq_20135597/article/details/95247381
[2] https://blog.csdn.net/program_developer/article/details/80632779

  • 9
    点赞
  • 108
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值