非负矩阵分解(NMF)是一种无监督学习算法,目的在于提取有用的特征(可以识别出组合成数据的原始分量),也可以用于降维,通常不用于对数据进行重建或者编码。

  • NMF将每个数据点写成一些分量的加权求和(与PCA相同),并且分量和系数都大于0,
  • 只能适用于每个特征都是非负的数据(正负号实际上是任意的)。

1、将NMF应用于模拟数据

应用NMF时,我们必须保证数据是正的

如图

  • 两个分量的NMF:分量指向边界,所有的数据点都可以写成这两个分量的正数组合。

  • 一个分量的NMF:分量指向平均值,指向这里可以对数据做出最好的解释。

在NMF中,不存在“第一非负分量”,所有分量地位平等,减少分量个数会删除一些方向。NMF使用了随机初始化,根据随机种子的不同可能会产生不同的结果。

2、将NMF应用于人脸图像

NMF的主要参数(n_components参数):想要提取的分量个数。这个数字通常要小于输入特征的个数(否则将每个像素作为单独的分量就可以解释数据)。

(1)先观察一下运用NMF找到的15个分量长什么样

  from sklearn.datasets import fetch_lfw_people
from sklearn.decomposition import PCA
from sklearn.model_selection import train_test_split
import numpy as np
from matplotlib import pyplot as plt people = fetch_lfw_people(min_faces_per_person=40,resize=0.7)
image_shape = people.images[0].shape #每个人最多有50张照片,防止数据偏斜
mask = np.zeros(people.target.shape,dtype=bool)
for target in np.unique(people.target):
mask[np.where(people.target==target)[0][:50]]=1 X_people = people.data[mask]
y_people = people.target[mask] X_train, X_test, y_train, y_test = train_test_split(X_people,y_people,stratify=y_people,random_state=42) #画出nmf模型训练得到的各个分量(这里指定15个),每个分量都是一张有点人形的图片(因为每个分量保留了所有的原始特征)。
#所有的数据点都可以写成这些分量的加权求和 from sklearn.decomposition import NMF
nmf = NMF(n_components=15,random_state=0)
nmf.fit(X_train) X_train_nmf = nmf.transform(X_train)
X_test_nmf = nmf.transform(X_test) fix,axes = plt.subplots(3,5,figsize=(15,12),subplot_kw={'xticks':(),'yticks':()}) for i ,(component,ax) in enumerate(zip(nmf.components_,axes.ravel())):
ax.imshow(component.reshape(image_shape))
ax.set_title("{}.component".format(i))

(2)、按照某个分量,重建数据点

  #将数据样本点按照第10个分量排序,绘制数据点中前10张图片

  compn = 10

  inds = np.argsort(X_train_nmf[:,compn])[::-1] #按照第三个分量排序

  fig,axes = plt.subplots(2,5,figsize=(15,8),subplot_kw={'xticks':(),'yticks':()})

  for i ,(ind,ax) in enumerate(zip(inds,axes.ravel())):
ax.imshow(X_train[ind].reshape(image_shape))

  • 可以看出在所有数据点中,分量10排名前10的数据点长什么样(它们的具有分量10提取的特点,脸有点歪)
  • 每个分量提取了数据的不同模式,将这些分量叠加(加权求和)就能重构出训练集中的每一张图像。

3、应用于具有叠加结构的数据(信号源数据)

(1)先了解一下数据集

  S = mglearn.datasets.make_signals()
plt.figure(figsize=(10,2))
plt.plot(S,'-')
plt.xlabel("Time")
plt.ylabel("Signal")

  print(S.shape)
print(S) #输出 (2000, 3)
[[2.65408203 2.48908887 1.07757433]
[2.94981947 3.45507031 0.79929765]
[2.97649958 3.65235694 0.73473133]
...
[2.22337048 1.33481395 4.31421863]
[2.36722058 1.56522921 4.53698235]
[1.77945297 1.62362822 0.47660599]]
  • 可以看出该数据具有2000条,每条有对应三个信号源的数据

(2)将混合信号分解为原始分量

  • 我们假设有100台测量装置来观测混合信号,得到了2000条具有100维特征的信号数据X

    #将数据混合成100维的状态
    A = np.random.RandomState(0).uniform(size=(100,3))
    X = np.dot(S,A.T)
    print(X)
    print(X.shape)
  • 应用NMF还原这个混合信号

    #用nmf还原这三个信号被混合成100维的信号X
    
    nmf = NMF(n_components=3,random_state=42)
    S_nmf =nmf.fit_transform(X) #用于对比的pca pca = PCA(n_components=3,random_state=42)
    S_pca = pca.fit_transform(X) #S_pca就是H #画图 models = [X,S,S_nmf,S_pca]
    names = ["Obsevations(first measurements)",
    "Ture sourses",
    "NMF recovered signals",
    "PCA recovered signals"] fig, axes = plt.subplots(4,figsize=(10,5),gridspec_kw={'hspace':.5},subplot_kw={'xticks':(),'yticks':()}) for model,name,ax in zip(models,names,axes):
    ax.set_title(name)
    ax.plot(model,'-')

  • NMF在发现原始信号源时得到了不错的结果,而PCA失败了(PCA不适合这种叠加数据结构)
  • NMF生成的分量是没有顺序的,如果分量顺序和原始信号完全相同(线的颜色)只是偶然。

4、参考文献

《Pyhon机器学习基础教程》P120-P126

最新文章

  1. 百度地图坐标纠偏和转换工具和DLL
  2. [解决方案] pythonchallenge level 4
  3. C++学习笔记30:模板与型式参数化
  4. ServiceStack.OrmLite中的一些"陷阱"(3)
  5. hdu 2660 Accepted Necklace
  6. iOS开发——动画编程Swift篇&(三)CATransition动画
  7. 用vs2010调试javascript
  8. ASP.NET 母版页和内容页的加载顺序
  9. 记录java/javascript让浮点数显示两位小数的方法
  10. ADB——命令大全
  11. v4l2框架
  12. PHPCMS的使用
  13. AlarmManager的使用和七牛云android SDK上传图片
  14. Mysql5.6 make 错误以及解决办法
  15. 【Visual Studio】如何在VS 2012中打印变量值到输出窗口
  16. IIS中发布后出现Could not load file or assembly'System.Data.SQLite.dll' or one of its depedencies
  17. CF600E:Lomsat gelral(线段树合并)
  18. Unity3D深入浅出 -创造 物理材质(Physics Materials)
  19. Linux cmus
  20. Linux源码包安装和脚本安装

热门文章

  1. APICloud首款全功能集成开发工具重磅发布,彰显云端一体理念
  2. 【uniapp 开发】如何给边框添加阴影效果
  3. idea maven web项目tomcat本地部署
  4. docker搭建cordova 11环境
  5. LazyCaptcha自定义随机验证码和字体
  6. Python中使用模块和库编程
  7. Python 图_系列之基于<链接表>实现无向图最短路径搜索
  8. python---单链表的常用操作
  9. 前端CSS浮动、定位、溢出、z-index、透明度
  10. 另类终端「GitHub 热点速览 v.22.15」