用python实现PCA降维
学习笔记
·
主成分分析(Principal Component Analysis)
Step 1:去相关(Decorrelation)
旋转数据样本,使它们与坐标轴对齐,并且样本均值变为0。
##############################################################################
# 准备工作
import matplotlib.pyplot as plt
import pandas as pd
grains = pd.read_csv('D:\CSDN_notes\python_ML\Grains.csv')
print(grains.keys())
del grains['Unnamed: 0']
# 读取width一列
width = grains['width']
# 读取length一列
length = grains['length']
# 画散点图
plt.scatter(width, length, c = 'lightcoral')
plt.axis('equal')
plt.savefig('before_decorrelation.jpg')
plt.show()
##############################################################################
# 导入PCA
from sklearn.decomposition import PCA
import numpy as np
# 创建一个模型叫 model
model = PCA()
# 训练模型并使用,注意训练一定要使用numpy数组
grains = np.array(grains)
pca_features = model.fit_transform(grains)
# 读取“去相关”的width一列
xs = pca_features[:,0]
# 读取“去相关”的length一列
ys = pca_features[:,1]
# 画散点图
plt.scatter(xs, ys,c = 'pink')
plt.axis('equal')
plt.savefig('decorrelation.jpg')
plt.show()
# 引入皮尔逊相关系数量化“去相关”前后的变化
# 导入相关库
from scipy.stats import pearsonr
# 计算“去相关”前的相关性
correlation_before, pvalue_before = pearsonr(width, length)
print(correlation_before)
# 计算“去相关”后的相关性
correlation_after, pvalue_after = pearsonr(xs, ys)
print(correlation_after)
结果分别是0.8603339890768432与1.1796119636642288e-16,后者接近0,说明“去相关”成功。
Step 2: 降维(Reduce Dimension)
思路:通过画出不同特征的方差来选择 Intrinsic Dimension。(使数据集特征最大程度保持的最低维度)
1,找出第一主成分(The first principal component),即数据变化最大的方向。
# 找出“第一主成分”
# 计算出每一特征的均值
mean = model.mean_
# 获取“第一主成分”
first_pc = model.components_[0,:]
# 画箭头,注意背景使用的是没有“去相关”的点
plt.scatter(width, length,c = 'pink')
plt.arrow(mean[0], mean[1], first_pc[0], first_pc[1], color='darkviolet', width=0.01)
plt.axis('equal')
plt.savefig('the first principal component.jpg')
plt.show()
2,作出方差图选择Intrinsic Dimension
# 画出方差图
features = range(model.n_components_)
plt.bar(features, model.explained_variance_, color = 'pink')
plt.xlabel('PCA feature')
plt.ylabel('variance')
plt.xticks(features)
plt.savefig('Variance of the PCA features.jpg')
plt.show()
可以从结果图看出,有两个特征,其中“0”号特征的方差远远大于“1”号特征,我们就可以认为该数据集的Intrinsic Dimension是1。但是很多情况下,我们需要特别规定留下几个特征,这时候可以使用n_components。
# 以留下2个特征为例
model = PCA(n_components=2)
数据是文本时
在自然语言处理中,词频这类稀疏数组,我们通常使用一种叫做"csr_matrix"的特殊数组表示,它的特点是只记忆非零项。可是Scikit-learn库中的"PCA"不支持这种数组,所以需要使用"TruncatedSVD"替代,但是不用担心,"TruncatedSVD"与“PCA”的用法类似。我们用维基百科中的一些articles举个例子叭
# Wikipedia Examples
# 导入我们的降维函数TruncatedSVD以及我们的分类函数KMeans,我们还导入make_pipeline来做一个pipeline
from sklearn.decomposition import TruncatedSVD
from sklearn.cluster import KMeans
from sklearn.pipeline import make_pipeline
#######################################################################################
# 在此之前,先使用 TfidfVectorizer 把文字编码成特殊数据类型
# 温馨提示:注意区分 TfidfVectorizer 与上面提到的 TruncatedSVD
from sklearn.feature_extraction.text import TfidfVectorizer
model_new = TfidfVectorizer()
wiki_features = model_new.fit_transform(wiki_documents)
#######################################################################################
# 选择50个特征
svd = TruncatedSVD(n_components = 2)
# 选择KMeans的参数为6
kmeans = KMeans(n_clusters = 6)
# 做一个通道,可以将TruncatedSVD()与KMeans()合成一个步骤调用
pipeline = make_pipeline(svd,kmeans)
# 训练模型
pipeline.fit(wiki_features)
# 预测标签
labels = pipeline.predict(wiki_features)
# 使用 pandas 整理输出
import pandas as pd
df = pd.DataFrame({'label': labels, 'wiki_title': titles}) # titles是每个文章的标题
print(df.sort_values('label')) # 按照标签数字升序排列
最后的输出结果:
<script.py> output:
label wiki_title
59 0 Adam Levine
57 0 Red Hot Chili Peppers
56 0 Skrillex
55 0 Black Sabbath
54 0 Arctic Monkeys
53 0 Stevie Nicks
52 0 The Wanted
51 0 Nate Ruess
50 0 Chad Kroeger
58 0 Sepsis
30 1 France national football team
31 1 Cristiano Ronaldo
32 1 Arsenal F.C.
33 1 Radamel Falcao
37 1 Football
35 1 Colombia national football team
36 1 2014 FIFA World Cup qualification
38 1 Neymar
39 1 Franck Ribéry
34 1 Zlatan Ibrahimović
26 2 Mila Kunis
28 2 Anne Hathaway
27 2 Dakota Fanning
: : : :
43 4 Leukemia
9 4 LinkedIn
48 4 Gabapentin
0 4 HTTP 404
45 5 Hepatitis C
41 5 Hepatitis B
40 5 Tonsillitis
最后另外再看一下编码后的 wiki_features 变量,它是csr_matrix类型。直接输出只有非0值,但如果使用 .toarray() 可以输出0值,大家通过对比第二个与第三个输出看出区别:
<script.py> output:
wiki_features.shape is (60, 13125)
wiki_features is (0, 16) 0.024688249778400003
(0, 32) 0.0239370711117
(0, 33) 0.0210896267411
: :
(59, 13107) 0.025819936285200004
(59, 13108) 0.0340972474957
(59, 13113) 0.0170000449408
wiki_features.toarray() is [[0. 0. 0. ... 0. 0. 0. ]
[0. 0. 0.02960744 ... 0. 0. 0. ]
[0. 0. 0. ... 0.01159441 0. 0. ]
...
[0. 0. 0. ... 0. 0. 0. ]
[0. 0.00610985 0. ... 0. 0.00547551 0. ]
[0. 0. 0. ... 0. 0. 0. ]]
更多推荐
已为社区贡献1条内容
所有评论(0)