【问题标题】:computing first principal component of sklearn's PCA计算 sklearn 的 PCA 的第一个主成分
【发布时间】:2018-09-06 07:27:05
【问题描述】:

我有以下代码成功计算了我的数据的最大主成分:

lst = ['date', 'MA(1,9)', 'MA(1,12)', 'MA(2,9)', 'MA(2,12)', 'MA(3,9)', 'MA(3,12)', 'MOM(9)', 'MOM(12)', 'VOL(1,9)', 'VOL(1,12)', 'VOL(2,9)', 'VOL(2,12)', 'VOL(3,9)', 'VOL(3,12)']
df = pd.read_excel(filename, sheet_name='daily', header=0, names=lst)
df = df.set_index('date')
df = df.loc[start_date:end_date]
pca = PCA()
pca = pca.fit(df)
print(pca.components_)
#print(pca.explained_variance_[0])
df = pd.DataFrame(pca.transform(df), columns=['PCA%i' % i for i in range(14)], index=df.index)

有什么方法可以不用自己计算就能成功得到第一个主成分? (sklearn 是否有某种我找不到的属性?)

我的数据:

            MA(1,9)  MA(1,12)  MA(2,9)  MA(2,12)  MA(3,9)  MA(3,12)  MOM(9)  \
date                                                                          
1990-06-08        1         1        1         1        1         1       1   
1990-06-11        1         1        1         1        1         1       1   
1990-06-12        1         1        1         1        1         1       1   
1990-06-13        1         1        1         1        1         1       1   
1990-06-14        1         1        1         1        1         1       1   

            MOM(12)  VOL(1,9)  VOL(1,12)  VOL(2,9)  VOL(2,12)  VOL(3,9)  \
date                                                                      
1990-06-08        1         1          0         1          1         1   
1990-06-11        1         1          1         1          1         1   
1990-06-12        1         0          0         1          1         1   
1990-06-13        1         0          0         1          1         1   
1990-06-14        1         0          0         1          1         1   

            VOL(3,12)  
date                   
1990-06-08          1  
1990-06-11          1  
1990-06-12          1  
1990-06-13          1  
1990-06-14          1  

输出:

                 PCA0      PCA1      PCA2      PCA3      PCA4      PCA5  \
date                                                                     
1990-06-08 -0.707212  0.834228  0.511333  0.104279 -0.055340 -0.117740   
1990-06-11 -0.685396  1.224009 -0.059560 -0.038864 -0.011676 -0.031021   
1990-06-12 -0.737770  0.445458  1.083377  0.237313 -0.075061  0.012465   
1990-06-13 -0.737770  0.445458  1.083377  0.237313 -0.075061  0.012465   
1990-06-14 -0.737770  0.445458  1.083377  0.237313 -0.075061  0.012465   
1990-06-15 -0.715954  0.835239  0.512485  0.094170 -0.031397  0.099184   
1990-06-18 -0.715954  0.835239  0.512485  0.094170 -0.031397  0.099184   
1990-06-19 -0.702743 -0.024860  0.185254 -0.976475 -0.028151  0.090701     
...              ...       ...       ...       ...       ...       ...    
2015-05-01 -0.636410 -0.440222 -1.139295 -0.229937  0.088941 -0.055738   
2015-05-04 -0.636410 -0.440222 -1.139295 -0.229937  0.088941 -0.055738   

                PCA6      PCA7      PCA8      PCA9     PCA10     PCA11  \
date                                                                     
1990-06-08 -0.050111  0.000652  0.062524  0.066524 -0.683963  0.097497   
1990-06-11 -0.053740  0.013313  0.008949 -0.006157  0.002628 -0.010517   
1990-06-12 -0.039659 -0.029781  0.009185 -0.026395 -0.006305 -0.019026   
1990-07-19 -0.053740  0.013313  0.008949 -0.006157  0.002628 -0.010517   
1990-07-20 -0.078581  0.056345  0.386847  0.056035 -0.044696  0.013128   
...              ...       ...       ...       ...       ...       ...   
2015-05-01  0.066707  0.018254  0.009552  0.002706  0.008036  0.000745   
2015-05-04  0.066707  0.018254  0.009552  0.002706  0.008036  0.000745   

               PCA12     PCA13  
date                            
1990-06-08  0.013466 -0.020638  
...              ...       ...  
2015-05-04  0.001502  0.004461  

以上是更新代码的输出,但它似乎是错误的输出。 “第一主成分”定义为:

这种变换的定义方式是,第一个主成分 > 具有最大可能的方差(即,尽可能多地解释数据中的 > 可变性),并且每个后续成分依次具有 >在它与>前面的组件正交的约束下可能的最大方差。

简单地抓取 PCA 的第一列是否符合与上述定义相同的过程?

