主成分分析法

概述

  • 是一种非监督的机器学习法
  • 主要用于数据的降维
  • 通过降维,便于理解数据的特征
  • 可以用于数据的去噪

主成分分析法的目标是求 w w w,使得 V a r ( X p r o j e c t ) = 1 m ∑ i = 1 m ( ∑ j = 1 m X j ( i ) w j ) 2 Var(X_{project})=\frac{1}{m}\sum^m_{i=1}(\sum^m_{j=1}X_j^{(i)}w_j)^2 Var(Xproject)=m1i=1m(j=1mXj(i)wj)2

公式的意思是:把m维的点,映射到 w w w坐标系上面,使得这些点在 w w w坐标系上的方差最大(最稀疏)。其中 w w w坐标系的每一个维度就被称为主成分。

梯度下降法中,我求解了方差最小,相应的,我使用梯度上升法可以去求解方差最大。
任何梯度算法都需要使用导数,因此在计算之前,首先应当对导数的公式进行推导:
在这里插入图片描述
先不推了,就这样吧,直接sklearn实战

scikit-learn中的PCA

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets # sklearn自带的数据

digits = datasets.load_digits() # 手写数字的数据
x = digits.data
y = digits.target

from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=666) # 先区分训练集和测试集

PCA是对自变量降维,只保留其中具有解释力的维度。降维后的数据在进行机器学习运算时会更快。
在KNN算法的研究中,我进行写手写数字的识别。如果使用PCA算法对自变量数据进行降维,那么计算的速度将会大大的提高。

from sklearn.neighbors import KNeighborsClassifier

knn_clf = KNeighborsClassifier()
knn_clf.fit(x_train, y_train)

%time knn_clf.score(x_test, y_test) # 查看需要的时间
CPU times: user 68.4 ms, sys: 1.54 ms, total: 69.9 ms
Wall time: 68.7 ms
Out[65]:
0.9866666666666667

发现KNN在计算模型的score时使用了69.9ms,准确度为98.67%
如果先对x进行降维处理,那么:

from sklearn.decomposition import PCA

pca = PCA(n_components=2)
pca.fit(x_train)
x_train_reduction = pca.transform(x_train)
x_test_reduction = pca.transform(x_test)

knn_clf = KNeighborsClassifier()
knn_clf.fit(x_train_reduction, y_train)

%time knn_clf.score(x_test_reduction, y_test)
CPU times: user 20 ms, sys: 5.03 ms, total: 25 ms
Wall time: 20.3 ms
Out[68]:
0.6066666666666667

我们发现虽然计算的时间从69.9ms降低到了25ms,但是准确率却下降到了60.67%。
这是因为在进行降维时,我们过度的减少了原有数据的维度,将原本64维的数据降低为2维,这本身就不合理。
我们通过 pca.explained_variance_ratio_可以查看这两个维度的解释力度发现:array([0.14566817, 0.13735469]),两个加起来对原数据的方差解释不到30%,意味着我们丢失了70%的解释力度。
我们可以保持数据的64维不变,来看看每个维度的解释力度:

pca = PCA(n_components=x_train.shape[1])
pca.fit(x_train)
pca.explained_variance_ratio_
array([1.45668166e-01, 1.37354688e-01, 1.17777287e-01, 8.49968861e-02,
       5.86018996e-02, 5.11542945e-02, 4.26605279e-02, 3.60119663e-02,
       3.41105814e-02, 3.05407804e-02, 2.42337671e-02, 2.28700570e-02,
       1.80304649e-02, 1.79346003e-02, 1.45798298e-02, 1.42044841e-02,
       1.29961033e-02, 1.26617002e-02, 1.01728635e-02, 9.09314698e-03,
       8.85220461e-03, 7.73828332e-03, 7.60516219e-03, 7.11864860e-03,
       6.85977267e-03, 5.76411920e-03, 5.71688020e-03, 5.08255707e-03,
       4.89020776e-03, 4.34888085e-03, 3.72917505e-03, 3.57755036e-03,
       3.26989470e-03, 3.14917937e-03, 3.09269839e-03, 2.87619649e-03,
       2.50362666e-03, 2.25417403e-03, 2.20030857e-03, 1.98028746e-03,
       1.88195578e-03, 1.52769283e-03, 1.42823692e-03, 1.38003340e-03,
       1.17572392e-03, 1.07377463e-03, 9.55152460e-04, 9.00017642e-04,
       5.79162563e-04, 3.82793717e-04, 2.38328586e-04, 8.40132221e-05,
       5.60545588e-05, 5.48538930e-05, 1.08077650e-05, 4.01354717e-06,
       1.23186515e-06, 1.05783059e-06, 6.06659094e-07, 5.86686040e-07,
       7.44075955e-34, 7.44075955e-34, 7.44075955e-34, 7.15189459e-34])

会发现,基本上越靠后的维度越没有解释的力度。我们将解释力度随着维度的增加而变化的图像显示出来,就可以更加清晰的发现,我们只需要一部分维度就既可以有很好的解释力度,有可以让计算变得很快。

plt.plot([i for i in range(x_train.shape[1])],
        [np.sum(pca.explained_variance_ratio_[:i+1]) for i in range(x_train.shape[1])])
plt.show()

在这里插入图片描述
sklearn中的PCA算法提供了一个很好用的参数:

pca = PCA(0.95) # 不知道取多少个主成分,但是可以解释95%以上的方差
pca.fit(x_train)
x_train_reduction = pca.transform(x_train)
x_test_reduction = pca.transform(x_test)

knn_clf = KNeighborsClassifier()
knn_clf.fit(x_train_reduction, y_train)

%time knn_clf.score(x_test_reduction, y_test)
CPU times: user 36 ms, sys: 1.36 ms, total: 37.3 ms
Wall time: 35.8 ms
Out[72]:
0.98

我们发现不但准确率变高了,而且计算速度也变快了。

用PCA发现人脸识别中的特征脸

其实特征脸就是寻找人脸中的主成分,这些特征脸对模型中的脸又很好的解释力度。

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_lfw_people # sklearn自带的人脸数据

faces = fetch_lfw_people() # 数据下载
faces.keys() # dict_keys(['data', 'images', 'target', 'target_names', 'DESCR'])
faces.data.shape # (13233, 2914),也就是13233个数据,每个数据都有2914个像素点组成

random_indexes = np.random.permutation(len(faces.data))
x = faces.data[random_indexes]
# 绘制36张脸作为实例
example_faces = x[:36, :]
example_faces.shape # (36, 2914)

def plot_faces(faces):
    fig, axs = plt.subplots(6, 6, figsize=(10,10),
                           subplot_kw={'xticks':[], 'yticks':[]},
                            gridspec_kw=dict(hspace=0.1, wspace=0.1))
    for i, ax in enumerate(axs.flat):
        ax.imshow(faces[i].reshape(62, 47), cmap='bone')
    plt.show()
plot_faces(example_faces)

在这里插入图片描述
进行PCA降维后就可以得到特征脸

from sklearn.decomposition import PCA
pca = PCA(svd_solver='randomized')
pca.fit(x)

plot_faces(pca.components_[:36])

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值