【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

Uniqe發表於2022-03-21

在上一節介紹了一種最常見的降維方法PCA,本節介紹另一種降維方法LLE,本來打算對於其他降維演算法一併進行一個簡介,不過既然看到這裡了,就對這些演算法做一個相對詳細的學習吧。


0.流形學習簡介

在前面PCA中說到,PCA是一種無法將資料進行拉直,當直接對於曲面進行降維後,導致資料的重疊,難以區分,如下圖所示:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

這是因為在使用PCA降維時,PCA僅僅關注於保持降維後的方差最大,沒有考慮樣本的區域性特徵,如圖所示:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

利用PCA在對點①進行降維後,沒有考慮點①與其他點②、③、④..的位置關係,也就是說對於點①來說,點⑤到點①的距離相較於點④到點①的距離更近,而在實際中並非如此,有句話說叫“舉頭見日,不見長安”

        此時就需要流形學習(Manifold Learning)來解決這個問題。所謂流形學習,就是一類基於流形的學習框架,所謂流形就是上面那樣一張“S”的曲面,也可以想象成一個將地毯捲起來的樣子,也就是一種不閉合的曲面,而流形學習就是對這個不閉合的去年進行降維,也就相當於把這上面那個“S”拉直,或者把地毯鋪開的一個過程。

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

不同於PCA演算法,流形學習在降維中關注保持樣本的區域性線性特徵,為了保持區域性特徵,在進行降維時,不能將歐氏距離作為樣本間的距離了,

此時就需要利用測地距離來保持樣本間的特徵,這個演算法就是ISOMAP等距對映演算法,該演算法考慮在降維後每一個樣本與其它樣本的測地距離。

ISOMAP也有一個問題,就是它要考慮所有其他樣本之間的測地距離,當樣本的數量巨大時,演算法時間較長。這時就需要對演算法做進一步的改進。

1.LLE

1.1 LLE簡介及基本思想

         LLE(Local Linear Embedding)就是一種流形學習的演算法,LLE在降維時不再考慮全部的樣本來尋找全域性最優解(這個在進行最終求解還是要考慮全域性的,只不過對於每個樣本而言,僅考慮區域性),

而是保留區域性的一些樣本點作為區域性特徵進行降維,這樣既保留了區域性特徵,又減少了計算量

LLE的基本思想比較簡單,也就是隻考慮“最近幾個樣本點”進行降維,下面具體來說說LLE的思想:

樣本在原始空間中,分佈如圖所示:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

假設現在我們對xi進行降維,將xi從原始空間降到低維空間,降維後暫且在這裡稱之為zi

首先第一步,找出能夠“代表”xi的一些點,比如利用k-NN的方法,找到距離xi的最近的點xj.(注意:這裡xj並不是一個點,而是“一些”點);

然後,定義這些能夠“代表”xi的這些點與xj相連的權重為wij,那麼xi就可以用這些能夠“代表”它的點進行表示為:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

但這些也僅僅代表而已,並不真正相等,但我們希望越能夠“代表”越好,也就是期望兩個值越接近越好。

這是對於一個樣本點i,而對於空間中所有的點都是如此,並且希望每一個樣本點與能夠“代表”它的那些點的越接近越好,也就是:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

我們已經通過K-NN找出這些點xj了,那對於w還是未知的,因此,需要找出一組w,使得上面的那個式子的值越小越好。這不就是一個常規的NN演算法嗎?直接使用梯度下降進行求解就可以求出w了。

現在假設我們已經求出了一組w,然後用這組w進行降維,同樣,假設降維後的資料分佈如下圖:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

這裡zi就是xi從原始空間降維後的結果,保持wij不變,找一組zi和zj,使得:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

可以看出,這個式子與上面的式子完全一樣,不同的是,這裡我們所要尋找的是zi和zj,而上面的式子所要尋找的是權重wij,這裡同樣利用梯度下降就可以進行優化求解。

上面就是LLE的基本原理,其實LLE的原理從上面來看是比較簡單的,為保持區域性樣本的特點,將樣本用區域性其他樣本的線性表示然後進行降維。這種方法在李宏毅老師的課程裡用一句比較形象的話來概括:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

1.2 LLE的數學推導

上面介紹了LLE的基本原理,說到了對於降維的過程直接用梯度下降的方法進行優化求解即可,然而同PCA一樣,LLE也有一套完整的推導流程。

