sklearn+python::主成分分析-PCA

概述

PCA是一种降维算法,可以用来对数据进行压缩,或者降维后进行可视化显示。

把n维数据降维k维数据时,就是要找出合适的k个向量,把n维数据投射到这k个向量决定的线性空间中,最终使投射误差最小化。

衡量PCA算法的指标是数据还原率(与失真度互补),这个指标由(1 - (平均投射误差的平方除以所有样本到原点的平均距离))得到。如果数据还原率为99%,我们就可以说99%的数据真实性被保存下来了。

K的选择

一般要选择一个偏差目标,在满足偏差目标的情况下最小化K。

计算K的过程就是把K从1开始,不断累加,直到偏差符合我们的要求。
计算偏差的过程可以通过求奇异值分解的S矩阵来简化。

PCA的一些建议

PCA算法常常用来给监督学习算法加速。

一种错误的PCA使用方法:直接用来降维后防止过拟合。

这种方法一般都有效,可是防止过拟合的更好方法是增加正则化项。
不建议一开始就用PCA降维数据再训练。应该先使用原始数据训练,在确信需要PCA的时候才使用PCA

sklearn:二维数据降为一维

下面使用sklearn演示二维数据降为一维,然后再恢复回来。

from sklearn.decomposition import PCA
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import  MinMaxScaler
import numpy as np
# 禁用科学计数法显示
np.set_printoptions(suppress=True)

# 使用缩放类预处理数据,然后后使用pipeline连接起来
def std_PCA(**argv):
    scaler = MinMaxScaler()
    pca = PCA(**argv)
    pipeline = Pipeline([('scaler', scaler),
                         ('pca', pca)])

    return pipeline

A = np.array([[3, 2000],
              [2, 3000],
              [4, 5000],
              [5, 8000],
              [1, 2000]], dtype='float')
print("raw data:\n{}".format(A))

# 训练,降维目标由n_components指定
pca = std_PCA(n_components=1)
pca.fit(A)

# 降维转换
compress = pca.transform(A)
print("compress:\n{}".format(compress))
score = pca.score(A)
print('fit score:{}'.format(score))

# 恢复数据
restore = pca.inverse_transform(compress)
print("restore:\n{}".format(restore))

这里的pca是一个Pipeline实例,其逆运算inverse_transform()是逐级进行的,即先进行PCA还原,再执行预处理的逆运算。

代码里的score按照文档里的解释是所有样本的对数似然函数平均值,具体计算参考:

See. "Pattern Recognition and Machine Learning"
        by C. Bishop, 12.2.1 p. 574
        or http://www.miketipping.com/papers/met-mppca.pdf

上述代码的输出为:

raw data:
[[   3. 2000.]
 [   2. 3000.]
 [   4. 5000.]
 [   5. 8000.]
 [   1. 2000.]]
compress:
[[-0.2452941 ]
 [-0.29192442]
 [ 0.29192442]
 [ 0.82914294]
 [-0.58384884]]
fit score:-0.15297041662134564
restore:
[[   2.33563616 2916.95452015]
 [   2.20934082 2711.06794139]
 [   3.79065918 5288.93205861]
 [   5.2456822  7660.90959707]
 [   1.41868164 1422.13588278]]

PCA+SVM 人脸识别

将剑桥人脸数据集的图片(分辨率64X64),经过PCA降到140维,然后使用SVM分类。数据集里有40个人,每人10张,共400张图片。

SVM的参数使用GridSearchCV搜索,找到最优参数后,对测试集进行预测,然后使用classification_report统计在测试集上的预测结果。

ps:我感觉这就是个玩具,人脸角度和光线变化肯定会前列影响分类结果,连割脸的位置都有很大影响。SVM并不能使用人脸的一些结构化信息,只能用来演示基本的算法调用方法。搞人脸还是要专门的算法。

import numpy as np
import time
from sklearn.decomposition import PCA
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.svm import SVC
from sklearn.metrics import classification_report

from sklearn.datasets import fetch_olivetti_faces
face_home = './att_faces'

faces = fetch_olivetti_faces(data_home=face_home)
X = faces.data
y = faces.target

print('########## face-dataset info ###########')
targets = np.unique(faces.target)
target_names = np.array(['c%d'% t for t in targets])
print('targets:{},\ntarget_names:{}\n'.format(targets, target_names))

