PCA和NMF

主成分分析(Principal Component Analysis,PCA)是最常用的一种降维方法,通常用于高维数据集的探索与可视化,还可以用作数据压缩和预处理等。PCA可以把具有相关性的高维变量合成为线性无关的低维变量,称为主成分。主成分能够尽可能保留原始数据的信息
详细介绍可以参考: 《主成分分析(PCA)原理详解(转载)》

一、数据降维

以 sklearn.datasets 的 load_wine 酒数据为例,将数据特征降维到2维,并可视化降维后的数据集,还给出原始特征与PCA主成分之间的关系。
注释1:

sklearn.decomposition.PCA

函数原型:sklearn.decomposition.PCA(self, n_components=None, copy=True, whiten=False, svd_solver='auto', tol=0.0, iterated_power='auto', random_state=None)

参数解释
n_components: 这个参数可以帮我们指定希望PCA降维后的特征维度数目。
   1.最常用的做法是直接指定降维到的维度数目,此时n_components是一个大于等于1的整数;即如果希望降维后保留原特征90%的信息,那么可以设置该值为0.9
   2.也可以指定主成分的方差和所占的最小比例阈值,让PCA类自己去根据样本特征方差来决定降维到的维度数,此时n_components是一个(0,1]之间的数;
   3.还可以将参数设置为'mle'(极大似然估计), 此时PCA类会用MLE算法根据特征的方差分布情况自己去选择一定数量的主成分特征来降维;
   4.也可以用默认值,即不输入n_components,此时n_components=min(样本数,特征数)。
copy: 表示是否在运行算法时,将原始数据复制一份。默认为True,则运行PCA算法后,原始数据的值不会有任何改变。因为是在原始数据的副本上进行运算的。
whiten:白化。所谓白化,就是对降维后的数据的每个特征进行标准化,让方差都为1。对于PCA降维本身来说,一般不需要白化。如果你PCA降维后有后续的数据处理动作,可以考虑白化。默认值是False,即不进行白化。
svd_solver:即指定奇异值分解SVD的方法,由于特征分解是奇异值分解SVD的一个特例,一般的PCA库都是基于SVD实现的。有4个可以选择的值:{‘auto’, ‘full’, ‘arpack’, ‘randomized’}。
   1.'randomized' 一般适用于数据量大,数据维度多同时主成分数目比例又较低的PCA降维,它使用了一些加快SVD的随机算法。
   2.'full' 则是传统意义上的SVD,使用了scipy库对应的实现。
   3.'arpack' 和randomized的适用场景类似,区别是randomized使用的是scikit-learn自己的SVD实现,而arpack直接使用了scipy库的sparse SVD实现。当svd_solve设置为'arpack'时,保留的成分必须少于特征数,即不能保留所有成分。
   4.默认是'auto',即PCA类会自己去在前面讲到的三种算法里面去权衡,选择一个合适的SVD算法来降维。一般来说,使用默认值就够了。
注意:当设置 n_components == 'mle'时,需要和参数svd_solver一起使用,且svd_solver需要选择 'full' 参数;即pca = PCA(n_components = 'mle',svd_solver='full');同时要保证输入数据的样本数多于特征数才可执行成功。
  另外,有两个PCA类的成员值得关注。第一个是explained_variance_,它代表降维后的各主成分的方差值,方差值越大,则说明越是重要的主成分。第二个是explained_variance_ratio_,它代表降维后的各主成分的方差值占总方差值的比例,这个比例越大,则越是重要的主成分。

注释2:

matplotlib.pyplot.matshow

函数原型:matshow(A, fignum=None, **kw)
这是一个绘制矩阵的函数:matplotlib.pyplot.matshow(A, fignum=None, **kwargs)
A是绘制的矩阵,一个矩阵元素对应一个图像像素。

from sklearn.datasets import load_wine
from sklearn.preprocessing import StandardScaler #导入数据预处理工具
from sklearn.decomposition import PCA #导入PCA
import matplotlib.pyplot as plt #导入画图工具


#载入红酒数据
wine = load_wine()