【问题讨论】:

    标签: pandas numpy scikit-learn pca


    【解决方案1】:

    您始终可以使用PCA().fit_transform(df).iloc[:, 0],这将为您提供每行第一个 PC 轴上的值。

    【讨论】:

    • 第一个主成分并不意味着轴上的第一个值,它有一个特定的定义
    • 当然,但是既然您已经从您的问题中了解了.components_,我认为您正在寻找第一个 PC 轴上的数据点的值,因为您已经打印出您的主要组件并在最后两行将数据转换到 PC 空间。
    • 但是,如果您只是在寻找主成分本身,那就是 - 正如 Stefan Falk 正确指出的 - PCA.components_[0]
    【解决方案2】:

    PCA 对象有一个成员 components_,它在调用 fit() 后保存组件。

    来自docs

    components_:数组,形状(n_components,n_features)

    特征空间中的主轴,表示数据中最大方差的方向。组件按explained_variance_排序。

    例子:

    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn.decomposition import PCA
    
    np.random.seed(42)
    
    df = pd.DataFrame(np.concatenate([np.random.rand(50, 5), np.random.rand(50, 5) + 1]))
    
    pca = PCA(n_components=2).fit(df)
    
    print(pca.components_)
    

    输出:特征空间中的两个分量

    [[-0.43227251 -0.47497776 -0.41079902 -0.47411737 -0.44044691]
     [ 0.41214174 -0.54429826 -0.55429329  0.34990399  0.32280758]]
    

    说明:

    如文档中所述,这些向量已按其explained_variance_ 排序。这意味着通过抓取第一个向量pca.components_[0],您将收到具有最高方差的向量(由pca.explained_variance_[0] 给出)。


    可以将其可视化。正如您在上面的代码中看到的,我们想要找到方差最大的两个组件(PCA(n_components=2))。通过进一步调用pca.transform(df),我们所做的就是将数据投影到这些组件上。这将产生一个大小为 (n_samples, n_components) 的矩阵 - 这也意味着我们可以绘制它。

    我们还可以转换pca.components_ 给出的向量,以便在低维空间中查看这两个组件。为了使绘图更有意义,我首先将转换后的分量标准化为长度 1,并通过它们解释的方差进一步对其进行缩放,以突出它们的重要性。

    t = pca.transform(df)
    ax = plt.figure().gca()
    ax.scatter(t[:,0], t[:,1], s=5)
    
    transf_components = pca.transform(pca.components_)
    
    for i, (var, c) in enumerate(zip(pca.explained_variance_, transf_components)):
        # The scaling of the transformed components for the purpose of visualization
        c = var * (c / np.linalg.norm(c))    
        ax.arrow(0, 0, c[0], c[1], head_width=0.06, head_length=0.08, fc='r', ec='r')
        ax.annotate('Comp. {0}'.format(i+1), xy=c+.08)
    
    plt.show()
    

    给予:


    特别更新:

    在评论区和你聊天后:不妨看看FactorAnalysissee also):

    请注意,df 现在是一个具有二进制值的矩阵(就像您的原始数据一样)

    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn.decomposition import FactorAnalysis
    
    np.random.seed(42)
    
    n_features = 20
    
    # After 50 samples we "change the behavior"
    df = pd.DataFrame(1*np.concatenate([np.random.rand(50, n_features) > .25, 
                                        np.random.rand(50, n_features) > .75]))
    
    # I chose n_components here totally arbitrary (< n_features) ..
    
    fa = FactorAnalysis(n_components=5).fit(df)
    t = fa.transform(df)
    
    ax = plt.figure().gca()
    ax.plot(t[:,0])
    ax.axvline(50, color='r', linestyle='--', alpha=.5) 
    

    输出:

    【讨论】:

    • 啊,既然它们已经排序,我可以抓取每个子列表的第一个元素,这是我每行的第一个主成分?
    • @ÉvaristeGalois 没错。 pca.components_[0] 将是第一个组件,依此类推。
    • pca.components_[0] 是一个列表,那么pca.components_[0][0] 不是第一个组件吗?
    • @ÉvaristeGalois 嗯,不,整个向量是(主)分量。正如文档所说,它是(n_components,n_features)。我已经稍微调整了我的答案以将它们可视化。
    • 所以,我正在尝试获取 6275 行,每行 14 个组件的主组件,我更新了 OP,使用了我相信您在此处为我解释的代码,但是输出似乎非常不正确.我错过了什么吗?
    猜你喜欢
    • 1970-01-01
    • 2015-07-29
    • 2013-03-28
    • 1970-01-01
    • 2021-07-19
    • 2015-07-03
    • 1970-01-01
    • 1970-01-01
    • 2014-10-10
    相关资源
    最近更新 更多