n_targets = target_names.shape[0]
n_samples, h, w = faces.images.shape
print('Sample count:{}\nTarget count:{}'.format(n_samples, n_targets))
print('Image size:{}X{}\nDataset shape:{}\n'.format(w, h, X.shape))

# -------------------------------------
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=4)

print('########### PCA ############')
n_components = 140
start = time.clock()
pca = PCA(n_components=n_components, svd_solver='randomized', whiten=True).fit(X_train)
print('PCA Done in {0:.2f}s'.format(time.clock() - start))

print('Projecting input data for PCA')
start = time.clock()
X_train_pca = pca.transform(X_train)
X_test_pca = pca.transform(X_test)
print('transform Done in {0:.2f}s\n'.format(time.clock() - start))

print('############# SVM ##############')
print('Searching the best parameters for SVC ...')
param_grid = {'C':[1, 5, 10, 50, 100], 'gamma':[0.0001, 0.0005, 0.001, 0.005, 0.01]}
clf = GridSearchCV(SVC(kernel='rbf', class_weight='balanced'), param_grid, verbose=0, n_jobs=1)
clf = clf.fit(X_train_pca, y_train)
print("Best param: {0}\nbest score: {1}\n".format(clf.best_params_,
                                                clf.best_score_))

print('############# Predict #################')
y_pre = clf.best_estimator_.predict(X_test_pca)
print(classification_report(y_test, y_pre, target_names=target_names))

最终的输出为:

########## face-dataset info ###########
targets:[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39],
target_names:['c0' 'c1' 'c2' 'c3' 'c4' 'c5' 'c6' 'c7' 'c8' 'c9' 'c10' 'c11' 'c12' 'c13'
 'c14' 'c15' 'c16' 'c17' 'c18' 'c19' 'c20' 'c21' 'c22' 'c23' 'c24' 'c25'
 'c26' 'c27' 'c28' 'c29' 'c30' 'c31' 'c32' 'c33' 'c34' 'c35' 'c36' 'c37'
 'c38' 'c39']

Sample count:400
Target count:40
Image size:64X64
Dataset shape:(400, 4096)

########### PCA ############
PCA Done in 0.29s
Projecting input data for PCA
transform Done in 0.01s

############# SVM ##############
Searching the best parameters for SVC ...
Best param: {'C': 10, 'gamma': 0.001}
best score: 0.80625

############# Predict #################
        precision    recall  f1-score   support

         c0       0.50      1.00      0.67         1
         c1       1.00      0.67      0.80         3
         c2       1.00      0.50      0.67         2
         c3       1.00      1.00      1.00         1
         c4       0.50      1.00      0.67         1
         c5       1.00      1.00      1.00         1
         c6       1.00      0.75      0.86         4
         c7       1.00      1.00      1.00         2
         c8       1.00      1.00      1.00         4
         c9       1.00      1.00      1.00         2
        c10       1.00      1.00      1.00         1
        c11       1.00      1.00      1.00         4
        c12       1.00      1.00      1.00         4
        c13       1.00      1.00      1.00         1
        c14       1.00      1.00      1.00         1
        c15       0.75      1.00      0.86         3
        c16       1.00      1.00      1.00         2
        c17       1.00      1.00      1.00         2
        c18       1.00      1.00      1.00         2
        c19       1.00      1.00      1.00         1
        c20       1.00      1.00      1.00         2
        c21       0.75      1.00      0.86         3
        c22       1.00      1.00      1.00         2
        c23       1.00      1.00      1.00         3
        c24       1.00      0.67      0.80         3
        c25       1.00      1.00      1.00         2
        c26       1.00      1.00      1.00         2
        c27       1.00      1.00      1.00         2
        c28       1.00      1.00      1.00         2
        c29       1.00      1.00      1.00         3
        c30       1.00      1.00      1.00         2
        c31       1.00      1.00      1.00         2
        c32       1.00      1.00      1.00         2
        c33       1.00      1.00      1.00         3
        c34       1.00      1.00      1.00         1
        c35       1.00      1.00      1.00         2
        c36       1.00      1.00      1.00         2

avg / total       0.97      0.95      0.95        80

平均准确率和召回率都在95%以上,看着还行啊。
试了下降维到40维然后svm分类,准确率达到了99%。看来不是特征越多越好呀。但也不是越少越好,降维到30,效果和140差不多了。

你可能感兴趣的:(机器学习,sklearn,python,DL/ML/AI,机器学习和机器视觉)