目录
PCA转回原特征
例1
参考:
https://www.cnpython.com/qa/81148
sklearn的PCA 转换是怎样手算, 如何执行反变换。pca对象的哪个字段包含反变换的相关系数?如何计算反变换?
具体来说,我指的是sklearn.decomposition.PCA package中提供的PCA.inverse_transform()方法调用:如何使用PCA计算的各种系数重现其功能?
1)transform不是data * pca.components_。 首先,*不是numpy数组的点积。这是元素相乘。要执行点积,需要使用np.dot。 其次,PCA.components_的形状是(n个组件,n个特征),而要转换的数据形状是(n个样本,n个特征),因此需要对PCA.components_进行转置才能执行点积。 此外,变换的第一步是减去平均值,因此,如果手动进行,也需要首先减去平均值。 正确的转换方法是 data_reduced = np.dot(data - pca.mean_, pca.components_.T) 2)inverse_transform只是transform的逆过程 data_original = np.dot(data_reduced, pca.components_) + pca.mean_ 如果您的数据在每一列中的平均值已经为零,那么您可以忽略上面的pca.mean_ 在Scikit中,pca.components_就是P的逆矩阵, 逆转换时PCA.components不用求逆 import numpy as np from sklearn.decomposition import PCA pca = PCA(n_components=3) pca.fit(data) data_reduced = np.dot(data, pca.components_.T) # transform data_original = np.dot(data_reduced, pca.components_) # inverse_transform |
例2
参考:
https://www.cnblogs.com/okokok/p/6822885.html
在Scikit中运用PCA很简单
import numpy as np from sklearn import decomposition from sklearn import datasets iris = datasets.load_iris() X = iris.data y = iris.target pca = decomposition.PCA(n_components=3) pca.fit(X) X = pca.transform(X) |
以上代码是将含有4个特征的数据经过PCA压缩为3个特征。PCA的压缩由如下特点:
1.新的3个特征并不是随便删除一个特征后留下的,而是4个特征的线性组合。
2.新的3个特征保留了原有4个特征的绝大部分信息,换句话说就是略有损失。
那么PCA的损失到底是什么? 新特征能否转回旧特征?
首先看PCA过程:
PCA过程
1.均值化矩阵X
2.通过一系列矩阵运算得出 特征矩阵P
3.矩阵运算 Y = P * X
Y 即为原始数据降维后的结果,也就是说,得到矩阵P后,我们还可以通过Y=P * X这个算式, 反推回X:
Y = P * X ==> P(-1) * Y = P(-1) * P * X, P(-1)是P的逆矩阵, 即 P(-1) * P = 1
==> P(-1) * Y = X
需要注意的是,程序一开始就已经将原始数据均值化,所以实际上, P(-1)*Y的结果需要去均值化才是原来的样子
在Scikit中,pca.components_就是P的逆矩阵
转换过程源码:
1 def transform(self, X, y=None): 2 """Apply dimensionality reduction to X. 3 4 X is projected on the first principal components previously extracted 5 from a training set. 6 7 Parameters 8 ---------- 9 X : array-like, shape (n_samples, n_features) 10 New data, where n_samples is the number of samples 11 and n_features is the number of features. 12 13 Returns 14 ------- 15 X_new : array-like, shape (n_samples, n_components) 16 17 Examples 18 -------- 19 20 >>> import numpy as np 21 >>> from sklearn.decomposition import IncrementalPCA 22 >>> X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]]) 23 >>> ipca = IncrementalPCA(n_components=2, batch_size=3) 24 >>> ipca.fit(X) 25 IncrementalPCA(batch_size=3, copy=True, n_components=2, whiten=False) 26 >>> ipca.transform(X) # doctest: +SKIP 27 """ 28 check_is_fitted(self, ['mean_', 'components_'], all_or_any=all) 29 print self.mean_ 30 X = check_array(X) 31 if self.mean_ is not None: 32 X = X - self.mean_ 33 X_transformed = fast_dot(X, self.components_.T) 34 if self.whiten: 35 X_transformed /= np.sqrt(self.explained_variance_) 36 return X_transformed |
还原降维前数据:
iris = datasets.load_iris() X = iris.data y = iris.target print X[0] pca = decomposition.PCA(n_components=3) pca.fit(X) X = pca.transform(X) a = np.matrix(X) b = np.matrix(pca.components_) c = a * b mean_of_data = np.matrix([5.84333333, 3.054, 3.75866667, 1.19866667]) print c[0] print c[0] + mean_of_data |
scikit-learn中的PCA
PCA.inverse_transform()
X=pca.inverse_transform(newX) 将降维后的数据转换成原始数据 |
X=scaler.inverse_transform(X[, copy]) 将标准化后的数据转换为标准化之前的原始数据。 |
参考博文:
https://blog.csdn.net/u012162613/article/details/42192293
scikit-learn官方文档:
https://scikit-learn.org/stable/modules/generated/sklearn.decomposition.PCA.html#sklearn.decomposition.PCA
PCA的对象
components_ :返回具有最大方差的成分。
explained_variance_ratio_:返回所保留的n个成分各自的方差百分比。即每个成分(新特征)的方差大小
n_components_:返回所保留的成分个数n。
mean_:每个特征的均值
noise_variance_:
PCA对象的方法
fit(X,y=None)
fit()可以说是scikit-learn中通用的方法,每个需要训练的算法都会有fit()方法,它其实就是算法中的“训练”这一步骤。因为PCA是无监督学习算法,此处y自然等于None。
fit(X),表示用数据X来训练PCA模型。
函数返回值:调用fit方法的对象本身。比如pca.fit(X),表示用X对pca这个对象进行训练。
fit_transform(X)
用X来训练PCA模型,同时返回降维后的数据。
newX=pca.fit_transform(X),newX就是降维后的数据。
inverse_transform()
将降维后的数据转换成原始数据,将数据转换回其原始空间X=pca.inverse_transform(newX)
transform(X)
将数据X转换成降维后的数据。当模型训练好后,对于新输入的数据,都可以用transform方法来降维。
例子
>>> pca.n_components 1 >>> pca.explained_variance_ratio_ array([ 0.99910873]) >>> pca.explained_variance_ array([ 2.55427003]) >>> pca.get_params <bound method PCA.get_params of PCA(copy=True, n_components=1, whiten=False)> |
训练的pca对象的n_components值为1,即保留1个特征,该特征的方差为2.55427003,占所有特征的方差百分比为0.99910873,意味着几乎保留了所有的信息。get_params返回各个参数的值。
PCA.components_
核实PCA.components_中数值的意义
看公式推导, components的逆和转置是等价的吗?
PCA算法认为降维就是线性function,输入x与输出z之间是线性变换(linear transform),PCA 目标: 找变换系数W.
z=wx
从n个特征转换到m个特征:
$$ z_{1} = w^{1} \cdot x,\\ z_{2} = w^{2} \cdot x,\\ W = \begin{bmatrix} \left( w^{1} \right)^{T} \\ \left( w^{2} \right)^{T} \\ \vdots \\ \end{bmatrix} \\ \\ \Rightarrow z = Wx \\ \begin{bmatrix} z_{1} \\ z_{2} \\ \vdots \\ z_{m}\end{bmatrix} =\begin{bmatrix} \left( w^{1} \right)^{T} \\ \left( w^{2} \right)^{T} \\ \vdots \\ \end{bmatrix} \begin{bmatrix} x_{1} \\ x_{2} \\ \vdots \\ x_{n}\end{bmatrix} \\ \Rightarrow \begin{bmatrix} z_{1} \\ z_{2} \\ \vdots \\ z_{m}\end{bmatrix} =\begin{bmatrix} w^{1}_{1} & w^{1}_{2} & \cdots & w^{1}_{n} \\w^{2}_{1} & w^{2}_{2} & \cdots &w^{2}_{n}\\ & \vdots \\ w^{m}_{1} & w^{m}_{2} & \cdots &w^{m}_{n}\end{bmatrix} \begin{bmatrix} x_{1} \\ x_{2} \\ \vdots \\ x_{n}\end{bmatrix} \\ \Rightarrow \begin{bmatrix} z_{1} \\ z_{2} \\ \vdots \\ z_{m}\end{bmatrix} =\begin{bmatrix} w^{1}_{1} x_{1}+ w^{1}_{2}x_{2} + \cdots +w^{1}_{n}x_{n} \\w^{2}_{1} x_{1}+ w^{2}_{2} x_{2}+ \cdots +w^{2}_{n}x_{n} \\ \vdots \\ w^{m}_{1} x_{1}+ w^{m}_{2} x_{2}+ \cdots +w^{m}_{n}x_{n}\end{bmatrix}$$
其中每个组件为一个w^i, 考虑x中的所有特征, 形成z中的一个特征
PCA.components_.T的形状是
W(m个组件, n个特征)对应X(n个特征, k个样本)
components的逆和转置等价
因为变换矩阵W是正交阵, 正交阵的逆等于它的转置.
证明
单位正交矩阵:
$$ Q=\left[ \begin{matrix} \vdots & \vdots & & \vdots \\ q_1 & q_2& \dots & q_n \\ \vdots & \vdots & & \vdots \\ \end{matrix} \right] , q_i^Tq_j=\left\{ \begin{aligned} 0 & \ &when \ i\neq j \\ 1 & \ & when \ i=j \end{aligned} \right. \\ Q^TQ=\left[ \begin{matrix}q_1^T \\ q_2^T \\ \vdots \\ q_n^T \end{matrix} \right] \left[ \begin{matrix} q_1^T q_2^T \dots q_n^T\end{matrix} \right]=I $$
总结
PCA过程
1.均值化矩阵X
2.通过一系列矩阵运算得出 特征矩阵P
3.矩阵运算 Y = P * X
PCA转回原特征的公式
Y 即为原始数据降维后的结果,也就是说,得到矩阵P后,我们还可以通过Y=P * X这个算式, 反推回X:
Y = P * X ==> P(-1) * Y = P(-1) * P * X, P(-1)是P的逆矩阵, 即 P(-1) * P = 1
==> P(-1) * Y = X
需要注意的是,程序一开始就已经将原始数据均值化,所以实际上, P(-1)*Y的结果需要去均值化才是原来的样子
手刻逆转换
iris = datasets.load_iris() X = iris.data y = iris.target print X[0] pca = decomposition.PCA(n_components=3) pca.fit(X) X = pca.transform(X) a = np.matrix(X) b = np.matrix(pca.components_) c = a * b mean_of_data = np.matrix([5.84333333, 3.054, 3.75866667, 1.19866667]) print c[0] print c[0] + mean_of_data |
Sklearn逆转换
X=scaler.inverse_transform(X[, copy]) 将标准化后的数据转换为原始数据。 X=pca.inverse_transform(newX) 将降维后的数据转换成原始数据 |
PCA逆转换实验
创建pcaInverseDemo.py进行尝试
先试一下调包
sklearn的逆转换
建立简单矩阵, PCA转换, 输出值
import numpy as np from sklearn import decomposition # 建立简单矩阵 X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]]) # 将含有2个特征的数据经过PCA压缩为1个特征 pca = decomposition.PCA(n_components=1) pca.fit(X) X_pca = pca.transform(X) print("X_pca:\n",X_pca) |
X_pca: [[ 1.38340578] [ 2.22189802] [ 3.6053038 ] [-1.38340578] [-2.22189802] [-3.6053038 ]] |
再逆转换, 输出值
X_origin=pca.inverse_transform(X_pca) |
X_origin: [[-1.15997501 -0.75383654] [-1.86304424 -1.21074232] [-3.02301925 -1.96457886] [ 1.15997501 0.75383654] [ 1.86304424 1.21074232] [ 3.02301925 1.96457886]] |
如果维度降低, 则会损失信息, 如果进行PCA时维度不变, 则逆转换后值与原来相同
手刻PCA以及逆转换
PCA:
def pca(X, k): # k is the components you want # mean of each feature n_samples, n_features = X.shape mean = np.array([np.mean(X[:, i]) for i in range(n_features)]) # normalization norm_X = X - mean # scatter matrix scatter_matrix = np.dot(np.transpose(norm_X), norm_X) # Calculate the eigenvectors and eigenvalues eig_val, eig_vec = np.linalg.eig(scatter_matrix) eig_pairs = [(np.abs(eig_val[i]), eig_vec[:, i]) for i in range(n_features)] # sort eig_vec based on eig_val from highest to lowest eig_pairs = [((np.abs(eig_val[i])), eig_vec[:, i]) for i in range(len(eig_vec))] eig_pairs.sort(key=lambda x: x[0], reverse=True) # select the top k eig_vec feature = np.array([ele[1] for ele in eig_pairs[:k]]) # get new data new_data = np.dot(norm_X, np.transpose(feature)) return new_data X_pca = pca(X, 1).real#.real取得复数的实部 print("X_pca:\n",X_pca) |
X_pca: [[-1.38340578] [-2.22189802] [-3.6053038 ] [ 1.38340578] [ 2.22189802] [ 3.6053038 ]] |
和刚刚结果绝对值相同, 正负相反, 但是和原数据的正负还是保持一致的, 感觉没有大问题(有时间对照包源码找下原因)
逆转换:
def pca(X, k): # k is the components you want # mean of each feature n_samples, n_features = X.shape mean = np.array([np.mean(X[:, i]) for i in range(n_features)]) # normalization norm_X = X - mean # scatter matrix scatter_matrix = np.dot(np.transpose(norm_X), norm_X) # Calculate the eigenvectors and eigenvalues eig_val, eig_vec = np.linalg.eig(scatter_matrix) eig_pairs = [(np.abs(eig_val[i]), eig_vec[:, i]) for i in range(n_features)] # sort eig_vec based on eig_val from highest to lowest eig_pairs = [((np.abs(eig_val[i])), eig_vec[:, i]) for i in range(len(eig_vec))] eig_pairs.sort(key=lambda x: x[0], reverse=True) # select the top k eig_vec feature = np.array([ele[1] for ele in eig_pairs[:k]]) # get new data new_data = np.dot(norm_X, np.transpose(feature)) return new_data,feature,mean # X_pca = pca(X, 1)#可行 X_pca,X_components,X_mean = pca(X, 1) print("X_pca:\n",X_pca) X_origin=np.dot(X_pca, X_components)+X_mean print("X_origin:\n",X_origin) |
X_pca: [[-1.38340578] [-2.22189802] [-3.6053038 ] [ 1.38340578] [ 2.22189802] [ 3.6053038 ]] X_origin: [[-1.15997501 -0.75383654] [-1.86304424 -1.21074232] [-3.02301925 -1.96457886] [ 1.15997501 0.75383654] [ 1.86304424 1.21074232] [ 3.02301925 1.96457886]] |
结果与调包相同, 基本没问题