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

Phi*_*l D 13 pca dimensionality-reduction scikit-learn matrix-factorization nmf

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

我想知道是否有可能确定NMF每个组成部分保留的差异.

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

有任何想法吗?

Dav*_*ale 19

TL; DR

你应该在每次迭代时循环不同n_components并估计explained_variance_score解码X.这将显示您需要多少组件来解释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仅限于),其中lossX和之间的均方误差dot(H, W),加上一些额外的惩罚.通过坐标下降来执行最小化,并且结果可以是非线性的X.
  • 培训也不同.PCA顺序学习:第一个组件在没有约束的情况下最小化MSE,每个下一个k组件最小化残余MSE,使其与先前组件正交.NMF最小化与loss(X, H, W)编码时相同,但现在关于两者HW.

如何衡量降维性能

如果要测量编码/解码算法的性能,可以按照常规步骤操作:

  1. 训练您的编码器+解码器 X_train
  2. 为了测量样品中的性能,比较X_train'=decode(encode(X_train))X_train用你喜欢的度量(例如MAE,RMSE,或解释方差)
  3. 要测量算法的样本外性能(泛化能力),请使用看不见的方法执行步骤2 X_test.

让我们尝试它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_))
Run Code Online (Sandbox Code Playgroud)

它将打印您解释的方差比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))
Run Code Online (Sandbox Code Playgroud)

这使

train set performance
0.9536930834362043 # same as before!
0.937291711378812 
test set performance
0.9597828443047842
0.9590555069007827
Run Code Online (Sandbox Code Playgroud)

您可以看到,在训练集上,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+1th个组件,则第一个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)
Run Code Online (Sandbox Code Playgroud)

这会给

[0.3236945680665101, 0.937291711378812, 0.995459457205891, 0.9974027602663655]
[0.26186701106012833, 0.9590555069007827, 0.9941424954209546, 0.9968456603914185]
Run Code Online (Sandbox Code Playgroud)

因此,需要三个组件(通过列车组性能判断)或两个组件(通过测试组)来解释至少95%的方差.请注意,这种情况很不寻常,并且由于培训和测试数据量较小而导致:通常性能会在测试集上降低一点,但在我的情况下,它实际上有所改善.