机器学习笔记 多项式回归这一篇中,我们讲到了如何构造新的特征,相当于对样本数据进行升维.

那么相应的,我们肯定有数据的降维.那么现在思考两个问题

  • 为什么需要降维
  • 为什么可以降维

第一个问题很好理解,假设我们用KNN训练一些样本数据,相比于有1W个特征的样本,肯定是训练有1K个特征的样本速度更快,因为计算量更小嘛.

第二个问题,为什么可以降维.一个样本原先有1W个特征,现在减少到1K个,不管如何变换,数据包含的信息肯定是减少了,这是毫无疑问的.但是信息的减少是否意味着我们对于样本的认知能力的下降?这个则未必.

以minist数据集为例,每一个数字图片都由N个像素构成,即样本有N个特征,但是我们不需要精确地知道每一个像素的值,依然能够分辨出这个数字是几,你可以通俗地理解为,比如你把每张图的边边角角都减掉,并不影响你识别这是几。  由此,我们知道,样本特征的重要性并不是一致的,有的重要,也即所谓的主成分.

现在问题则转换为:我们怎么样寻找到一种方法,使得降维后"重要的特征"尽可能地保留,也即降维后信息的丢失最少?

依然从一个极端的例子入手,假设我们有M个样本,每个样本2个特征,特征1的波动幅度很大,特征2的波动幅度很小.

此时,如果要把这M个样本降成1维,采用最简单粗暴的方式,丢弃一个特征,是丢弃feature1呢还是feature2呢?

如果,丢弃feature1的话,我们的样本就只剩下了feature2,而feature2的值在3附近微小的波动,几乎没有变化.   没有变化,机器学习算法就没法从中学习到足够的信息.比如M个样本对应着M个label,这M个label各不相同.来了个新样本,特征值还是3,这时候我们是没法推算出新样本的label的.

对机器学习算法而言,我们希望在合理的范围内,数据的分布越分散越好,即数据的方差越大越好,这样才能学习到足够多的信息.

而这也正是PCA降维的理论基础:我们希望找到一个新的N维坐标系,使得数据在这个新的N维坐标系的前K个坐标轴上分布,方差最大.这样的N维坐标系中的K个坐标轴就是我们所要寻找的K个主成分.

比如对这个图中的蓝色的点而言,我们希望找到一个向量w(图中的蓝色线),使得各点在w上的投影点,方差最大.样本点$X^{(i)}$投影到单位向量w后得到$X_p^{(i)}$,这些新的样本点的方差为$\frac{\sum_{i=1}^m (X_p^{(i)} - \overline X_p)^2)} m$,为了方便计算,在向w投影之前,我们对样本X做demean去均值处理,即每个特征值减去该维度特征的均值,这个操作并不会影响数据的分布.demean后的样本点投影到w后得到的新样本点的方差变为$\frac{\sum_{i=1}^m (X_p^{(i)})^2)} m$.注意这里$X_p^{(i)}$是一个向量.所以我们的方差可以转变为$$Var(X_p) = \frac{\sum_{i=1}^m || X_p^{(i)} ||^2)} m$$

注意,样本点$X^{(i)}$投影到单位向量w后得到$X_p^{(i)}$,由向量点乘的定义我们能够得到$X^{(i)} \cdot w = || X^{(i)}|| \cdot || w|| \cdot \cos \theta =  || X^{(i)}|| \cdot \cos \theta = || X_p^{(i)} ||$.由此我们的目标转变为使得$$Var(X_p) = \frac{\sum_{i=1}^m  X^{(i)} \cdot w^2)} m$$最大化.

接下来我们用梯度上升法求出这个w。现在先不用管梯度上升法是怎么回事,本篇重点在于理解PCA。梯度下降法梯度上升法以后会再写博文解释.这个w也就是我们的第一主成分.即样本投影到这个方向后,方差最大,损失信息最少.那么现在我们如何求出第二主成分呢?

求出这个w之后,注意w是一个N维向量. 我们就可以得到X在w之外剩余的分量为$X^{’(i)}=X^{(i)}-X_p^{(i)}=X^{(i)}-X^{(i) \cdot w}$,对$X^{’(i)}$,我们再次求出一个w2,使得其在w2上的投影的方差最大,求解方法同上.

我们不断循环这个过程,就可以求解出k个w,记做

$$W_k=\begin{bmatrix} W_1^{(1)}& W_2^{(1)}& … &W_n^{(1)} \\ W_1^{(2)}& W_2^{(2)}& … &W_n^{(2)} \\ … \\ W_1^{(k)}& W_2^{(k)}& … &W_n^{(k)} \\ \end{bmatrix}$$.即$$W_k=\begin{bmatrix} w_1\\ w_2 \\ … \\w_k\\ \end{bmatrix}$$

