没有运行时错误,但 iris PCA 绘图错误
No runtime error, but wrong iris PCA plotting
我正在使用以下代码对 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/ )的绘图进行比较时,我的绘图不正确。似乎存在以下差异:
- 花瓣长度和花瓣宽度线的长度应该相似。
- 萼片长度线应该更接近花瓣长度和花瓣宽度线,而不是更接近萼片宽度线。
- 所有 4 条线都应位于 x 轴的同一侧。
为什么我的剧情不对。错误在哪里,如何纠正?
这取决于你是否缩放方差。 “其他站点”使用 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()
我不确定 algorithm/math 能深入到什么程度。 StandardScaler
的要点是获得 uniform/consistent 特征的均值和方差。假设是具有大测量单位的变量不一定(也不应该)在 PCA 中占主导地位。换句话说,StandardScaler
使特征对 PCA 的贡献相同。如您所见,normalize
不会给出一致的均值或方差。
我正在使用以下代码对 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/ )的绘图进行比较时,我的绘图不正确。似乎存在以下差异:
- 花瓣长度和花瓣宽度线的长度应该相似。
- 萼片长度线应该更接近花瓣长度和花瓣宽度线,而不是更接近萼片宽度线。
- 所有 4 条线都应位于 x 轴的同一侧。
为什么我的剧情不对。错误在哪里,如何纠正?
这取决于你是否缩放方差。 “其他站点”使用 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()
我不确定 algorithm/math 能深入到什么程度。 StandardScaler
的要点是获得 uniform/consistent 特征的均值和方差。假设是具有大测量单位的变量不一定(也不应该)在 PCA 中占主导地位。换句话说,StandardScaler
使特征对 PCA 的贡献相同。如您所见,normalize
不会给出一致的均值或方差。