使用PCA主要有三个作用: 1). 大大节省后续运行机器学习的时间; 2). 对数据可视化; 3). 降噪。
以下将用sklearn中的手写数据集来看看这三个方面的作用。
from sklearn import datasets
from sklearn.neighbors import KNeighborsClassifier
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 = 1)
在降维之前:
%%time
knn = KNeighborsClassifier()
knn.fit(X_train, y_train)
print(knn.score(X_test, y_test))
所需时间:
在降维之后:
# 先进性降维再分类
pca = PCA(n_components=2)
pca.fit(X_train)
X_train_reduction = pca.transform(X_train)
X_test_reduction = pca.transform(X_test)
%%time
knn = KNeighborsClassifier()
knn.fit(X_train_reduction, y_train)
print(knn.score(X_test_reduction, y_test))
可以看到PCA可以大大减少算法的运行速度,但是大大降低了精度。降到二维会丢失太多的信息,所以我们可以用sklearn中的explained_variance_ratio_参数来看前多少个轴的可解释方差。
得到所有的主成分中的方差并作图:
# 所有的主成分
pca = PCA(n_components=X.shape[1])
pca.fit(X_train)
print(pca.explained_variance_ratio_)
all_var = []
for i in range(X.shape[1]):
all_var.append(np.sum(pca.explained_variance_ratio_[:i]))
plt.plot(all_var, 'o-',color = 'g')
plt.show()
这样我们可以看到有多少维度的时候就有多少累积的可解释方差。不过sklearn提供了更方便的方法,其实在PCA()中可以直接传入这个百分比:
# 在PCA中我们可以传入多少的可解释方差, eg. 0.95
# 并且可以看到,28维的时候就有0.95了
pca = PCA(0.95)
pca.fit(X_train)
pca.n_components_
会输出28, 即前28维即可解释95%.
X_train_reduction = pca.transform(X_train)
X_test_reduction = pca.transform(X_test)
%%time
knn = KNeighborsClassifier()
knn.fit(X_train_reduction, y_train)
print(knn.score(X_test_reduction, y_test))
这样,时间要比一开始要少,而且得到的score也比较高。如果有海量样本,牺牲一点精度换取更少的时间是值得的。
降维到二维,就可以直接可视化。
pca = PCA(n_components=2)
pca.fit(X)
X_reduction = pca.transform(X)
for i in range(10):
plt.scatter(X_reduction[y==i, 0], X_reduction[y == i, 1], alpha=0.7)
plt.show()
这个是比较常用的方法,PCA丢掉的一部分特征其实也许是噪声,将这些噪声丢掉会增加模型的准确性。比如说如上的手写数据加上一部分噪声,那么可视化之后:
但是PCA降维之后(取50%):
以上是学习https://coding.imooc.com/learn/list/169.html [python3入门机器学习]课程所做的部分笔记。