【机器学习】NMF (⾮负矩阵分解)
写在篇前
本篇⽂章主要介绍NMF算法原理以及使⽤sklearn中的封装⽅法实现该算法,最重要的是理解要NMF矩阵分解的实际意义,将其运⽤到⾃⼰的数据分析中!
理论概述
NMF(Non-negative matrix factorization),即对于任意给定的⼀个⾮负矩阵V,其能够寻找到⼀个⾮负矩阵W和⼀个⾮负矩阵H,满⾜条件V=W*H,从⽽将⼀个⾮负的矩阵分解为左右两个⾮负矩阵的乘积。**其中,V矩阵中每⼀列代表⼀个观测(obrvation),每⼀⾏代表⼀个特征(feature);W矩阵称为基矩阵,H矩阵称为系数矩阵或权重矩阵。这时⽤系数矩阵H代替原始矩阵,就可以实现对原始矩阵进⾏降
维,得到数据特征的降维矩阵,从⽽减少存储空间。**过程如下图所⽰:
nmf更详尽的原理可以参考,这⾥我主要列出我很关注的损失函数(lossFunction or objective function):
squared frobenius norm
其中:
为L1&L2正则化参数,⽽\rho为L1正则化占总正则化项的⽐例。||*||_1为L1范数。Kullback-Leibler (KL)
Itakura-Saito (IS)
∣∣A −W ,H arg min
21WH ∣∣+Fro 2αρ∣∣W ∣∣+1αρ∣∣H ∣∣+1∣∣W ∣∣+2α(1−ρ)Fro 2∣∣H ∣∣2
α(1−ρ)Fro 2∣∣A −21WH ∣∣=Fro 2(A −21i ,j ∑ij WH )ij 2
αd (X ,Y )=KL (X log()−i ,j ∑ij Y ij X ij X +ij Y )
ij
邮政挂号信实际上,上⾯三个公式是beta-divergence family中的三个特殊情况(分别是当),其原型是:
代码实现
代码解读
新概念2课后答案
在sklearn封装了NMF的实现,可以⾮常⽅便我们的使⽤,其实现基本和前⾯理论部分的实现是⼀致的,但是注意sklearn中输⼊数据的格式是(samples, features):
from sklearn .decomposition import NMF
from sklearn .datats import load_iris
X , _ = load_iris (True )
# can be ud for example for dimensionality reduction, source paration or topic extraction
# 个⼈认为最重要的参数是n_components 、alpha 、l1_ratio 、solver
nmf = NMF (n_components =2, # k value,默认会保留全部特征
init =None , # W H 的初始化⽅法,包括'random' | 'nndsvd'(默认) | 'nndsvda' | 'nndsvdar' | 'custom'.
solver ='cd', # 'cd' | 'mu'
beta_loss ='frobenius', # {'frobenius', 'kullback-leibler', 'itakura-saito'},⼀般默认就好
tol =1e -4, # 停⽌迭代的极限条件
max_iter =200, # 最⼤迭代次数
random_state =None ,
alpha =0., # 正则化参数
l1_ratio =0., # 正则化参数
verbo =0, # 冗长模式
shuffle =Fal # 针对"cd solver"
)
# -----------------函数------------------------
print ('params:', nmf .get_params ()) # 获取构造函数参数的值,也可以nmf.attr 得到,所以下⾯我会省略这些属性
# 下⾯四个函数很简单,也最核⼼,例⼦中见
nmf .fit (X )
W = nmf .fit_transform (X )
W = nmf .transform (X )
nmf .inver_transform (W )
# -----------------属性------------------------
H = nmf .components_ # H 矩阵
print ('reconstruction_err_', nmf .reconstruction_err_) # 损失函数值
print ('n_iter_', nmf .n_iter_) # 实际迭代次数注意点:
init 参数中,nndsvd (默认)更适⽤于spar factorization,其变体则适⽤于den factorization.solver 参数中,如果初始化中产⽣很多零值,Multiplicative Update (mu ) 不能很好更新。所以mu ⼀般不和nndsvd 使⽤,⽽和其变体nndsvda 、nndsvdar 使⽤。
solver 参数中,cd 只能优化Frobenius norm函数;⽽mu 可以更新所有损失函数
案例1
d (X ,Y )=IS (−i ,j ∑Y ij X ij
log()−Y ij X ij 1)
β=2,1,0d (X ,Y )=β(X +i ,j ∑β(β−1)1ij β(β−1)Y −ij ββX Y )
ij ij β−1
第⼀个案例很简单,⽬的是理解分解出来的这两个矩阵能⽤来⼲嘛,分别是什么意思,但是其实我在⽂章第⼀部分已经解释了,直接看例⼦:
>>>import numpy as np
漕运总督
>>> X = np.array([[1,1],[2,1],[3,1.2],[4,1],[5,0.8],[6,1]])
>>>from sklearn.decomposition import NMF
女主重生的小说>>> model = NMF(n_components=2, init='random', random_state=0)
>>> W = model.fit_transform(X)
>>> H = ponents_
>>> X_new = np.array([[1,0],[1,6.1],[1,0],[1,4],[3.2,1],[0,4]])
>>> W_new = ansform(X_new)
>>> W_new # 输出 W_new
array([[0.35919303],
[0.86264547],
[0.35919303],
[0.68932578],
[1.23195088],
[0.33013275]])
ok,这个⼩例⼦就说明了我们通过NMF获得系数矩阵H,并⽤系数矩阵H获得新矩阵W_new的基矩阵,实现W_new的数据降维(or 特征提取)。实际上,这时W_new = ansform(X_new)做的⼯作相当于:
np.mat(X_new)*(np.mat(H).I)
matrix([[0.35919303],
[0.86264547],
[0.35919303],
[0.68932578],
[1.23195088],
[0.33013275]])
案例2
这⾥再举⼀个NMF在图像特征提取的应⽤,来⾃,根据我的需要改动了⼀些:
from time import time
from numpy.random import RandomState
import matplotlib.pyplot as plt
from sklearn.datats import fetch_olivetti_faces
from sklearn import decomposition
n_row, n_col =2,3
n_components = n_row * n_col
image_shape =(64,64)
rng = RandomState(0)
# >>>>>>>>>>>>>>>##动物大世界# Load faces data
datat = fetch_olivetti_faces('./',True,
random_state=rng)
faces = datat.data
n_samples, n_features = faces.shape
print("Datat consists of %d faces, features is %s"%(n_samples, n_features))
def plot_gallery(title, images, n_col=n_col, n_row=n_row, ay):
plt.figure(figsize=(2.* n_col,2.26* n_row))
plt.suptitle(title, size=16)
for i, comp in enumerate(images):
plt.subplot(n_row, n_col, i +1)
vmax =max(comp.max(),-comp.min())
plt.shape(image_shape), cmap=cmap,
interpolation='nearest',
vmin=-vmax, vmax=vmax)
plt.subplots_adjust(0.01,0.05,0.99,0.93,0.04,0.)
# >>>>>>>>>>>>>>>## estimators =[('Non-negative components - NMF',
三国马超decomposition.NMF(n_components=n_components, init='nndsvda', tol=5e-3))
]
# >>>>>>>>>>>>>>>## # Plot a sample of the input dataplot_gallery("First centered Olivetti faces", faces[:n_components])
班主任工作漫谈
# >>>>>>>>>>>>>>>## # Do the estimation and plot itfor name, estimator in estimators:
print("Extracting the top %d %s..."%(n_components, name))
t0 = time()
data = faces
estimator.fit(data)
train_time =(time()- t0)
print("done in %0.3fs"% train_time)
components_ = ponents_
print('components_:', components_.shape,'\n**\n', components_)
plot_gallery('%s - Train time %.1fs'%(name, train_time),
components_)
plt.show()
#---------------------------其他注释---------------------------
V矩阵:400*4096
W矩阵:400*6
H矩阵:6*4096
下⾯是script运⾏结果:
处理的英语写在篇后
NMF最早由科学家D.D.Lee和H.S.Seung提出的⼀种⾮负矩阵分解⽅法,并在Nature发表⽂章《Learning the parts of objects by non-negative matrix factorization》。随后也有了很多NMF变体,
应⽤也越发⼴泛,包括⽂本降维、话题提取、图像处理等。这⾥必须指出,我看到⼀份NMF⾮常完整的资料,但是精⼒有限,不能全⾯cover,有兴趣的同学可以参考。