参考花书《深度学习》实现一个简易版PCA,并和sklearn比较了一下,还是有些许差别,还不知道为什么存在差别,有大佬知道的可以指点一下。
知道了,原来需要中心化数据,让输入样本的均值为零(已修改)。
import numpy as np
from sklearn.decomposition import PCA
import matplotlib.pyplot as plot
class MyPCA:
def __init__(self, n_components):
self.l = n_components
def fit(self, X: np.ndarray):
self.n = X.shape[1]
if self.n < self.l:
raise ValueError("data_dimensions must equal or greater than n_components!")
X = self.centralize(X)
__, __, e_vecs = np.linalg.svd(X)
e_vecs = e_vecs.T
# 这是由最小化 所有训练样本的 重投影误差或者说恢复误差 来推导得到的D的值(就是一些线性代数推导)
self.D = e_vecs[:, :self.l]
#中心化 数据
def centralize(self, X):
self.mean = np.mean(X, axis=0)
if X.dtype != self.mean.dtype:
X = X.astype(self.mean.dtype)
return X - self.mean
def transform(self, X: np.ndarray):
n = X.shape[1]
if n != self.n:
raise Exception("DimensionError: 测试数据维度和训练集不一致!")
X = self.centralize(X)
return X.dot(self.D)
def inverse_transform(self, X):
# 这是一开始定义的重投影形式,也是PCA所有推导的出发点
return X.dot(self.D.T)+self.mean # 恢复 数据
def fit_transform(self, X):
self.fit(X)
return self.transform(X)
n_components = 1
X = np.array([[-3, -2, 1, 1], [-2, -1, 2, 3], [-1, -1, 3, 5], [1, 1, 4, 7], [2, 1, 5, 9], [3, 2, 6, 11]])
plot.scatter(X[:, 0], X[:, 1])
plot.show()
print("X:\n", X)
print("####################MyPCA###########################")
pca = MyPCA(n_components=n_components)
newX = pca.fit_transform(X) # 等价于pca.fit(X) pca.transform(X)
invX = pca.inverse_transform(newX) # 将降维后的数据转换成原始数据
print("newX:\n", newX)
print("invX:\n", invX)
print("####################sklean PCA###########################")
pca = PCA(n_components=n_components)
newX = pca.fit_transform(X) # 等价于pca.fit(X) pca.transform(X)
invX = pca.inverse_transform(newX) # 将降维后的数据转换成原始数据
print("newX:\n", newX)
print("invX:\n", invX)