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

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

例如,使用PCA可以通过以下方式给出:
retainedVariance(i) = eigenvalue(i) / sum(eigenvalue)

有任何想法吗?

最佳答案

TL; DR

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

现在,我将解释原因。

PCA和NMF之间的关系

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


将输入X编码为压缩表示H
H解码回X',该值应尽可能接近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


如何衡量降维性能

如果要测量编码/解码算法的性能,可以按照通常的步骤进行:


X_train上训练编码器和解码器
要衡量样本内的效果,请使用您喜欢的指标(例如MAE,RMSE或解释的方差)将X_train'=decode(encode(X_train))X_train进行比较
要测量算法的样本外性能(泛化能力),请对看不见的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不能适应训练数据,但可能会提高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%的方差。请注意,这种情况是不寻常的,是由少量的培训和测试数据引起的:通常,测试集的性能会有所下降,但就我而言,它实际上有所改善。

10-05 19:40