度量學習系列(2):有監督度量學習

有監督度量學習算法利用輸入點xx與目標標籤yy作爲來學習一個距離矩陣,這個距離矩陣拉近同類別的點(分類問題)或者目標值鄰近的點(迴歸問題)的距離,並使不同類別或目標值相差大的點的互相遠離。

1. 通用API

有監督的度量學習算法實質上利用了與scikit-learn相同的應用程序接口(API)。

1.1 輸入數據

爲了訓練一個模型,我們需要兩個array-like對象:XXyyXX應該爲 n×mn \times m的2D數組,其中nn爲樣本的個數,mm爲數據的維數。yy爲大小爲nn的一維數組,該數組包含XX中每個數據的類別標籤(迴歸問題是爲實數,例如度量學習核迴歸MLKR)。

下面給出用於度量學習的數據例子,數據中包含兩種類別:狗與貓。

import numpy as np
X = np.array([[2.3, 3.6], [0.2, 0.5], [6.7, 2.1]])
y = np.array(['dog', 'cat', 'dog'])

注意:我們也可以利用數據預處理器來替代直接給出2D數組形式的輸入,詳情請查閱Preprocessor一節。

1.2 Fit, transform以及其它

有監督度量學習算法的目標是爲了將數據轉換到新空間中,在該空間中,同類別的兩個數據點的距離會非常小,而不同類別的兩個數據的距離則很大。爲了得到這個轉換矩陣,我們需要利用訓練數據來fit度量學習器(例子:最近鄰成分分析NCA)。

>>> from metric_learn import NCA
>>> nca = NCA(random_state=42)
>>> nca.fit(X, y)
NCA(init=None, max_iter=100, n_components=None, num_dims='deprecated',
  preprocessor=None, random_state=42, tol=None, verbose=False)

上面的代碼塊已經fit了度量學習器nca,現在我們可以將nca用於新的數據上。

首先,我們可以利用transform將數據轉換到新的狀態空間。下面給出轉換兩個數據到嵌入空間的例子:

>>> X_new = np.array([[9.4, 4.1], [2.1, 4.4]])
>>> nca.transform(X_new)
array([[ 5.91884732, 10.25406973],
       [ 3.1545886 ,  6.80350083]])

通過以上步驟,我們的度量學習器已經學到了數據點之間的距離,我們有以下兩種使用它的途徑:

  • 我們可以利用score_pairs返回兩個數據點之間的距離:
>>> nca.score_pairs([[[3.5, 3.6], [5.6, 2.4]], [[1.2, 4.2], [2.1, 6.4]]])
array([0.49627072, 3.65287282])
  • 也可以利用get_metric函數返回兩個數據點之間的距離:
>>> metric_fun = nca.get_metric()
>>> metric_fun([3.5, 3.6], [5.6, 2.4])
0.4962707194621285

注意:如果度量學習是學習馬氏距離,我們可以利用get_mahalanobis_matrix得到學習到的矩陣。

>>> nca.get_mahalanobis_matrix()
array([[0.43680409, 0.89169412],
       [0.89169412, 1.9542479 ]])

2. 算法

2.1 LMNN

大邊緣最近鄰度量學習 Large Margin Nearest Neighbor Metric Learning (LMNN)

LMNN在kNN分類任務的前提下學習一個馬氏距離度量。學習到的度量嘗試保持同類別的K最近鄰很近,並將不同類別的數據以大邊緣隔離開來。該算法不對數據的分佈作假設。

該距離是通過求解以下優化問題來學習得到的:
minLi,jηi,jL(xixj)2+ci,j,lηi,j(1yi,j)[1+L(xixj)2L(xixl)2]+min_{L}\sum_{i,j}\eta_{i,j}||L(x_i-x_j)||^2+c\sum_{i,j,l}\eta_{i,j}(1-y_{i,j})[1+||L(x_i-x_j)||^2-||L(x_i-x_l)||^2]_{+}
此處,xix_i爲一數據點,xjx_jxix_i的一個具有相同標籤的k最近鄰點,xlx_l爲所有其它不同標籤的k最近鄰點,ηi,jyi,j{0,1}\eta_{i,j},y_{i,j}\in \{0,1\}都是指標參數,ηi,j\eta_{i,j}表示xjx_j爲與xix_i相同標籤的k最近鄰數,yi,j=0y_{i,j}=0表示xi,xjx_i,x_j屬於不同的類別,[]+[·]_{+}表示損失函數Hinge Loss。

import numpy as np
from metric_learn import LMNN
from sklearn.datasets import load_iris

