如何让Scikit-learn NMF生成稀疏的基矩阵W?
关于sklearn NMF实现稀疏基矩阵W的参数调整问题
非负矩阵分解(NMF)因可生成稀疏基集而备受推崇,但使用sklearn.decomposition.NMF时,得到的因子并不稀疏。旧版NMF设有稀疏度参数beta,但新版已移除该参数,我希望得到真正稀疏的基矩阵W。
我尝试增大各类正则化参数(如alpha),但在Olivetti人脸数据集上无法达到Lee和Seung(1999)论文中的稀疏效果,结果仍近似特征脸。我已尝试调整alpha_W、l1_ratio及组件数量的多种组合,但问题依旧。
问题复现代码
from sklearn.datasets import fetch_olivetti_faces import matplotlib.pyplot as plt import numpy as np from sklearn.decomposition import NMF faces, _ = fetch_olivetti_faces(return_X_y=True) # run nmf on the faces data set num_nmf_components = 50 estimator = NMF(num_nmf_components, init='nndsvd', tol=5e-3, max_iter=1000, alpha_W=0.01, l1_ratio=0) H = estimator.fit_transform(faces) W = estimator.components_ # plot the basis faces n_row, n_col = 6, 4 # how many faces to plot image_shape = (64, 64) n_samples, n_features = faces.shape plt.figure(figsize=(10,12)) for face_id, face in enumerate(W[:n_row*n_col]): plt.subplot(n_row, n_col, face_id+1) plt.imshow(face.reshape(image_shape), cmap='gray') plt.axis('off') plt.tight_layout()
参数调整方案与解决思路
要在sklearn的NMF中实现基矩阵W的稀疏性,核心是利用L1正则化结合针对性的参数组合,以下是具体调整方向:
1. 启用L1正则化,调整l1_ratio
你当前设置l1_ratio=0,仅启用L2正则化(权重衰减),无法带来稀疏性。需要将l1_ratio设为大于0的值:
l1_ratio=1:仅使用L1正则化,对稀疏性的约束最强l1_ratio介于0-1之间:混合L1和L2正则化,平衡稀疏性与权重平滑性
2. 增大alpha_W的取值
alpha_W是施加在W上的正则化强度,值越大,稀疏性约束越强。你当前使用的0.01对于Olivetti数据集来说过小,可以尝试逐步增大到0.1、0.5甚至1.0,同时配合l1_ratio=1测试效果。
3. 调整组件数量num_nmf_components
Lee和Seung的论文中使用的组件数量可能与你设置的50不同,尝试减少组件数量(比如20-30),会迫使模型用更稀疏的基来重构数据,更容易得到类似论文中的稀疏基脸。
4. 优化初始化与迭代次数
- 保持
init='nndsvd'(非负双重奇异值分解初始化),这是适合稀疏性的初始化方式;也可尝试init='random'配合强正则化,有时能跳出局部最优。 - 增加
max_iter到2000甚至更高,确保正则化约束下模型能充分收敛。
调整后的示例代码
from sklearn.datasets import fetch_olivetti_faces import matplotlib.pyplot as plt import numpy as np from sklearn.decomposition import NMF faces, _ = fetch_olivetti_faces(return_X_y=True) # 调整后的参数设置 num_nmf_components = 30 estimator = NMF(num_nmf_components, init='nndsvd', tol=5e-3, max_iter=2000, alpha_W=0.5, l1_ratio=1.0) H = estimator.fit_transform(faces) W = estimator.components_ # 绘制基脸 n_row, n_col = 6, 4 image_shape = (64, 64) plt.figure(figsize=(10,12)) for face_id, face in enumerate(W[:n_row*n_col]): plt.subplot(n_row, n_col, face_id+1) plt.imshow(face.reshape(image_shape), cmap='gray') plt.axis('off') plt.tight_layout() plt.show()
补充说明
- 若上述调整后仍未达到预期,可尝试设置
beta_loss='kullback-leibler',KL散度损失相比默认的欧氏距离,更倾向于生成稀疏因子矩阵,配合正则化参数能进一步增强稀疏性。 - 注意正则化强度不要过大,否则会导致基矩阵过于稀疏而丧失数据重构能力,可通过
estimator.reconstruction_err_查看重构误差,在稀疏性与误差间做权衡。
内容的提问来源于stack exchange,提问作者eric
相关产品推荐
相关产品推荐