前面對於PCA是基於數學推導流程,求出的解析解,然後說道PCA可以看做一個NN結構,利用梯度下降進行求解。

本打算這裡不再對LLE的推導進行闡述,但看到目前sklearn下對LLE用的就是解析解的方法,這裡就對LLE推導和求解過程進行一個簡單的學習和推導。

  • 首先,對於第一步尋找xi的最近鄰樣本xj這裡就不再贅述,直接採用K-NN演算法找出就可以了。
  • 假設原始空間中有m個樣本,每個樣本為n維,假設樣本xi的近鄰樣本xj有k個

接下來,在高維空間中,需要找出xi與xj的空間線性關係,也就是找出權重係數wij。損失函式前面已經給出:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

這裡一般會對權重係數做一個歸一化的處理,也就是:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

為了便於推導,根據上面的歸一化對xi做一個變形:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

則有:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

作進一步的變換:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

這裡【機器學習基礎】無監督學習(2)——降維之LLE和TSNE,然後令【機器學習基礎】無監督學習(2)——降維之LLE和TSNE,則有:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

再對約束條件進一步變形:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

這裡"1k"表示k*1全為1的向量

根據損失函式L和約束條件,利用拉格朗日乘子求最小值:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

對W進行求導,令其為0,則得到:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

這裡就得到了在高維空間中的權重係數。

這裡Wi是一個k維的列向量,將所有樣本的Wi串起來後,最終W則是一個m*k維的矩陣。

  • 接下來根據這些權重係數,在低維空間中找出降維後的資料,使得下面的損失函式越小越好:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

這裡zi和zj是新的空間中的資料,也就是說原資料為m*n,到新空間中假設降到d維,則新空間資料變為m*d

為了方便後邊的推導,這裡需要注意的是,這裡的j不再是1~k,而是1~m,也就是說,從m個資料中拿出對應的k個樣本,對於不屬於近鄰內的w則為0,也就是說,

W由原來的m*k維擴充到了m*m維,這裡同樣對於標準化資料有閒置條件:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

對損失函式L(z)進一步整理得到:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

令M=【機器學習基礎】無監督學習(2)——降維之LLE和TSNE,則:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

這裡就類似於PCA中降維的求解過程類似(在PCA中是使其最大),同樣的,對於上面的式子,使得L(z)最小的解為M的前d個最小的特徵值所組成的特徵向量所組成的Z

這裡注意的是,M的最小特徵值為0,此時對應的特徵向量為全1,不能反映資料特徵,通常選擇第2到d+1小的特徵值對應的特徵向量得到最終降維後的資料Z

1.3 LLE的演算法實現

根據上面的理論部分,按照其解析解的方式對LLE的演算法進行實現,加深演算法的理解。然後根據sklearn中的manifold中的LLE方法,實現LLE。

首先是LLE演算法的具體實現過程:

import numpy as np


def cal_pairwise_dist(x):
    # 輸入矩陣x,返回兩兩之間的距離
    """
    輸入矩陣x,返回兩兩之間的距離
    (a-b)^2 = a^2 + b^2 - 2ab
    """
    # a^2 + b^2
    sum_x = np.sum(np.square(x), axis=1)

    dist = np.add(np.add(-2 * np.dot(x, x.T), sum_x).T, sum_x)
    return dist


def get_n_neighbors(data, n_neighbors=10):
    dist = cal_pairwise_dist(data)
    dist[dist < 0] = 0
    dist = dist ** 0.5

    n = dist.shape[0]
    N = np.zeros((n, n_neighbors))

    for i in range(n):
        # 計算每一個樣本點,距離其最近的近鄰點的索引
        index_ = np.argsort(dist[i])[1:n_neighbors+1]
        # 距離每一個樣本最近的點的索引i
        N[i] = N[i] + index_

    return N.astype(np.int32)