iris_data = load_iris()
X = iris_data['data']
Y = iris_data['target']

lmnn = LMNN(k=5, learn_rate=1e-6)
lmnn.fit(X, Y, verbose=False)

參考文獻:
[1] Weinberger et al. Distance Metric Learning for Large Margin Nearest Neighbor Classification. JMLR 2009
[2] Wikipedia entry on Large Margin Nearest Neighbor

2.2 NCA

近鄰成分分析 Neighborhood Components Analysis (NCA)

NCA是一個距離度量學習算法,該度量算法旨在提升最近鄰分類器的精確度(與傳統歐式距離相比較)。算法直接最大化訓練集上留一法KNN評價器的隨機變量。它也可以用來學習一個低張維度的線性轉換矩陣,用於數據可視化和快速分類。

利用分解M=LTL\mathbf{M}=\mathbf{L}^T\mathbf{L},並定義概率pijp_{ij},此概率通過xix_i的鄰居xjx_j來對其進行正確分類的概率,如下通過馬氏距離意義下的softmax似然值表示:

pij=exp(LxiLxj22)liexp(LxiLxl22),pii=0 p_{i j}=\frac{\exp \left(-\left\|\mathbf{L} \mathbf{x}_{i}-\mathbf{L} \mathbf{x}_{j}\right\|_{2}^{2}\right)}{\sum_{l \neq i} \exp \left(-\left\|\mathbf{L} \mathbf{x}_{i}-\mathbf{L} \mathbf{x}_{l}\right\|_{2}^{2}\right)}, \quad p_{i i}=0
對每一個與xix_i近鄰的數據點,我們將上式計算的概率加和得到xix_i被正確分類的最終概率:
pi=j:ji,yj=yipij p_{i}=\sum_{j: j \neq i, y_{j}=y_{i}} p_{i j}
優化問題變爲找到矩陣L\mathbf{L}使得所有數據點的正確分類概率和最大:
L=argmaxipi \mathbf{L}=\operatorname{argmax} \sum_{i} p_{i}

import numpy as np
from metric_learn import NCA
from sklearn.datasets import load_iris

iris_data = load_iris()
X = iris_data['data']
Y = iris_data['target']

nca = NCA(max_iter=1000)
nca.fit(X, Y)

參考文獻:

[1] Goldberger et al. Neighbourhood Components Analysis. NIPS 2005
[2] Wikipedia entry on Neighborhood Components Analysis

2.3 LFDA

局部Fisher差別分析 Local Fisher Discriminant Analysis (LFDA)

LFDA是一個線性的有監督降維方法。該算法對於多模態問題特別有效,所謂的多模態就是一個或多個類別在狀態空間中包含多個獨立的聚集。LFDA的核心優化問題是一個廣義特徵值求解問題。

該算法定義Fisher局部的類內、類間散佈矩陣S(ω)/S(ω)\mathbf{S}^{(\omega)}/\mathbf{S}^{(\omega)}

S(w)=12i,j=1nWij(w)(xixj)(xixj)TS(b)=12i,j=1nWij(b)(xixj)(xixj)T \begin{aligned} \mathbf{S}^{(w)} &=\frac{1}{2} \sum_{i, j=1}^{n} W_{i j}^{(w)}\left(\mathbf{x}_{i}-\mathbf{x}_{j}\right)\left(\mathbf{x}_{i}-\mathbf{x}_{j}\right)^{T} \\ \mathbf{S}^{(b)} &=\frac{1}{2} \sum_{i, j=1}^{n} W_{i j}^{(b)}\left(\mathbf{x}_{i}-\mathbf{x}_{j}\right)\left(\mathbf{x}_{i}-\mathbf{x}_{j}\right)^{T} \end{aligned}

