没有运行时错误,但错误的虹膜PCA绘图

时间:2018-04-09 15:46:01

标签: python matplotlib scikit-learn pca

我正在使用以下代码在iris数据集上执行PCA:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns 

# get iris data to a dataframe: 
from sklearn import datasets
iris = datasets.load_iris() 
varnames = ['SL', 'SW', 'PL', 'PW']
irisdf = pd.DataFrame(data=iris.data, columns=varnames)
irisdf['Species'] = [iris.target_names[a] for a in iris.target]

# perform pca: 
from sklearn.decomposition import PCA
model = PCA(n_components=2)
scores = model.fit_transform(irisdf.iloc[:,0:4])
loadings = model.components_

# plot results: 
scoredf = pd.DataFrame(data=scores, columns=['PC1','PC2'])
scoredf['Grp'] = irisdf.Species
sns.lmplot(fit_reg=False, x="PC1", y='PC2', hue='Grp', data=scoredf) # plot point; 
loadings = loadings.T
for e, pt in enumerate(loadings):
    plt.plot([0,pt[0]], [0,pt[1]], '--b') 
    plt.text(x=pt[0], y=pt[1], s=varnames[e], color='b')
plt.show()

我得到以下情节:

enter image description here

然而,当我与其他网站的情节(例如http://marcoplebani.com/pca/)进行比较时,我的情节不正确。以下差异似乎存在:

  1. 花瓣长度和花瓣宽度线应具有相似的长度。
  2. 萼片长度线应更接近花瓣长度和花瓣宽度线,而不是靠近萼片宽度线。
  3. 所有4条线应位于x轴的同一侧。
  4. 为什么我的情节不正确。错误在哪里以及如何纠正?

1 个答案:

答案 0 :(得分:1)

这取决于您是否缩放方差。 "其他网站"使用scale=TRUE。如果您想使用sklearn执行此操作,请在拟合模型之前添加StandardScaler并使用缩放数据拟合模型,如下所示:

from sklearn.preprocessing import StandardScaler
X = StandardScaler().fit_transform(irisdf.iloc[:,0:4])
scores = model.fit_transform(X)

enter image description here

修改:StandardScalernormalize

之间的差异

这是an answer,它指出了一个关键的区别(行与列)。即使您在此处使用normalize,也可以考虑X = normalize(X.T).T。以下代码显示了转换后的一些差异:

import pandas as pd
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler, normalize

iris = datasets.load_iris() 
varnames = ['SL', 'SW', 'PL', 'PW']

fig, ax = plt.subplots(2, 2, figsize=(16, 12))

irisdf = pd.DataFrame(data=iris.data, columns=varnames)
irisdf.plot(kind='kde', title='Raw data', ax=ax[0][0])

irisdf_std = pd.DataFrame(data=StandardScaler().fit_transform(irisdf), columns=varnames)
irisdf_std.plot(kind='kde', title='StandardScaler', ax=ax[0][1])

irisdf_norm = pd.DataFrame(data=normalize(irisdf), columns=varnames)
irisdf_norm.plot(kind='kde', title='normalize', ax=ax[1][0])

irisdf_norm = pd.DataFrame(data=normalize(irisdf.T).T, columns=varnames)
irisdf_norm.plot(kind='kde', title='normalize', ax=ax[1][1])

plt.show()

enter image description here

我不确定算法/数学有多深。 StandardScaler的要点是在各要素之间获得统一/一致的均值和方差。假设具有大量测量单位的变量不一定(并且不应该)在PCA中占主导地位。换句话说,StandardScaler使得功能对PCA的贡献相同。如您所见,normalize不会给出一致的均值或方差。