问题 使用scikit-learn NMF和一组预先计算的基矢量(Python)


我想使用scikit-learn NMF(来自 这里)(或任何其他NMF,如果它完成工作,实际上)。

具体来说,我有一个输入矩阵(这是一个音频幅度谱图),我想分解它。

我已经预先计算了W矩阵。我该如何使用? 固定W. 在 sklearn.decompose.NMF?我还没有找到任何其他问题。

我看到 这个 方法也提到类似的东西 适合 参数:“如果为假,则假定组件已预先计算并存储在变压器中,并且不会更改。”但是,我不知道如何制作变换器对象。


12379
2018-06-10 22:29


起源



答案:


这部分代码 稍微解释了内部处理。

听起来你想修复W.根据代码,你只能修复H,同时优化W.这不是问题,因为你可以切换那些矩阵(反转他们的角色)。

这样做,代码说:使用 init='custom' 并设置 update_h=False

所以一般来说我会期望使用看起来像(基于示例 这里):

未经测试!

import numpy as np
X = np.array([[1,1], [2, 1], [3, 1.2], [4, 1], [5, 0.8], [6, 1]])

fixed_W = np.array([[1,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1])  # size=3 just an example
                                                                      # might break
fixed_H = fixed_W.T  # interpret W as H (transpose)

from sklearn.decomposition import NMF
model = NMF(n_components=2, init='custom', H=fixed_H, update_H=False, random_state=0)
model.fit(X) 

您可能希望在再次求解后切换变量。

编辑: 正如评论中所提到的,上面未经测试的代码将不起作用。 我们需要使用更低级别的功能来实现这一点。

这是一个快速入侵(我不关心正确的预处理; transpose和co。),这应该使你能够解决你的任务:

import numpy as np
X = np.array([[1,1], [2, 1], [3, 1.2], [4, 1], [5, 0.8], [6, 1]])

fixed_W = np.array([[0.4,0.4],[0.2,0.1]])  # size=2 just an example
fixed_H = fixed_W.T  # interpret W as H (transpose)

from sklearn.decomposition import NMF, non_negative_factorization

W, H, n_iter = non_negative_factorization(X, n_components=2, init='random', random_state=0)
print(W)
print(H)
print('error: ')
print(W.dot(H) - X)  # just a demo, it's not the loss minimized!

W, H, n_iter = non_negative_factorization(X, n_components=2, init='custom', random_state=0, update_H=False, H=fixed_H)
print(W)
print(H)
print('error: ')
print(W.dot(H) - X)

输出:

[[ 0.          0.46880684]
 [ 0.55699523  0.3894146 ]
 [ 1.00331638  0.41925352]
 [ 1.6733999   0.22926926]
 [ 2.34349311  0.03927954]
 [ 2.78981512  0.06911798]]
[[ 2.09783018  0.30560234]
 [ 2.13443044  2.13171694]]
error: 
[[  6.35579822e-04  -6.36528773e-04]
 [ -3.40231372e-04   3.40739354e-04]
 [ -3.45147253e-04   3.45662574e-04]
 [ -1.31898319e-04   1.32095249e-04]
 [  9.00218123e-05  -9.01562192e-05]
 [  8.58722020e-05  -8.60004133e-05]]
[[  3.           0.        ]
 [  5.           0.        ]
 [  4.51221142   2.98707026]
 [  0.04070474   9.95690087]
 [  0.          12.23529412]
 [  0.          14.70588235]]
[[ 0.4  0.2]
 [ 0.4  0.1]]
error: 
[[  2.00000000e-01  -4.00000000e-01]
 [ -2.22044605e-16  -1.11022302e-16]
 [ -2.87327549e-04   1.14931020e-03]
 [ -9.57758497e-04   3.83103399e-03]
 [ -1.05882353e-01   4.23529412e-01]
 [ -1.17647059e-01   4.70588235e-01]]

10
2018-06-11 11:18



感谢你的回答。但是,好像 H=fixed_H 是一个意外的关键字参数。 - pavlos163
@ pk1914你是对的。我们需要使用其他一些功能。 - sascha
看起来很棒!我还要提一下,我也必须调换一下 X 阵列。 - pavlos163
起初我很困惑,并意识到发生了什么。 Sklearn只能解决 X=WH 在保持第二个矩阵的同时 H 固定。为了解决这个问题,sascha解决了 X^T=H^T W^T,现在让sklearn保留第二个矩阵 W^T 固定,解决 H^T。非常聪明! - user3433489


答案:


这部分代码 稍微解释了内部处理。

听起来你想修复W.根据代码,你只能修复H,同时优化W.这不是问题,因为你可以切换那些矩阵(反转他们的角色)。

这样做,代码说:使用 init='custom' 并设置 update_h=False

所以一般来说我会期望使用看起来像(基于示例 这里):

未经测试!

import numpy as np
X = np.array([[1,1], [2, 1], [3, 1.2], [4, 1], [5, 0.8], [6, 1]])

fixed_W = np.array([[1,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1])  # size=3 just an example
                                                                      # might break
fixed_H = fixed_W.T  # interpret W as H (transpose)

from sklearn.decomposition import NMF
model = NMF(n_components=2, init='custom', H=fixed_H, update_H=False, random_state=0)
model.fit(X) 

您可能希望在再次求解后切换变量。

编辑: 正如评论中所提到的,上面未经测试的代码将不起作用。 我们需要使用更低级别的功能来实现这一点。

这是一个快速入侵(我不关心正确的预处理; transpose和co。),这应该使你能够解决你的任务:

import numpy as np
X = np.array([[1,1], [2, 1], [3, 1.2], [4, 1], [5, 0.8], [6, 1]])

fixed_W = np.array([[0.4,0.4],[0.2,0.1]])  # size=2 just an example
fixed_H = fixed_W.T  # interpret W as H (transpose)

from sklearn.decomposition import NMF, non_negative_factorization

W, H, n_iter = non_negative_factorization(X, n_components=2, init='random', random_state=0)
print(W)
print(H)
print('error: ')
print(W.dot(H) - X)  # just a demo, it's not the loss minimized!

W, H, n_iter = non_negative_factorization(X, n_components=2, init='custom', random_state=0, update_H=False, H=fixed_H)
print(W)
print(H)
print('error: ')
print(W.dot(H) - X)

输出:

[[ 0.          0.46880684]
 [ 0.55699523  0.3894146 ]
 [ 1.00331638  0.41925352]
 [ 1.6733999   0.22926926]
 [ 2.34349311  0.03927954]
 [ 2.78981512  0.06911798]]
[[ 2.09783018  0.30560234]
 [ 2.13443044  2.13171694]]
error: 
[[  6.35579822e-04  -6.36528773e-04]
 [ -3.40231372e-04   3.40739354e-04]
 [ -3.45147253e-04   3.45662574e-04]
 [ -1.31898319e-04   1.32095249e-04]
 [  9.00218123e-05  -9.01562192e-05]
 [  8.58722020e-05  -8.60004133e-05]]
[[  3.           0.        ]
 [  5.           0.        ]
 [  4.51221142   2.98707026]
 [  0.04070474   9.95690087]
 [  0.          12.23529412]
 [  0.          14.70588235]]
[[ 0.4  0.2]
 [ 0.4  0.1]]
error: 
[[  2.00000000e-01  -4.00000000e-01]
 [ -2.22044605e-16  -1.11022302e-16]
 [ -2.87327549e-04   1.14931020e-03]
 [ -9.57758497e-04   3.83103399e-03]
 [ -1.05882353e-01   4.23529412e-01]
 [ -1.17647059e-01   4.70588235e-01]]

10
2018-06-11 11:18



感谢你的回答。但是,好像 H=fixed_H 是一个意外的关键字参数。 - pavlos163
@ pk1914你是对的。我们需要使用其他一些功能。 - sascha
看起来很棒!我还要提一下,我也必须调换一下 X 阵列。 - pavlos163
起初我很困惑,并意识到发生了什么。 Sklearn只能解决 X=WH 在保持第二个矩阵的同时 H 固定。为了解决这个问题,sascha解决了 X^T=H^T W^T,现在让sklearn保留第二个矩阵 W^T 固定,解决 H^T。非常聪明! - user3433489