机器学习(四)降维之NMF及人脸特征提取

一.非负矩阵分解(Non-negative Matrix Factorization ,NMF)

是在矩阵中所有元素均为非负数约束条件之下的矩阵分解方法。
基本思想:给定一个非负矩阵V,NMF能够找到一个非负矩阵W和一个非负矩阵H,使得矩阵W和H的乘积近似等于矩阵V中的值。

• W矩阵:基础图像矩阵,相当于从原矩阵V中抽取出来的特征
• H矩阵:系数矩阵。
• NMF能够广泛应用于图像分析、文本挖掘和语音处理等领域

上图摘自NMF作者的论文,左侧为W矩阵,可以看出从原始图像中抽取出
来的特征,中间的是H矩阵。可以发现乘积结果与原结果是很像的。

矩阵分解优化目标:最小化W矩阵H矩阵的乘积和原始矩阵之间的差别,目标函数如下:

基于KL散度的优化目标,损失函数如下:

公式推导的参考链接:http://blog.csdn.net/acdreamers/article/details/44663421/

sklearn中非负矩阵分解

在sklearn库中,可以使用sklearn.decomposition.NMF加载NMF算法,主要参数有:
• n_components:用于指定分解后矩阵的单个维度k;
• init:W矩阵和H矩阵的初始化方式,默认为‘nndsvdar’。

二.NMF人脸数据特征提取

目标:已知Olivetti人脸数据共400个,每个数据是64*64大小。由于NMF分解得到的W矩阵相当于从原始矩阵中提取的特征,那么就可以使用NMF对400个人脸数据进行特征提取。

通过设置k的大小,设置提取的特征的数目。在本实验中设置k=6,随后将提取的特征以图像的形式展示出来。

import matplotlib.pyplot as plt
from sklearn import decomposition
#加载PCA算法包
from  sklearn.datasets import fetch_olivetti_faces
#加载人脸数据集
from numpy.random import RandomState
#加载RandomState用于创建随机种子

n_row,n_col = 2,3
#设置图像展示时的排列情况,2行三列
n_components = n_row = n_col
#设置提取的特征的数目
image_shape = (64,64)
#设置人脸数据图片的大小
dataset = fetch_olivetti_faces(shuffle=True,random_state=RandomState(0))
faces = dataset.data#加载数据,并打乱顺序

#设置图像的展示方式
def plot_gallery(title,images,n_col=n_col,n_row=n_row):
    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.imshow(comp.reshape(image_shape),cmap=plt.cm.gray,interpolation='nearest',vmin=-vmax,vmax=vmax)#对数值归一化,并以灰度图形式显示
        plt.xticks(())
        plt.yticks(())#去除子图的坐标轴标签
    plt.subplots_adjust(0.01,0.05,0.99,0.93,0.04,0.)

#创建特征提取的对象NMF,使用PCA作为对
estimators=[('Eigenfaces - PCA using randomized SVD',decomposition.PCA(n_components=6,whiten=True)),('Non-negative components - NMF',decomposition.NMF(n_components=6,init='nndsvda',tol=5e-3))]
#NMF和PCA实例,将它们放在一个列表中

#降维后数据点的可视化
for name,estimators in estimators:#分别调用PCA和NMF
    estimators.fit(faces)#调用PCA或NMF提取特征
    components_=estimators.components_#获取提取特征
    plot_gallery(name,components_[:n_components])
    #按照固定格式进行排列
plt.show()#可视化

发布了219 篇原创文章 · 获赞 13 · 访问量 9789

猜你喜欢

转载自blog.csdn.net/qq_35812205/article/details/104327701