我正在使用以下代码在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()
我得到以下情节:
然而,当我与其他网站的情节(例如http://marcoplebani.com/pca/)进行比较时,我的情节不正确。以下差异似乎存在:
为什么我的情节不正确。错误在哪里以及如何纠正?
答案 0 :(得分:1)
这取决于您是否缩放方差。 "其他网站"使用scale=TRUE
。如果您想使用sklearn执行此操作,请在拟合模型之前添加StandardScaler
并使用缩放数据拟合模型,如下所示:
from sklearn.preprocessing import StandardScaler
X = StandardScaler().fit_transform(irisdf.iloc[:,0:4])
scores = model.fit_transform(X)
StandardScaler
和normalize
这是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()
我不确定算法/数学有多深。 StandardScaler
的要点是在各要素之间获得统一/一致的均值和方差。假设具有大量测量单位的变量不一定(并且不应该)在PCA中占主导地位。换句话说,StandardScaler
使得功能对PCA的贡献相同。如您所见,normalize
不会给出一致的均值或方差。