无监督学习——非负矩阵分解(NMF)

article/2025/9/21 14:13:52

非负矩阵分解(NMF)是一种无监督学习算法,其目的在于提取有用的特征。它的工作原理类似于PCA,也可以用于降维。与PCA相同,我们试图将每个数据点写成一些分量的加权求和。但在PCA中,我们想要的是正负分量,并且能够解释尽可能多的数据方差;而在NMF中,我们希望分量和系数均为负,也就是说,我们希望分量和系数都大于或等于0。因此,NMF只能应用于每个特征都是非负的数据,因为非负分量的非负求和不可能变为负值。

将数据分解成非负加权求和的这个过程,对由多个独立源相加(或叠加)创建而成的数据特别有用,比如多人说话的音轨或包含很多乐器的音乐。在这种情况下,NMF可以识别出组合成数据的原始分量。总的来说,与PCA相比,NMF得到的分量更容易解释,因为负的分量和系数可能会导致难以解释的抵消效应。

PCA原理传送门:无监督学习与主成分分析(PCA)

接下来,我们将NMF应用于人脸识别。

NMF实际应用

1.数据源

数据是之前我们已经处理好的人脸图像数据,一共有15个人物,每个人有10张头像。想了解具体处理过程的可以去看一下主成分分析(PCA)应用——特征提取_人脸识别(上)。

提数代码如下:

import os
all_folds = os.listdir(r'C:\Users\Administrator\Desktop\源数据-分析\lfw_funneled')###https://www.kaggle.com/atulanandjha/lfwpeople?select=pairs.txt
all_folds = [x for x in all_folds if '.' not in x]
import pandas as pd 
numbers_img=pd.DataFrame(columns=["文件名称","图片数量"])####统计各个文件夹里面的图片数量
for i in range(len(all_folds)):path = 'C:\\Users\\Administrator\\Desktop\\源数据-分析\\lfw_funneled\\'+all_folds[i]all_files = os.listdir(path)numbers_img.loc[i]=[all_folds[i],len(all_files)]   
img_10=numbers_img[numbers_img["图片数量"]==10].reset_index()#####为了降低数据偏斜,选取图片数量为10的文件(否则,特征提取会被图片数量过多的数据影响)
from PIL import Image 
import numpy as np
image_arr_list=[]###存放灰度值numpy数组
flat_arr_list=[]###存放灰度值一维数组
target_list=[]###存放目标值
for m in range(len(img_10["文件名称"])):file_address='C:\\Users\\Administrator\\Desktop\\源数据-分析\\lfw_funneled\\'+img_10["文件名称"][m]+"\\"####指定特定的文件地址image_name=os.listdir(file_address)###获得指定文件夹下的左右文件名称for n in image_name:image=Image.open(file_address+n)image=image.convert('L')###RGB(红绿蓝)像素值转换成灰度值image_arr=np.array(image,"f")###灰度值转化成numpy数组(二维)flat_arr=image_arr.ravel()###将数组扁平化处理,返回的是一个一维数组的非副本视图,就是将几行的数据强行拉成一行image_arr_list.append(image_arr)flat_arr_list.append(flat_arr)target_list.append(m)###这里的m设定是数字,如果是文本的话后面的算法会报错
faces_dict={"images":np.array(image_arr_list),"data":np.array(flat_arr_list),"target":np.array(target_list)}

2.建模

提取完数据集之后,我们划分数据集为训练集和测试集,并用核向量算法SVM来进行建模和评估。

SVM算法讲解传送门:支持向量机(SVM)算法之补充说明

from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.svm import SVC
train=faces_dict["data"]/255
X_train,X_test,y_train,y_test=train_test_split(train,faces_dict["target"],random_state=0)###划分训练集和测试集
clf = SVC(kernel="linear",random_state=0)
clf.fit(X_train, y_train)#训练
y_predict = clf.predict(X_test)#预测
print(accuracy_score(y_test, y_predict))#评分

结果如下:

在这里插入图片描述

这样,我们就得到了一个精度为23.6%的模型。

3.NMF处理

NMF的主要参数是我们想要提取的分量个数——n_components。通常来说,这个数字要小于输入特征的个数(否则的话,将每个像素作为单独的分量就可以对数据进行解释)。代码如下:

from sklearn.decomposition import NMF
nmf=NMF(n_components=20,random_state=0,max_iter=10000).fit(X_train)###增加最大迭代次数,不然会预警
X_train_nmf=nmf.transform(X_train)
X_test_nmf=nmf.transform(X_test)
clf=SVC(kernel="linear",random_state=0)
clf.fit(X_train_nmf,y_train)#训练
clf_predict=clf.predict(X_test_nmf)
print(accuracy_score(y_test,clf_predict))

需要注意的是,如果特征值过多的话,NMF默认的迭代次数便会限制模型的精度,并且预警。所以我们还需要设立下NMF的最大迭代次数。最后得到的结果如下:

