详解主成分分析PCA与奇异值分解SVD-PCA对手写数据集的降维 & 用PCA做噪音过滤菜菜的sklearn课堂笔记

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了详解主成分分析PCA与奇异值分解SVD-PCA对手写数据集的降维 & 用PCA做噪音过滤菜菜的sklearn课堂笔记相关的知识,希望对你有一定的参考价值。

数据预处理章节一直用的这个数据集

在本个案例中,由于PCA也有random_state参数,而并未设置,因此结果可能有不同

from sklearn.decomposition import PCA
from sklearn.ensemble import RandomForestClassifier as RFC
from sklearn.model_selection import cross_val_score
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

data = pd.read_csv(r"D:\\ObsidianWorkSpace\\SklearnData\\digit recognizor.csv")
X = data.iloc[:,1:]
y = data.iloc[:,0]

X.shape
---
(42000, 784)

y.shape
---
(42000,)

画累计方差贡献率曲线,找最佳降维后维度的范围

pca_line = PCA().fit(X)

plt.figure(figsize=[20,5])
plt.plot(np.cumsum(pca_line.explained_variance_ratio_))
plt.xlabel(number of components after dimension reduction)
plt.ylabel(cumulative explained variance)
plt.show()

继续缩小最佳维度的范围

score = []
for i in range(1,101,10):
    X_dr = PCA(i).fit_transform(X)
    once = cross_val_score(RFC(n_estimators=10,random_state=0)
                          ,X_dr,y,cv=5).mean()
    score.append(once)

plt.figure(figsize=[20,5])
plt.plot(range(1,101,10),score)
plt.xticks(range(1,101,10))
plt.show() # 降维到21维左右,并将数据导入随机森林将有最佳效果

再次缩小

score = []
for i in range(11,25):
    X_dr = PCA(i).fit_transform(X)
    once = cross_val_score(RFC(n_estimators=10,random_state=0)
                          ,X_dr,y,cv=5).mean()
    score.append(once)

plt.figure(figsize=[20,5])
plt.plot(range(11,25),score)
plt.xticks(range(11,25))
plt.show()

查看模型效果

X_dr = PCA(24).fit_transform(X)

cross_val_score(RFC(n_estimators=10,random_state=0),X_dr,y,cv=5).mean()
---
0.9170718423612418

cross_val_score(RFC(n_estimators=100,random_state=0),X_dr,y,cv=5).mean()
---
0.9471193590104136

在之前的建模过程中,因为计算量太大,所以我们一直使用随机森林,但事实上,对于这个数据集,KNN的效果比随机森林更好,KNN在未调参的状况下已经达到96%的准确率,而随机森林在未调参前只能达到93%,这是模型本身的限制带来的。现在我们的特征数量已经降到不足原来的3%,可以考虑使用KNN了

from sklearn.neighbors import KNeighborsClassifier as KNN
cross_val_score(KNN(),X_dr,y,cv=5).mean() # 默认k=5

score = []
for i in range(10):
    once = cross_val_score(KNN(i+1),X_dr,y,cv=5).mean()
    score.append(once)

plt.figure(figsize=[20,5])
plt.plot(range(10),score)
plt.xticks(range(10))
plt.show()

在k=5是效果最好,上面我们也跑过交叉验证了,这里不再赘述

可以发现,原本785列的特征被我们缩减到23列之后,用KNN跑出了目前位置这个数据集上最好的结果。再进行更细致的调整,我们也许可以将KNN的效果调整到98%以上。PCA为我们提供了无限的可能,终于不用再因为数据量太庞大而被迫选择更加复杂的模型了!

用PCA做噪音过滤

降维的目的之一就是希望抛弃掉对模型带来负面影响的特征,而我们相信,带有效信息的特征的方差应该是远大于噪音的,所以相比噪音,有效的特征所带的信息应该不会在PCA过程中被大量抛弃inverse_transform能够在不恢复原始数据的情况下,将降维后的数据返回到原本的高维空间,即是说能够实现”保证维度,但去掉方差很小特征所带的信息“。利用inverse_transform的这个性质,我们能够实现噪音过滤。

from sklearn.datasets import load_digits
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
import numpy as np

digits = load_digits()
digits.data.shape
---
(1797, 64)

digits.images.shape
---
(1797, 8, 8)

set(digits.target)
---
0, 1, 2, 3, 4, 5, 6, 7, 8, 9

def plot_digits(data):
# data的结构必须是(m,n),并且n要能够被分成(8,8)这样的结构
    fig, axes = plt.subplots(4,10,figsize=(10,4)
                            ,subplot_kw=xticks:[],yticks:[]
                            )
    for i,ax in enumerate(axes.flat):
        ax.imshow(data[i].reshape(8,8),cmap=binary)

plot_digits(digits.data)

为数据加上噪音

rng = np.random.RandomState(42)
noisy = rng.normal(digits.data,2) # 猜测应该是给每一列加上方差为2的高斯噪声,均值为该列的均值
# digits.data指定数据集
# 2:抽取出来正态分布的方差
noisy.shape
---
(1797, 64)
plot_digits(noisy)

pca = PCA(0.5,svd_solver=full).fit(noisy)
# 0.5是指50%的数据,而不是50%的维度
X_dr = pca.transform(noisy)
X_dr.shape
---
(1797, 6)

pca.explained_variance_ratio_.sum()
---
0.5071198405440357

without_noisy = pca.inverse_transform(X_dr)
plot_digits(without_noisy)

总结

以上是关于详解主成分分析PCA与奇异值分解SVD-PCA对手写数据集的降维 & 用PCA做噪音过滤菜菜的sklearn课堂笔记的主要内容,如果未能解决你的问题,请参考以下文章

详解主成分分析PCA与奇异值分解SVD-高维数据可视化以及参数n_components菜菜的sklearn课堂笔记

PCA(主成分分析)+SVD(奇异值分解)+区别

主成分分析(PCA)原理详解

机器学习——降维(主成分分析PCA线性判别分析LDA奇异值分解SVD局部线性嵌入LLE)

主成分分析PCA详解

主成分分析PCA主成分分析原理详解