如何比较 PCA 和 NMF 的预测能力



我想将算法的输出与不同的预处理数据进行比较:NMF和PCA。 为了以某种方式获得可比较的结果,我想选择解释例如 95% 保留方差的量,而不是为每个 PCA 和 NMF 选择相同数量的分量。

我想知道是否有可能确定 NMF 的每个组件中保留的方差。

例如,使用 PCA,这将由下式给出:retainedVariance(i) = eigenvalue(i) / sum(eigenvalue)

有什么想法吗?

TL;博士

应遍历不同的n_components,并在每次迭代时估计解码Xexplained_variance_score。这将显示您需要多少个分量来解释 95% 的方差。

现在我将解释原因。

PCA与NMF的关系

NMF和PCA与许多其他无监督学习算法一样,旨在做两件事:

  • 输入X编码为压缩表示H;
  • 解码HX',这应该尽可能接近X

他们以某种类似的方式做到这一点:

  • 在PCA和NMF中,解码是相似的:它们输出X' = dot(H, W),其中W是一个学习矩阵参数。
  • 编码是不同的。在PCA中,它也是线性的:H = dot(X, V),其中V也是一个学习参数。在 NMF 中,H = argmin(loss(X, H, W))(仅针对H),其中lossXdot(H, W)之间的均方误差,加上一些额外的惩罚。最小化是通过坐标下降执行的,结果在X中可能是非线性的。
  • 培训也不同。PCA按顺序学习:第一个分量在没有约束的情况下最小化MSE,接下来的每个分量k分量最小化残余MSE,但须与前一个分量正交。NMF 最大限度地减少了与编码时相同的loss(X, H, W),但现在在HW方面。

如何衡量降维的性能

如果要测量编码/解码算法的性能,可以执行常规步骤:

  1. X_train上训练编码器+解码器
  2. 要测量样本内性能,请使用您的首选指标(例如 MAE、RMSE 或解释方差)将X_train'=decode(encode(X_train))X_train进行比较
  3. 要测量算法的样本外性能(泛化能力),请使用看不见的X_test执行步骤 2

让我们用PCANMF试试吧!

from sklearn import decomposition, datasets, model_selection, preprocessing, metrics
# use the well-known Iris dataset
X, _ = datasets.load_iris(return_X_y=True)
# split the dataset, to measure overfitting
X_train, X_test = model_selection.train_test_split(X, test_size=0.5, random_state=1)
# I scale the data in order to give equal importance to all its dimensions
# NMF does not allow negative input, so I don't center the data
scaler = preprocessing.StandardScaler(with_mean=False).fit(X_train)
X_train_sc = scaler.transform(X_train)
X_test_sc = scaler.transform(X_test)
# train the both decomposers
pca = decomposition.PCA(n_components=2).fit(X_train_sc)
nmf = decomposition.NMF(n_components=2).fit(X_train_sc)
print(sum(pca.explained_variance_ratio_))

它将打印您解释的方差比0.9536930834362043- PCA 的默认指标,使用其特征值估计。我们可以以更直接的方式衡量它 - 通过将指标应用于实际值和"预测"值:

def get_score(model, data, scorer=metrics.explained_variance_score):
""" Estimate performance of the model on the data """
prediction = model.inverse_transform(model.transform(data))
return scorer(data, prediction)
print('train set performance')
print(get_score(pca, X_train_sc))
print(get_score(nmf, X_train_sc))
print('test set performance')
print(get_score(pca, X_test_sc))
print(get_score(nmf, X_test_sc))

这给了

train set performance
0.9536930834362043 # same as before!
0.937291711378812 
test set performance
0.9597828443047842
0.9590555069007827

您可以看到,在训练集上,PCA 的性能优于 NMF,但在测试集上,它们的性能几乎相同。发生这种情况是因为 NMF 应用了大量正则化

  • HW(学习的参数)必须是非负数
  • H应尽可能小(L1 和 L2 处罚)
  • W应尽可能小(L1 和 L2 处罚)

这些正则化使 NMF 对训练数据的拟合比可能的更差,但它们可能会提高其泛化能力,这在我们的例子中发生了。

如何选择组件数量

PCA中,它很简单,因为它的组件h_1, h_2, ... h_k是按顺序学习的。如果添加新组件h_(k+1),则第一个k不会更改。因此,您可以估计每个组件的性能,这些估计值不会根据组件的数量而定。这使得 PCA 可以在仅对数据进行一次拟合后输出explained_variance_ratio_数组。

NMF更复杂,因为它的所有组件都是同时训练的,每个组件都依赖于所有其他组件。因此,如果添加第k+1个分量,则前k分量将更改,并且您无法将每个特定分量与其解释的方差(或任何其他指标)匹配。

但是您可以做的是为每个分量数拟合一个新的NMF实例,并比较总解释方差:

ks = [1,2,3,4]
perfs_train = []
perfs_test = []
for k in ks:
nmf = decomposition.NMF(n_components=k).fit(X_train_sc)
perfs_train.append(get_score(nmf, X_train_sc))
perfs_test.append(get_score(nmf, X_test_sc))
print(perfs_train)
print(perfs_test)

这将给

[0.3236945680665101, 0.937291711378812, 0.995459457205891, 0.9974027602663655]
[0.26186701106012833, 0.9590555069007827, 0.9941424954209546, 0.9968456603914185]

因此,需要三个分量(通过训练集性能判断)或两个分量(通过测试集)来解释至少 95% 的方差。请注意,这种情况是不寻常的,是由少量的训练和测试数据引起的:通常在测试集上性能会下降一点,但在我的情况下,它实际上有所改善。