在这里插入图片描述

通常来说,提取的特征越多,即n_components越大,模型的精度就越高,但是模型的训练时间也就越长。这里我就不再继续尝试了,感兴趣的朋友们可以试试改变n_components的值来提高模型精度。

与PCA的比较

PCA对于数据特征的处理是找到特征重建的最佳方向。而NMF通常并不用于对数据进行重建或者编码。而是寻找用于数据中的有趣的模式。正如我们之前提到的一样,NMF最适合于具有叠加结构的数据,包括音频,基因表达和文本数据。接下来我们通过一段模拟信号来与PCA比较一下。

假设有一段信号,它是由三个不同的信号源组成的,代码如下:

import mglearn
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']###防止中文显示不出来
plt.rcParams['axes.unicode_minus'] = False###防止坐标轴符号显示不出来
S=mglearn.datasets.make_signals()
plt.figure(figsize=(10,1))
plt.plot(S,"_")
plt.xlabel("Time")
plt.ylabel("Signal")

在这里插入图片描述

不幸的是,我们无法观测到原始信号,只能观测到三个信号的叠加混合。而我们的目的便是将混合信号分解成原信号。假设我们有100台测量装置,每个测量装置都为我们提供了一系列测量结果。所以接下来我们将数据混合成100维的状态:

A=np.random.RandomState(0).uniform(size=(100,3))###假设有100台装置测量混合信号
X=np.dot(S,A.T)###将数据混合成100维的状态

接下来,我们分别用NMF和PCA来还原这三个信号:

from sklearn.decomposition import PCA
pca=PCA(n_components=3)
H=pca.fit_transform(X)
nmf=NMF(n_components=3,max_iter=10000,random_state=0)
S_=nmf.fit_transform(X)

最后,我们将结果画出来:

models=[X,S,S_,H]
names=["观测信号","真实信号","非负矩阵(NMF)还原信号","主成分分析(PCA)还原信号"]
fig,axes=plt.subplots(4,figsize=(10,10),gridspec_kw={"hspace":1},subplot_kw={"xticks":(),"yticks":()})
plt.figure(figsize=(6,1))
for model,name,ax in zip(models,names,axes):ax.set_title(name)ax.plot(model[:,:3],"_")

在这里插入图片描述

可以看到,NMF在发现原始信号源是得到了不错的成果,而PCA的表现却很差,仅使用第一个成分来解释数据中的大部分变化。

这里需要注意的是,NMF生成的分量是没有顺序的。在上面的例子中,NMF分量的顺序与原始信号完全相同(可以从三条线的颜色看出来),但这纯属偶然。

总结

除了PCA和NMF之外,还有许多算法可用于将每个数据点分解为一系列固定分量的加权求和。通常描述对分量和系数的约定会涉及到概率论。如果朋友们对这种类型的模式感兴趣,可以去看下scikit-learn中关于独立成分分析(ICA),因子分析(FA)和稀疏编码(字典学习)等。

个人博客:https://www.yyb705.com/
欢迎大家来我的个人博客逛一逛,里面不仅有技术文,也有系列书籍的内化笔记。
有很多地方做的不是很好,欢迎网友来提出建议,也希望可以遇到些朋友来一起交流讨论。


http://chatgpt.dhexx.cn/article/rvgdnMsa.shtml

相关文章

非负矩阵分解NMF

http://blog.csdn.net/pipisorry/article/details/52098864 非负矩阵分解(NMF,Non-negative matrix factorization) NMF的发展及原理 著名的科学杂志《Nature》于1999年刊登了两位科学家D.D.Lee和H.S.Seung对数学中非负矩阵研究的突出成果。该文提出了一种新的矩阵分解思想—…

非负矩阵分解(NMF)的Matlab实例与说明

原理啥的到处都有,就直接跳过了。这里主要是NMF的基础实验。下一篇是NMF的高光谱实验总结。 1. matlab示例解说 这一节的图片来自官方文档。 这里第一和第三变量在第一行的值0.6945和0.62220对W的第一列有相当强的权重。第一个第二变量在第二行的值0.8020和0.568…

【机器学习】NMF(非负矩阵分解)

写在篇前 本篇文章主要介绍NMF算法原理以及使用sklearn中的封装方法实现该算法,最重要的是理解要NMF矩阵分解的实际意义,将其运用到自己的数据分析中! 理论概述 NMF(Non-negative matrix factorization),即对于任意给定的一个非负…

vs快捷键与vs自定义快捷键

文章目录 :star: 主题:VS快捷键1.常用的默认快捷键2.自定义快捷键2.1 添加快捷键2.2 移除快捷键2.3 重置快捷键,恢复默认 :bookmark: 小结 ⭐️ 主题:VS快捷键 📍 来自:中南林业科技大学软件协会学术部:谢…

vs注释与反注释快捷键