这个$W_k$即我们求出的新的N维坐标系的前K个坐标轴.

原始数据点在新的N维坐标系的第k个坐标轴的投影距离为$X^{(i)} \cdot w_k$,则原始样本在新的N维坐标系的前K个坐标轴上可以表示为$$X^{‘}=XW_k^T$$。这样我们就把矩阵M*N的矩阵X转换成了M*K的矩阵$X^{'}$,从而达到了降维的目的.


原理部分说完了,我们来看一下sklearn中的具体api使用.

class sklearn.decomposition.PCA(n_components=Nonecopy=Truewhiten=Falsesvd_solver=’auto’tol=0.0iterated_power=’auto’random_state=None)[source]

常用参数有n_components,代表降维后需要保留的维度数.如果0<n_components<1的话,表示降维后需要保留的方差比例.(你可以通俗地理解为保留的信息占原始信息的百分比)

常用属性:

explained_variance_ : array, shape (n_components,)  解释了新的坐标系中的k个坐标轴的每一个轴所解释的方差.

explained_variance_ratio_ : array, shape (n_components,) 解释了新的坐标系中的k个坐标轴的每一个轴所解释的方差所占百分比.

n_components_:主成分个数.即降到的维度数.

components_ : array, shape (n_components, n_features) 主成分.

这样说显得有点抽象,看个例子你就全明白.

  1. from sklearn.decomposition import PCA
  2.  
  3. pca = PCA(n_components=2)
  4. pca.fit(X_train)
  5. X_train_reduction = pca.transform(X_train)
  6. X_test_reduction = pca.transform(X_test)
  7.  
  8. knn_clf = KNeighborsClassifier()
  9. knn_clf.fit(X_train_reduction, y_train)

我们把64维的X_train降成二维的X_train_reduction.

pca.explained_variance_

  1. array([ 175.77007821, 165.73864334])

pca.explained_variance_ratio_

  1. array([ 0.14566817, 0.13735469])

什么意思呢?降维后的X_train_reduction在第一个维度上(第一主成分)的方差为175.77,占比为14.56%.

来看下当我们将n_components传参为原始特征数量时

  1. from sklearn.decomposition import PCA
  2.  
  3. pca = PCA(n_components=X_train.shape[1])
  4. pca.fit(X_train)
  5. pca.explained_variance_ratio_
  6.  
  7. plt.plot([i for i in range(X_train.shape[1])],
  8. [np.sum(pca.explained_variance_ratio_[:i+1]) for i in range(X_train.shape[1])])
  9. plt.show()

可以看到前40个维度,(注意不是X_train的前40个维度的特征,是降维后,新的坐标系的前40个坐标轴,即第一主成分到第四十主成分),已经可以表达接近100%的原始信息了.

PCA降维后,我们的数据不像原始数据那样具有可解释性了. 这是PCA的一个缺点. 降维后,在数学的角度上我们可以通过$X=X^{(')}W_k$还原回去得到一个M*N的矩阵,但是这个X与原始的X已经不一样了,因为降维后一定是损失了信息的,所以说只是数学角度上可以还原回去.

PCA降维后,有些时候不但不会降低模型的训练效果,反而提升了训练效果,因为我们损失了一些信息,但是这些不重要的信息可能恰好是影响模型训练的噪音.


PCA的一个典型应用,人脸识别中提取特征脸.

  1. from __future__ import print_function
  2.  
  3. from time import time
  4. import logging
  5. import matplotlib.pyplot as plt
  6.  
  7. from sklearn.model_selection import train_test_split
  8. from sklearn.model_selection import GridSearchCV
  9. from sklearn.datasets import fetch_lfw_people
  10. from sklearn.metrics import classification_report
  11. from sklearn.metrics import confusion_matrix
  12. from sklearn.decomposition import PCA
  13. from sklearn.svm import SVC
  14.  
  15. print(__doc__)
  16.  
  17. # Display progress logs on stdout
  18. logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s')
  19.  
  20. # #############################################################################
  21. # Download the data, if not already on disk and load it as numpy arrays
  22.  
  23. lfw_people = fetch_lfw_people(min_faces_per_person=70, resize=0.4)
  24.  
  25. # introspect the images arrays to find the shapes (for plotting)
  26. n_samples, h, w = lfw_people.images.shape
  27.  
  28. # for machine learning we use the 2 data directly (as relative pixel
  29. # positions info is ignored by this model)
  30. X = lfw_people.data
  31. n_features = X.shape[1]
  32.  
  33. # the label to predict is the id of the person
  34. y = lfw_people.target
  35. target_names = lfw_people.target_names
  36. n_classes = target_names.shape[0]
  37.  
  38. print("Total dataset size:")
  39. print("n_samples: %d" % n_samples)
  40. print("n_features: %d" % n_features)
  41. print("n_classes: %d" % n_classes)
  42.  
  43. # #############################################################################
  44. # Split into a training set and a test set using a stratified k fold
  45.  
  46. # split into a training and testing set
  47. X_train, X_test, y_train, y_test = train_test_split(
  48. X, y, test_size=0.25, random_state=42)
  49.  
  50. # #############################################################################
  51. # Compute a PCA (eigenfaces) on the face dataset (treated as unlabeled
  52. # dataset): unsupervised feature extraction / dimensionality reduction
  53. n_components = 150
  54.  
  55. print("Extracting the top %d eigenfaces from %d faces"
  56. % (n_components, X_train.shape[0]))
  57. t0 = time()
  58. pca = PCA(n_components=n_components, svd_solver='randomized',
  59. whiten=True).fit(X_train)
  60. print("done in %0.3fs" % (time() - t0))
  61.  
  62. eigenfaces = pca.components_.reshape((n_components, h, w))
  63.  
  64. print("Projecting the input data on the eigenfaces orthonormal basis")
  65. t0 = time()
  66. X_train_pca = pca.transform(X_train)
  67. X_test_pca = pca.transform(X_test)
  68. print("done in %0.3fs" % (time() - t0))
  69.  
  70. # #############################################################################
  71. # Train a SVM classification model
  72.  
  73. print("Fitting the classifier to the training set")
  74. t0 = time()
  75. param_grid = {'C': [1e3, 5e3, 1e4, 5e4, 1e5],
  76. 'gamma': [0.0001, 0.0005, 0.001, 0.005, 0.01, 0.1], }
  77. clf = GridSearchCV(SVC(kernel='rbf', class_weight='balanced'),
  78. param_grid, cv=5)
  79. clf = clf.fit(X_train_pca, y_train)
  80. print("done in %0.3fs" % (time() - t0))
  81. print("Best estimator found by grid search:")
  82. print(clf.best_estimator_)
  83.  
  84. # #############################################################################
  85. # Quantitative evaluation of the model quality on the test set
  86.  
  87. print("Predicting people's names on the test set")
  88. t0 = time()
  89. y_pred = clf.predict(X_test_pca)
  90. print("done in %0.3fs" % (time() - t0))
  91.  
  92. print(classification_report(y_test, y_pred, target_names=target_names))
  93. print(confusion_matrix(y_test, y_pred, labels=range(n_classes)))
  94.  
  95. # #############################################################################
  96. # Qualitative evaluation of the predictions using matplotlib
  97.  
  98. def plot_gallery(images, titles, h, w, n_row=3, n_col=4):
  99. """Helper function to plot a gallery of portraits"""
  100. plt.figure(figsize=(1.8 * n_col, 2.4 * n_row))
  101. plt.subplots_adjust(bottom=0, left=.01, right=.99, top=.90, hspace=.35)
  102. for i in range(n_row * n_col):
  103. plt.subplot(n_row, n_col, i + 1)
  104. plt.imshow(images[i].reshape((h, w)), cmap=plt.cm.gray)
  105. plt.title(titles[i], size=12)
  106. plt.xticks(())
  107. plt.yticks(())
  108.  
  109. # plot the result of the prediction on a portion of the test set
  110.  
  111. def title(y_pred, y_test, target_names, i):
  112. pred_name = target_names[y_pred[i]].rsplit(' ', 1)[-1]
  113. true_name = target_names[y_test[i]].rsplit(' ', 1)[-1]
  114. return 'predicted: %s\ntrue: %s' % (pred_name, true_name)
  115.  
  116. prediction_titles = [title(y_pred, y_test, target_names, i)
  117. for i in range(y_pred.shape[0])]
  118.  
  119. plot_gallery(X_test, prediction_titles, h, w)
  120.  
  121. # plot the gallery of the most significative eigenfaces
  122.  
  123. eigenface_titles = ["eigenface %d" % i for i in range(eigenfaces.shape[0])]
  124. plot_gallery(eigenfaces, eigenface_titles, h, w)
  125.  
  126. plt.show()

具体详情请参考sklearn官方文档.

特征脸是怎么提取的之主成分分析法PCA的更多相关文章

  1. 【笔记】主成分分析法PCA的原理及计算

    主成分分析法PCA的原理及计算 主成分分析法 主成分分析法(Principal Component Analysis),简称PCA,其是一种统计方法,是数据降维,简化数据集的一种常用的方法 它本身是一 ...

  2. 【机器学习】主成分分析法 PCA (II)

    主成分分析法(PAC)的优化——选择主成分的数量 根据上一讲,我们知道协方差为① 而训练集的方差为②. 我们希望在方差尽可能小的情况下选择尽可能小的K值. 也就是说我们需要找到k值使得①/②的值尽可能 ...

  3. 吴恩达机器学习笔记(八) —— 降维与主成分分析法(PCA)

    主要内容: 一.降维与PCA 二.PCA算法过程 三.PCA之恢复 四.如何选取维数K 五.PCA的作用与适用场合 一.降维与PCA 1.所谓降维,就是将数据由原来的n个特征(feature)缩减为k ...

  4. 主成分分析法PCA原理

    PCA(Principal Component Analysis)是一种常用的数据分析方法.PCA通过线性变换将原始数据变换为一组各维度线性无关的表示,可用于提取数据的主要特征分量,常用于高维数据的降 ...

  5. 【机器学习】主成分分析法 PCA (I)

    主成分分析算法是最常见的降维算法,在PCA中,我们要做的是找到一个方向向量,然后我们把所有的数都投影到该向量上,使得投影的误差尽可能的小.投影误差就是特征向量到投影向量之间所需要移动的距离. PCA的 ...

  6. 主成分分析法(PCA)答疑

    问:为什么要去均值? 1.我认为归一化的表述并不太准确,按统计的一般说法,叫标准化.数据的标准化过程是减去均值并除以标准差.而归一化仅包含除以标准差的意思或者类似做法.2.做标准化的原因是:减去均值等 ...

  7. 【笔记】特征脸(PCA在人脸识别领域的应用)

    人脸识别与特征脸(简单介绍) 什么是特征脸 特征脸(Eigenface)是指用于机器视觉领域中的人脸识别问题的一组特征向量,该方法被认为是第一种有效的人脸识别方法. PCA的具体实现思想见 [笔记]主 ...

  8. 降维之主成分分析法(PCA)

    一.主成分分析法的思想 我们在研究某些问题时,需要处理带有很多变量的数据,比如研究房价的影响因素,需要考虑的变量有物价水平.土地价格.利率.就业率.城市化率等.变量和数据很多,但是可能存在噪音和冗余, ...

  9. 特征脸(Eigenface)理论基础-PCA(主成分分析法)

    在之前的博客  人脸识别经典算法一:特征脸方法(Eigenface)  里面介绍了特征脸方法的原理,但是并没有对它用到的理论基础PCA做介绍,现在做补充.请将这两篇博文结合起来阅读.以下内容大部分参考 ...

随机推荐

  1. Python3--Numpy

    数组的形状是它有多少行和列,上面的数组有5行和5列,所以它的形状是(5,5). itemsize属性是每个项占用的字节数.这个数组的数据类型是int 64,一个int 64中有64位,一个字节中有8位 ...

  2. jQuery的基本选择器

    <script type="text/javascript"> //演示jQuery的基本选择器 $(function () { //通过ID var obj1 = $ ...

  3. 前端 javascript

    ---恢复内容开始--- JavaScript  JavaScript:是一门编译型的语言,比python语言还要弱类型的语言 JavaScript 分为三个部分:Ecmascript.dom.bom ...

  4. 11个炫酷的Linux终端命令大全

    我已经用了十年的Linux了,通过今天这篇文章我将向大家展示一系列的命令.工具和技巧,我希望一开始就有人告诉我这些,而不是曾在我成长道路上绊住我. 1.命令行日常系快捷键 如下的快捷方式非常有用,能够 ...

  5. python property对象

    一.从@porperty说起 Python内置的@property装饰器是负责把一个方法变成属性调用的 class Stu(object): def __init__(self,age): self. ...

  6. Pip无法卸载某些包:Cannot uninstall 'PyYAML'.

    查找了很多资料,最终还是手动删除吧: 注意如果你有火萤酱或everything等外部索引的,来搜索如图PyYAML的进行删除,可能删不干净 建议最后在你的anaconda路径下或者python路径下在 ...

  7. CentOS 5 常见的configure error的解决方法

    仅限于CentOS 5 configure: error: No curses/termcap library found 网上有的说法是: --with-named-curses-libs=/usr ...

  8. 手动模拟attach cinder volume的过程

    我们首先启动一台机器,启动的时候attach一个volume 创建一个空的cinder volume root:~# cinder create --display-name emptyvolume1 ...

  9. PopupWindow 以及拍照、裁剪

    实现这样的效果 圆角图片的自定义控件直接拷进来,和com一个等级 想要弹出内容可以使用悬浮窗 layout_pupup <LinearLayout xmlns:android="htt ...

  10. springboot tomcat配置参数列表

    springboot tomcat的配置选项大全 server. Port = xxxx server. Address = server. contextPath = server. display ...