08無監督學習-降維NMF
NMF方法及例項
非負矩陣分解(NMF)
非負矩陣分解(Non-negative Matrix Factorization,NMF)是在矩陣中所有元素均為非負數約束條件之下的矩陣分解方法。
基本思想:給定一個非負矩陣V,NMF能夠找到一個非負矩陣W和一個非負矩陣H,使得矩陣W和H的乘積近似等於矩陣V中的值。
-
W矩陣:基礎影象矩陣,相當於從原矩陣V中抽取出來的特徵。
-
矩陣:係數矩陣。
-
NMF能夠廣泛應用於影象分析、文字挖掘和語音處理等領域。
下圖來自NMF原作者的論文:
左側是一個W矩陣,可以看出從原始影象中抽取出來的特徵,中間是一個H矩陣
將W矩陣和H矩陣相乘,得到右邊的一個結果
可以發現,這個結果矩陣和原矩陣是基本相像的
如何對矩陣進行分解
矩陣分解優化目標:最小化W矩陣H矩陣的乘積和原始矩陣之間的差別。
前面所給出的公式是基於歐氏距離的
基於KL散度的優化目標,損失函式如下:
W和H矩陣的具體求解方法,也就是他們的迭代演算法,參考連結: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,隨後將提取的特徵以影象的形式展示出來。
例項程式編寫
1、建立工程,匯入sklearn相關工具包:
# 載入matplotlib用於資料的視覺化 import matplotlib.pyplot as plt # 載入PCA演算法包 from sklearn import decomposition # 載入olivetti人臉資料集匯入函式 from sklearn.datasets import fetch_olivetti_faces # 載入RandomState用於建立隨機種子 from numpy.random import RandomState
2、設定基本引數並載入資料:
# 設定影象展示時的排列情況,兩行,一行3個
n_row, n_col = 2, 3
# 設定提取特徵的數目
n_components = n_col * n_row
# 設定人臉資料圖片的大小=6
image_shape = (64, 64)
# 載入資料,並將其打亂
dataset = fetch_olivetti_faces(shuffle=True, random_state=RandomState(0))
faces = dataset.data
3、設定影象的展示方式:
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.)
4、建立特徵提取的物件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))
]
# 將他們放在一個列表中
5、降維後資料點的視覺化:
# 分別呼叫PCA和NMF
for name, estimator in estimators:
# 呼叫PCA或NMF提取特徵值
estimator.fit(faces)
# 獲取提取的特徵值
components_ = estimator.components_
# 按照固定格式進行排列
plot_gallery(name, components_[:n_components])
# 視覺化
plt.show()
結果展示
用PCA演算法:
用NMF演算法
感覺用NMF提取的特徵值更加明顯