使用VS C语言编译器的快捷注释按键: 选中部分注释: Ctrl KD (按住Ctrl然后先按K再按D) 注释前: 注释后: 反注释: Ctrl KU (按住Ctrl然后先按K再按U) 操作完就恢复了…

VS(visual studio)注释快捷键及自定义设置

注释: CtrlKC 取消注释: CtrlKU 【工具】→【选项】→【环境】→【键盘】→【搜索注释】 点击【编辑.注释选定内容】→【移除】 输入快捷键,点击【分配】→【确定】 取消注释的自定义快捷键同理设置即可,注释和取消注释不…

Visual Studio Code2022无法使用注释快捷键

用了一个月vscode,使用ctrl/发现注释始终无法使用,最开始一直以为是系统或者版本问题,因为之前机器做过一次修改机器码的操作。 今天尝试解决了一下,发现问题可以通过键盘映射方案进行解决 文件->账户设置或者右上角头像图标 搜…

vs2019注释快捷键设置

vs2019默认的注释快捷键为ctrl+k+c 取消注释快捷键为ctrl+k+u 我们也可以自己设置 当然,也可以设置自己习惯的快捷键

VS中的设置和快捷键

一.相关设置 1.设置主题颜色 【工具】-》【选项】-》【常规】,选择主题颜色为浅色,点击确定。 2.设置背景颜色 【工具】-》【选项】-》【字体和颜色】,项背景颜色那里,点击自定义。 HSB(HSL)&#xff1a…

VS注释快捷键整理

在 Visual Studio IDE 中使用快捷键注释代码,无论是行注释还是块注释,第一步一定是选中要注释的内容(取消注释同样要先选中)! 当然,如果是行注释,不必选取整行,将光标定位到该行即可…

javassh客户端_简单的Java SSH客户端

javassh客户端 可以使用jcabi-ssh在Java中通过几行代码通过SSH执行shell命令: String hello = new Shell.Plain(new SSH("ssh.example.com", 22,"yegor", "-----BEGIN RSA PRIVATE KEY-----...") ).exec("echo Hello, world!"); jca…

Java打造一款SSH客户端,而且已开源

点击上方“Java基基”,选择“设为星标” 做积极的人,而不是积极废人! 源码精品专栏 原创 | Java 2020 超神之路,很肝~中文详细注释的开源项目RPC 框架 Dubbo 源码解析网络应用框架 Netty 源码解析消息中间件 RocketMQ 源码解析数…

最新版本spring框架下载

首先spring的各种好就不说了;主要是最近spring将官网地址www.springsource.org改为了http://spring.io/(新网站设计的比较舒服,这难道是奔商业化的节奏去的吗?!);同时spring将原来比较容易找到的…

用 Java 打造一款 SSH 客户端,这个太强了。。

前言 最近由于项目需求,项目中需要实现一个WebSSH连接终端的功能,由于自己第一次做这类型功能,所以首先上了GitHub找了找有没有现成的轮子可以拿来直接用,当时看到了很多这方面的项目,例如:GateOne、webssh、shellinabox等。 这些项目都可以很好地实现webssh的功能,但…

Java 打造一款 SSH 客户端,已开源~

来源:https://blog.csdn.net/NoCortY/article/details/104772431 前言 最近由于项目需求,项目中需要实现一个WebSSH连接终端的功能,由于自己第一次做这类型功能,所以首先上了GitHub找了找有没有现成的轮子可以拿来直接用&#x…

官网下载最新版本Spring

目录 官网下载步骤官网下载地址 官网下载步骤 官网地址:https://spring.io/projects/spring-framework 1.点击右上角 Git 图标 2. 进入Spring的Git仓库 3. 进入Spring Framework Artifacts后点击"https://repo.spring.io" 4.进入Spring repository&a…

SSH框架整合demo

Struts、Spring、Hibernate整合 一、创建web工程,搭建Struts框架开发环境: 这里只导入了项目中所需要的重要的jar包,以后根据业务要求继续导入相关的包。 步骤1::导入struts框架所需的jar包步骤2:在web.xml中配置stru…

Spring的下载

Spring是一个独立的框架,他不需要依赖于任何Web服务器或容器,既可以在独立的javaSE项目中使用,也可以在JavaEE项目中使用,在使用Spring之前需要获取它的JAR包,下面就是Spring下载的详细过程。 1.使用浏览器访问Spring…

Web SSH 客户端工具

webssh简介 如何在浏览器web页面登录我们的linux机器,这个工具是使用Python开发 官网:https://pypi.org/project/webssh/ webssh这个工具可以干啥?? 在linux机器上安装python环境,并且使用命令pip3 install webssh,…

web版ssh工具

本系统后端使用springboot框架,持久层使用mybatis,jsch实现ssh,sftp连接,前端使用xterm.js,vue,elementplus框架,使用vue3-sfc-loader加载vue文件,无需使用npm包管理器 系统登录 系统注册 登录后主机资源树…