【发布时间】:2020-02-28 04:30:46
【问题描述】:
我想用类似于sklearn 中的类来实现 PCA。
我的寻找具有 k 个主成分的 PCA 的算法如下:
- 计算样本均值并转换数据集,使其以原点为中心。
- 计算新翻译集的协方差矩阵。
- 找出特征值和特征向量,按降序排列。
- 将数据集投影到由前 k 个特征向量跨越的向量空间。
import numpy as np
class MyPCA:
def __init__(self, n_components):
self.n_components = n_components
def fit_transform(self, X):
"""
Assumes observations in X are passed as rows of a numpy array.
"""
# Translate the dataset so it's centered around 0
translated_X = X - np.mean(X, axis=0)
# Calculate the eigenvalues and eigenvectors of the covariance matrix
e_values, e_vectors = np.linalg.eigh(np.cov(translated_X.T))
# Sort eigenvalues and their eigenvectors in descending order
e_ind_order = np.flip(e_values.argsort())
e_values = e_values[e_ind_order]
e_vectors = e_vectors[e_ind_order]
# Save the first n_components eigenvectors as principal components
principal_components = np.take(e_vectors, np.arange(self.n_components), axis=0)
return np.matmul(translated_X, principal_components.T)
但是,当在 Iris 数据集上运行时,此实现产生的结果与 sklearn 的结果大不相同,并且结果并未表明数据中存在三个不同的组:
from sklearn import datasets
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
def plot_pca_results(pca_class, dataset, plot_title):
X = dataset.data
y = dataset.target
y_names = dataset.target_names
pca = pca_class(n_components=1)
B = pca.fit_transform(X)
B = np.concatenate([B, np.zeros_like(B)], 1)
scatter = plt.scatter(B[:, 0], B[:, 1], c=y)
scatter_objects, _ = scatter.legend_elements()
plt.title(plot_title)
plt.legend(scatter_objects, y_names, loc="lower left", title="Classes")
plt.show()
dataset = datasets.load_iris()
plot_pca_results(MyPCA, dataset, "Iris - my PCA")
plot_pca_results(PCA, dataset, "Iris - Sklearn")
造成这种差异的原因可能是什么?我的方法在哪里,或者我的计算不正确?
【问题讨论】:
-
要对 PCA 的数据进行归一化,不仅需要 mean=0,还需要 stdev=1。类似
translated_X = (X - np.mean(X, axis=0))/np.std(X, axis=0) -
@krubo 即使在我应用了这个归一化/z-score 之后,结果仍然是关闭的。
标签: python numpy machine-learning pca