def lle(data, n_dims=2, n_neighbors=10):
    # 先獲取到樣本點的近鄰的樣本索引
    N = get_n_neighbors(data, n_neighbors)
    # 樣本數量n,維數為D
    n, D = data.shape

    # 當原空間維度小於近鄰點數量時,W不是滿秩的,要進行特殊處理
    if n_neighbors > D:
        tol = 1e-3
    else:
        tol = 0

    # 初始化W,W應該是n * n——neighbors維度,即n個樣本有n個wi,每一個wi有n_neighbors, 這裡做了轉置
    W = np.zeros((n_neighbors, n))
    # 即1k,k維全為1的列向量
    I = np.ones((n_neighbors, 1))

    for i in range(n):
        # 對於每一個樣本點xi
        # 先將xi進行伸展,形狀同xj一致
        Xi = np.tile(data[i], (n_neighbors, 1)).T
        # xj所組成的矩陣
        Ni = data[N[i]].T
        # 求Yi
        Yi = np.dot((Xi-Ni).T, (Xi - Ni))
        # 這裡是對於樣本維度小於n_neighbors時做的特殊處理,MLLE演算法,保持區域性鄰域關係的增量Hessian LLE演算法
        Yi = Yi + np.eye(n_neighbors) * tol * np.trace(Yi)

        # 求解逆矩陣
        Yi_inv = np.linalg.pinv(Yi)
        # 求解每一個樣本的wi,並做歸一化處理
        wi = (np.dot(Yi_inv, I))/(np.dot(np.dot(I.T, Yi_inv), I)[0, 0])
        W[:, i] = wi[:, 0]

    # 初始化W
    W_y = np.zeros((n, n))

    # 對上一步求的W做進一步擴充,之前是n*k維的,現在變成n*n維的,不是近鄰的位置補0
    for i in range(n):
        index = N[i]
        for j in range(n_neighbors):
            W_y[index[j], i] = W[j, i]


    I_y = np.eye(n)
    # 計算(I-W)(I-W).T
    M = np.dot((I_y - W_y), (I_y - W_y).T)
    # 求特徵值
    eig_val, eig_vector = np.linalg.eig(M)
    # 找出前n_dim個小的特徵值,忽略掉0,取第2到第n_dim+1個
    index_ = np.argsort(np.abs(eig_val))[1: n_dims+1]
    print("index_", index_)
    # 特徵值對應的特徵向量就是最後降維後得到的樣本
    Y = eig_vector[:, index_]

    return Y

然後對上面的程式碼進行測試,首先匯入一些必要的畫圖的工具包和資料集,資料集採用sklearn自帶的“瑞士捲”資料集:

from sklearn.datasets import make_swiss_roll
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D


X, color = make_swiss_roll(n_samples=5000, noise=0.1, random_state=42)
fig = plt.figure()
ax = Axes3D(fig)
ax.scatter(X[:, 0], X[:, 1], X[:, 2], c=color, cmap=plt.cm.Spectral)

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

同時用sklearn自帶的manifold方法實現LLE,並同時用PCA對上面的資料集進行降維,對比三者得到的結果:

from sklearn import manifold
from sklearn.decomposition import PCA


# LLE
data_1 = lle(X, n_neighbors=30)
# sklearn LLE
data_2 = manifold.LocallyLinearEmbedding(n_components=2, n_neighbors=30).fit_transform(X)
# PCA
pca_data = PCA(n_components=2).fit_transform(X)

# 畫圖
plt.figure(figsize=(8, 4))
plt.subplot(131)
plt.title("LLE")
plt.scatter(data_1[:, 0], data_1[:, 1], c=color, cmap=plt.cm.Spectral)

plt.subplot(132)
plt.title("sklearn_LLE")
plt.scatter(data_2[:, 0], data_2[:, 1], c=color, cmap=plt.cm.Spectral)


plt.subplot(133)
plt.scatter(pca_data[:, 0], pca_data[:, 1], c=color, cmap=plt.cm.Spectral)
plt.title('PCA')

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

LLE演算法對於所選取的區域性樣本點的個數較為敏感,所選取區域性樣本數量不同,對結果影響比較大,如下一組實驗:

fig = plt.figure()
for index, k in enumerate((10, 20, 30, 40)):
    plt.subplot(2, 2, index+1)
    trans_data = manifold.LocallyLinearEmbedding(n_neighbors=k, n_components=2).fit_transform(X)
    plt.scatter(trans_data[:, 0], trans_data[:, 1], c=color, cmap=plt.cm.Spectral)

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

可以看出,當n_neighbors不同取值,對於結果的影響較大,當過多或者過少時,結果則會完全壞掉。

1.4 LLE的優缺點

LLE的原理大致就是上面所介紹的,那麼在最後的實驗中也比較了不同的近鄰數目對結果的影響,在這裡總結一些LLE的優點和缺點進行比較:

