LDA 的逆不一定有意义,因为它丢失了很多信息。
为了比较,请考虑 PCA。在这里,我们得到一个用于转换数据的系数矩阵。我们可以通过从矩阵中剥离行来进行降维。为了得到逆变换,我们首先反转整个矩阵,然后删除对应于被删除行的列。
LDA 没有给我们一个完整的矩阵。我们只得到一个不能直接反转的简化矩阵。可以采用伪逆,但这比使用完整矩阵时效率要低得多。
考虑一个简单的例子:
C = np.ones((3, 3)) + np.eye(3) # full transform matrix
U = C[:2, :] # dimensionality reduction matrix
V1 = np.linalg.inv(C)[:, :2] # PCA-style reconstruction matrix
print(V1)
#array([[ 0.75, -0.25],
# [-0.25, 0.75],
# [-0.25, -0.25]])
V2 = np.linalg.pinv(U) # LDA-style reconstruction matrix
print(V2)
#array([[ 0.63636364, -0.36363636],
# [-0.36363636, 0.63636364],
# [ 0.09090909, 0.09090909]])
如果我们有完整的矩阵,我们会得到一个不同的逆变换 (V1),而不是我们简单地逆变换 (V2)。 这是因为在第二种情况下,我们丢失了有关废弃组件的所有信息。
您已被警告。如果你仍然想做逆 LDA 变换,这里有一个函数:
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.decomposition import PCA
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.utils.validation import check_is_fitted
from sklearn.utils import check_array, check_X_y
import numpy as np
def inverse_transform(lda, x):
if lda.solver == 'lsqr':
raise NotImplementedError("(inverse) transform not implemented for 'lsqr' "
"solver (use 'svd' or 'eigen').")
check_is_fitted(lda, ['xbar_', 'scalings_'], all_or_any=any)
inv = np.linalg.pinv(lda.scalings_)
x = check_array(x)
if lda.solver == 'svd':
x_back = np.dot(x, inv) + lda.xbar_
elif lda.solver == 'eigen':
x_back = np.dot(x, inv)
return x_back
iris = datasets.load_iris()
X = iris.data
y = iris.target
target_names = iris.target_names
lda = LinearDiscriminantAnalysis()
Z = lda.fit(X, y).transform(X)
Xr = inverse_transform(lda, Z)
# plot first two dimensions of original and reconstructed data
plt.plot(X[:, 0], X[:, 1], '.', label='original')
plt.plot(Xr[:, 0], Xr[:, 1], '.', label='reconstructed')
plt.legend()
您看,逆变换的结果与原始数据没有太大关系(好吧,可以猜测投影的方向)。相当一部分的变化已经消失了。