Scikit-learn中NMF自定义初始化H及固定H仅更新W的问题
解决Scikit-learn NMF自定义H初始化及固定H更新W的问题
刚好我之前也踩过Scikit-learn NMF的这些坑,给你一步步讲清楚怎么解决:
一、正确传入自定义初始化的H矩阵
你之前写的代码有两个小问题:
- 语法错误:
H=myInitializationH后面少了逗号,导致random_state=0的参数传递直接报错; - 使用
init='custom'时,必须同时提供初始的W和H矩阵(Scikit-learn的自定义初始化规则要求两个矩阵都要指定,不能只传其中一个)。
如果你的需求只是自定义H,W可以用随机非负矩阵初始化,那可以这么写:
import numpy as np from sklearn.decomposition import NMF # 假设你的输入数据是X,形状为(n_samples, n_features) n_samples, n_features = X.shape n_components = 2 # 自定义初始化H矩阵,注意形状必须是(n_components, n_features) myInitializationH = np.random.rand(n_components, n_features) # 随机生成W的初始值,形状为(n_samples, n_components) myInitializationW = np.random.rand(n_samples, n_components) # 正确初始化NMF模型 model = NMF(n_components=n_components, init='custom', W=myInitializationW, H=myInitializationH, random_state=0) W = model.fit_transform(X) # 此时model.components_就是你传入的H(如果没开启固定H的话,后续迭代会更新它)
要是不想手动生成W的初始值,也可以先用默认方法生成W,再替换成自定义H:
# 先初始化临时模型生成符合要求的W初始值 temp_model = NMF(n_components=n_components, init='random', random_state=0) temp_W = temp_model.fit_transform(X) # 再用自定义H初始化目标模型 model = NMF(n_components=n_components, init='custom', W=temp_W, H=myInitializationH, random_state=0) W = model.fit_transform(X)
二、固定H矩阵,仅更新W矩阵
Scikit-learn的NMF默认会同时迭代更新W和H,要固定H只更新W,我们可以继承NMF类,重写更新H的方法,让它直接返回原矩阵不做修改:
from sklearn.decomposition import NMF class FixedHNMF(NMF): def _update_h(self, X, W, H): # 重写H的更新逻辑,直接返回原H,完全不更新 return H # 使用自定义的FixedHNMF类初始化模型 model = FixedHNMF(n_components=n_components, init='custom', W=myInitializationW, H=myInitializationH, random_state=0) W = model.fit_transform(X) # 此时model.components_完全等于你传入的myInitializationH,只有W会根据输入数据X迭代优化
另外,如果你只是想基于已知的H求解最优W,也可以直接用非负最小二乘法,这种方法更高效:
from sklearn.linear_model import NonNegativeLeastSquares # 已知H,求解最优W(满足X ≈ W @ H,且W元素非负) nnls = NonNegativeLeastSquares(fit_intercept=False) W = nnls.fit_transform(X, H.T) # 这里转置H是因为NonNegativeLeastSquares默认处理的是X = y @ coef的形式,刚好对应我们的X = W @ H
这样就能完美满足你的需求啦~
内容的提问来源于stack exchange,提问作者kalonymus
相关产品推荐
相关产品推荐