優點:

    • 方法簡單易於實現,相較於ISOMAP而言,計算複雜度低;
    • LLE不同於PCA的線性降維,LLE是一種非線性的降維方法,能夠學習任意維的流形圖形;
    • 因為其非線性的特點,LLE能夠表達區域性特徵,從而保留原資料特徵。

當然,LLE也自身存在一些缺點:

    • 對於近鄰演算法選取的近鄰樣本點和樣本點的數量較為敏感
    • 僅能夠學習流形圖形,對於閉合的非流行圖形,演算法不適用
    • LLE只能夠用於稠密分佈均勻的樣本分佈,稀疏的樣本使用LLE演算法效果不佳(這可能也是因為LLE對於近鄰樣本敏感所造成的)。

2 TSNE演算法

前面介紹了兩種降維的方法PCA和LLE,這兩種降維的方法都有一個共同的特點:在進行降維時,都強調了降維後的相似的資料要儘可能地保持相似,但並沒有說對於那些不相似的資料,要有多不相似這個問題

這就導致了在進行降維時,可能導致資料的重疊問題,導致在低維空間中一樣很難進行區分。

這時就需要另一種降維的方法——T-SNE。

所謂T-SNE,其就是SNE(stochastic neighbor embedding)的升級版,SNE同前面的演算法一樣,希望樣本在高維空間中相似的資料點,到低維空間也相似,而T-SNE則是在SNE的基礎上,要使得對於高維空間不相似的樣本,在低維空間中也儘可能不相似

SNE則把這種距離的關係轉換為一種概率。下面先介紹二者共同的部分,對於區別和改進,在後邊進行對比。這裡僅做簡要原理介紹,不再做過多推導。

首先,定義在高維空間中兩個樣本xi和xj之間的相似度S(xi,xj),則:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

這個概率表示,xi作為中心點,xj是其近鄰點的概率,當兩個點越近,則概率越大,距離較遠時,則概率較小。

同樣的,樣本對映到低維空間後,分別為zi和zj,在低位空間中,二者的相似度定義為S'(zi,zj),則:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

然後根據這兩個分佈,在高維空間和低維空間中,我們希望這兩個分佈越相似越好,而用來衡量樣本相似度的指標為KL散度,因此定義損失如下:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

具體的KL散度的公式如下:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

然後根據這個損失函式,找一組zi和zj,使得損失越小越好。然後就是梯度下降進行求解。

上面就是SNE與TSNE所共同的過程,在高維空間中,二者都採用高斯分佈來度量任意兩個點相似性,即:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

而在低維空間中,SNE同樣採用高斯分佈作為相似性度量的方式,即:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

對於TSNE來說,則採用了更一般的T分佈來替代高斯分佈

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

這樣可以不但拉近相似的樣本的之間距離,同時,當樣本不相似時,則可以使距離拉的更遠。如下圖所示:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

對於兩條曲線而言,當i與j相距較近時,二者在相似度上差不多,而當i與j相距較遠時,T分佈則可以進一步拉遠二者之間的距離。

上面就是TSNE的基本思想,具體原理和演算法這裡不再進行推導,詳細內容可以參考部落格:TSNE-原理與實現

關於TSNE的具體實現方法,git地址https://github.com/heucoder/dimensionality_reduction_alo_codes/tree/master/codes/T-SNE。這裡就利用sklearn中的tsne方法對其進行實現和比較:

from sklearn.manifold import TSNE

plt.figure()
for index, k in enumerate((5, 15, 25, 30, 40, 100)):
    plt.subplot(230+index+1)
    data_tsne = TSNE(n_components=2, perplexity=k).fit_transform(X)
    plt.scatter(data_tsne[:, 0], data_tsne[:, 1], c=color, cmap=plt.cm.Spectral)

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

對於在手寫數字識別上使用TSNE得到的結果,能夠更加明顯地看出TSNE的優點:

【機器學習基礎】無監督學習(2)——降維之LLE和TSNE

可以看出,TSNE解決了資料在降維之後的擁擠問題

以上就是關於LLE和TSNE的內容,這裡暫時沒有對TSNE進行推導,後面自己會對TSNE的原始碼進行熟悉和了解加深理解,本節有關降維的方法就先到這裡了。

本文參考資料:

區域性線性嵌入(LLE)原理總結

LLE原理及推導過程

李宏毅《機器學習》


降維的方法其實有很多,也有同一種的不同變形,當用到時後面會再進行補充。下一更準備對比較重要的演算法AutoEnder做一個複習。

相關文章