#对红酒数据进行预处理
scaler = StandardScaler()
X = wine.data
y = wine.target
X_scaled = scaler.fit_transform(X)

print('红酒数据样本数和特征数:', X_scaled.shape)

#设置主成分数量为 2 ,便于可视化
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_scaled)

print('降维后,红酒数据样本数和特征数:', X_pca.shape)

#数据特征可视化

#将三个分类中的主成分提取出来
X0 = X_pca[wine.target ==0]
X1 = X_pca[wine.target ==1]
X2 = X_pca[wine.target ==2]

#绘制散点图
plt.scatter(X0[:,0],X0[:,1],c='b',s=60,edgecolors='k')
plt.scatter(X1[:,0],X1[:,1],c='g',s=60,edgecolors='k')
plt.scatter(X2[:,0],X2[:,1],c='r',s=60,edgecolors='k')

#设置图注
plt.legend(wine.target_names, loc='best')
plt.xlabel('component 1')
plt.xlabel('component 2')
plt.show()

执行结果为:

红酒数据样本数和特征数: (178, 13)
降维后,红酒数据样本数和特征数: (178, 2)
9.2PCA.png

在之前的帖子中,为了可视化红酒数据,总是只取前2个特征,砍掉其余,其实是不科学的,现在使用PCA之后,将数据特征降维至二维,轻松实现可视化,又不会丢失太多信息

主成分与各特征值之间的关系


9.2PCA_relation.png

在上图中,颜色由深至浅代表一个从 -0.5~0.4的数值,在两个主成分中,分贝涉及了13个特征,如果某个特征对应的数字是正数,说明它和主成分之间是正相关的关系,如果是负数则相反。

二、使用PCA 进行特征提取

使用 LFW人脸识别数据。LFW 人脸识别数据集包含了若干张JPEG图片,是从网站上搜集的一些名人的照片,每张照片都是一个人的脸部。这个数据集最初创建是为了训练机器学习算法,看给出两张照片,算法能否判断出这两个人是否是同一个人;后来,对机器学习提出了更高的要求,给出一张不在数据集里的照片,让机器判断这张照片书否属于该数据集中的某一个人,并叫出TA的名字。

注释:
1.关于该数据集的详细介绍,可以参考这篇《Dataset之LFW:LFW人脸数据库的简介、安装、使用方法之详细攻略》
2.由于外网太慢,下载真的太难了,最好直接下到本地使用,我再这里下载的本地数据集,如果你需要,给我留言,我分享给你
3.关于该数据集在本地的使用,请参考《解决sklearn中 fetch_lfw_people安装失败问题》

接下来,使用该数据集,在数据未经处理的情况下,训练一个神经网络;再使用PCA中的数据白化功能处理人脸数据集,再训练神经网络模型,对比结果

注释:
关于白化处理的原理以及作用,可以参考以下两篇帖子《# 白化(Whitening): PCA 与 ZCA (转)
》 和《数据处理中白化Whitening的作用图解分析》

#特征提取
from sklearn.decomposition import PCA #导入PCA
import matplotlib.pyplot as plt #导入画图工具
from sklearn.datasets import fetch_lfw_people
from sklearn.neural_network import MLPClassifier
from sklearn.model_selection import train_test_split


#载入人脸数据(本地提前下载好的,不然太慢了)
faces = fetch_lfw_people(min_faces_per_person=20, resize=0.8)
image_shape = faces.images[0].shape
#将照片打印出来
fig, axes = plt.subplots(3, 4, figsize=(12,9), subplot_kw={'xticks':(), 'yticks':()})
for target, image, ax in zip(faces.target, faces.images, axes.ravel()):
    #print(target,faces.target_names[target])
    ax.imshow(image, cmap=plt.cm.gray)
    ax.set_title(faces.target_names[target])
#显示图像
#plt.show()

#数据未经处理,训练神经网络
X_train, X_test, y_train, y_test = train_test_split(faces.data/255, faces.target, random_state=62)

#训练神经网络
mlp = MLPClassifier(hidden_layer_sizes=[100,100], random_state=62, max_iter=400)
mlp.fit(X_train, y_train)
print('未经过预处理的数据模型识别准确率为:{:.2f}'.format(mlp.score(X_test, y_test)))

