主成分分析(Principal Component Analysis)

Step 1:去相关(Decorrelation)

Step 2: 降维(Reduce Dimension)

数据是文本时


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()
没有“去相关”前 length VS width
“去相关”后 length VS width

# 引入皮尔逊相关系数量化“去相关”前后的变化
# 导入相关库
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()
width & length 的第一主成分由箭头看出

         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()

Variance of the PCA features

可以从结果图看出,有两个特征,其中“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.        ]]

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