线性判别分析逆变换

Bab*_*emi 5 python machine-learning dimensionality-reduction scikit-learn

我尝试使用scikit-learn 库中的线性判别分析,以便对具有 200 多个特征的数据执行降维。inverse_transform但我在LDA类中找不到该函数。

我只是想问,如何从LDA域中的一个点重建原始数据?

根据 @bogatron 和 @kazemakase 回答进行编辑:

我认为“原始数据”这个术语是错误的,我应该使用“原始坐标”或“原始空间”。我知道如果没有所有 PCA,我们就无法重建原始数据,但是当我们构建形状空间时,我们会在 PCA 的帮助下将数据投影到更低的维度。PCA 尝试仅用 2 或 3 个分量来解释数据,这些分量可以捕获数据的大部分方差,如果我们基于它们重建数据库,它应该向我们显示导致这种分离的形状部分。

我再次检查了 scikit-learn LDA 的源代码,我注意到特征向量存储在scalings_变量中。当我们使用svd求解器时,不可能反转特征向量 ( scalings_) 矩阵,但是当我尝试矩阵的伪逆时,我可以重建形状。

这里,有两个图像分别从 [ 4.28, 0.52] 和 [0, 0] 点重建:

来自[4.28,0.52] 从 [0, 0]

我认为如果有人深入解释 LDA 逆变换的数学局限性那就太好了。

kaz*_*ase 3

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]])
Run Code Online (Sandbox Code Playgroud)

如果我们有完整的矩阵,我们会得到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()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

你看,逆变换的结果与原始数据没有太大关系(嗯,可以猜测投影的方向)。相当一部分的变化已经永远消失了。