此處,
Wij(w)={0yiyjAi,j/nlyi=yjAi,j(1/n1/nl)yi=yj \begin{aligned} W_{i j}^{(w)}=\left\{\begin{array}{cc}{0} & {y_{i} \neq y_{j}} \\ {\mathbf{A}_{i, j} / n_{l}} & {y_{i}=y_{j}} \\ {\mathbf{A}_{i, j}\left(1 / n-1 / n_{l}\right)} & {y_{i}=y_{j}}\end{array}\right.\end{aligned}

Ai,j\mathbf{A}_{i,j}爲接近矩陣A\mathbf{A}(i,j)(i,j)個元素,A\mathbf{A}可以根據局部縮放方法來計算。

因此,學習問題變成推導LFDA變換矩陣TLFDA\mathbf{T}_{LFDA}
TLFDA=argmaxT[tr((TTS(w)T)1TTS(b)T)] \mathbf{T}_{L F D A}=\arg \max _{\mathbf{T}}\left[\operatorname{tr}\left(\left(\mathbf{T}^{T} \mathbf{S}^{(w)} \mathbf{T}\right)^{-1} \mathbf{T}^{T} \mathbf{S}^{(b)} \mathbf{T}\right)\right]

得到的變換矩陣T\mathbf{T}可保證同類中鄰近的數據靠的更近,不同類中的數據離的更遠,但是不能保證同類中離的遠的數據靠近。

import numpy as np
from metric_learn import LFDA
from sklearn.datasets import load_iris

iris_data = load_iris()
X = iris_data['data']
Y = iris_data['target']

lfda = LFDA(k=2, dim=2)
lfda.fit(X, Y)

參考文獻:

[1] Sugiyama. Dimensionality Reduction of Multimodal Labeled Data by Local Fisher Discriminant Analysis. JMLR 2007
[2] Tang. Local Fisher Discriminant Analysis on Beer Style Clustering.

2.4 MLKR

核迴歸度量學習 Metric Learning for Kernel Regression (MLKR)

MLKR是一個有監督度量學習算法,該算法通過直接最小化留一法迴歸誤差來學習一個距離函數。MLKR可以被看作爲一個有監督版本的PCA,能用於降維和高維數據可視化。

理論上,MLKR也能應用於許多不同形式的核函數和距離度量。此處,我們利用高斯核函數與馬氏距離。一個高斯核函數如下所示:

kij=12πσexp(d(xi,xj)σ2) k_{i j}=\frac{1}{\sqrt{2 \pi} \sigma} \exp \left(-\frac{d\left(\mathbf{x}_{i}, \mathbf{x}_{j}\right)}{\sigma^{2}}\right)

此處,d(,)d(·,·)爲某一測度下的距離平方,此處該測度爲馬氏距離,爲d(xi,xj)A(xixj)d(x_i,x_j)||\mathbf{A}(x_i-x_j)||A\mathbf{A}爲推導出的分解矩陣爲:M=ATA\mathbf{M}=\mathbf{A}^T\mathbf{A}

σ2\sigma^2可以歸併到d()d(·)中,此處我們簡單的設σ2=1\sigma^2=1。我們利用以下在訓練樣本上的累積留一法二次迴歸誤差作爲損失函數:

L=i(yiy^i)2 \mathcal{L}=\sum_{i}\left(y_{i}-\hat{y}_{i}\right)^{2}

此處,預測y^i\hat{y}_i是由核迴歸器得到的:
y^i=jiyjkijjikij \hat{y}_{i}=\frac{\sum_{j \neq i} y_{j} k_{i j}}{\sum_{j \neq i} k_{i j}}

from metric_learn import MLKR
from sklearn.datasets import load_iris

iris_data = load_iris()
X = iris_data['data']
Y = iris_data['target']

mlkr = MLKR()
mlkr.fit(X, Y)

參考文獻:

[1] Weinberger et al. Metric Learning for Kernel Regression. AISTATS 2007

2.5 有監督版本的弱監督度量學習算法

每一個弱監督度量學習算法都有一個對應的有監督版本*_Supervised,其中,相似元組從標籤信息中生成並傳遞給底層算法。

對於成對的學習者(參見“成對學習”),使用metric_learn.constraints.positive_negative_pair函數採樣成對(數據集中兩個點的元組)和成對標籤(int,表示這兩個點是相似的(+1)還是不同的(-1))。爲了對(標籤+1的)正對進行抽樣,該方法將對來自同一標籤的所有樣本進行抽樣,並從中隨機抽取一對樣本。爲了對負對(標籤-1)進行抽樣,該方法將查看來自不同類的所有樣本,並隨機抽取其中的一對樣本。該方法將嘗試構建num_constraints正對和num_constraints負對,但有時它找不到足夠的一個,因此強制same_length=True將返回兩個lenghts的最小值。
使用四元組學習器(見基於四元組的學習)以監督的方式,積極的和消極的對採樣如上和連接,這樣我們有一個3維四元組的數組,其中每個成套的一分之二點來自同一個類,最後兩個點來自不同的類(事實上類似最後兩點應該低於前兩個點)。

from metric_learn import MMC_Supervised
from sklearn.datasets import load_iris

iris_data = load_iris()
X = iris_data['data']
Y = iris_data['target']

mmc = MMC_Supervised(num_constraints=200)
mmc.fit(X, Y)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章