#使用白化功能处理人脸数据
pca = PCA(whiten=True, n_components=0.9, random_state=62) #保留90%的原始特征信息
pca.fit(X_train)
X_train_whiten = pca.transform(X_train)
X_test_whiten = pca.transform(X_test)

print('====================')
print('原始数据形态:{}'.format(X_train.shape))
print('白化后的数据形态:{}'.format(X_train_whiten.shape))

#使用白化后的数据进行神经网络模型训练
mlp.fit(X_train_whiten, y_train)
print('====================')
print('经过白化后的数据模型识别准确率为:{:.2f}'.format(mlp.score(X_test_whiten, y_test)))

执行结果为:
LFW人脸数据集中的部分照片如下图所示:


9.3LFW.png
未经过预处理的数据模型识别准确率为:0.46
====================
原始数据形态:(2267, 7500)
白化后的数据形态:(2267, 107)
====================
经过白化后的数据模型识别准确率为:0.57

从结果可以看到。模型的准确率轻微的提高了一些,说明PCA 的白化功能对提高神经网络的准确率是有一定的帮助的。

三、使用NMF进行 特征提取

NMF(Non-Negative Matrix Factorization)非负矩阵分解,是一个无监督学习,原始的矩阵中的所有数值必须大于或者等于0,分解之后的矩阵中的数据也是大于或者等于0的,简单理解为, NMF 是在
一堆特征值混乱无序的堆放空间中,从坐标原点出(0,0)出发引出一个或者几个向量,用这些向量,尽可能的把原始特征的信息表达出来。
与PCA的不同:
1.如果我们降低NMF的成分数量,它会生成新的成分,而新的成分和原来的成分是完全不一样的。
2.NMF中的成分是无序的,这点和PCA是不同的。
以下用NMF对LFW人脸数据集进行特征提取,再重新训练神经网络模型,对比查看结果。

#特征提取
from sklearn.decomposition import PCA #导入PCA
import matplotlib.pyplot as plt #导入画图工具
from sklearn.datasets import fetch_lfw_people
from sklearn.neural_network import MLPClassifier
from sklearn.model_selection import train_test_split
from sklearn.decomposition import NMF

#载入人脸数据(本地提前下载好的,不然太慢了)
faces = fetch_lfw_people(min_faces_per_person=20, resize=0.8)
image_shape = faces.images[0].shape
#将照片打印出来
fig, axes = plt.subplots(3, 4, figsize=(12,9), subplot_kw={'xticks':(), 'yticks':()})
for target, image, ax in zip(faces.target, faces.images, axes.ravel()):
    #print(target,faces.target_names[target])
    ax.imshow(image, cmap=plt.cm.gray)
    ax.set_title(faces.target_names[target])
#显示图像
#plt.show()

#数据未经处理,训练神经网络
X_train, X_test, y_train, y_test = train_test_split(faces.data/255, faces.target, random_state=62)

#训练神经网络
mlp = MLPClassifier(hidden_layer_sizes=[100,100], random_state=62, max_iter=400)
mlp.fit(X_train, y_train)
print('未经过预处理的数据模型识别准确率为:{:.2f}'.format(mlp.score(X_test, y_test)))

#使用NMF处理数据
nmf = NMF(n_components=107, random_state=62)
nmf.fit(X_train)
X_train_nmf = nmf.transform(X_train)
X_test_nmf = nmf.transform(X_test)
print('====================')
print('原始数据形态:{}'.format(X_train.shape))
print('nmf后的数据形态:{}'.format(X_train_nmf.shape))

mlp.fit(X_train_nmf, y_train)
print('====================')
print('经过nmf后的数据模型识别准确率为:{:.2f}'.format(mlp.score(X_test_nmf, y_test)))

执行结果如下:

原始数据形态:(2267, 7500)
nmf后的数据形态:(2267, 107)
====================
经过nmf后的数据模型识别准确率为:0.58

可见,进过NMF 处理后的数据训练的神经网络模型准确率和PCA处理后的模型准确率基本持平。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容