UMAP應(yīng)該說(shuō)是目前最好的降維算法了,能最大程度的保留原始數(shù)據(jù)的特征同時(shí)大幅度的降低特征維數(shù)。
如果你不知道tSNE是什么,它是如何工作的,也沒(méi)有讀過(guò)2008年的革命性的van der Maaten & Hinton原稿,你可能不需要知道,因?yàn)閠SNE現(xiàn)在基本上已經(jīng)死了。盡管tSNE對(duì)一般的單細(xì)胞基因組學(xué)和數(shù)據(jù)科學(xué)產(chǎn)生了巨大的影響,但人們普遍認(rèn)為它有一些缺點(diǎn),這些缺點(diǎn)很快將得到解決。
究竟是什么讓我們想放棄使用tSNE單細(xì)胞基因組學(xué)?這里我用簡(jiǎn)短的評(píng)論總結(jié)了幾點(diǎn):
在scRNAseq中,tSNE并不能很好地?cái)U(kuò)展快速增加的樣本量。試圖用FItSNE來(lái)加速它會(huì)導(dǎo)致大量的內(nèi)存消耗,使得在計(jì)算機(jī)集群之外無(wú)法進(jìn)行分析。(集群之痛)
tSNE沒(méi)有保留全局?jǐn)?shù)據(jù)結(jié)構(gòu),這意味著只有在集群距離內(nèi)才有意義,而集群之間的相似性并不能保證,因此使用tSNE作為集群不是一個(gè)很好的主意。
tSNE實(shí)際上只能嵌入到2維或3維中,即僅用于可視化目的,因此很難將tSNE作為一種通用的降維技術(shù)來(lái)生產(chǎn)10個(gè)或50個(gè)組件。
請(qǐng)注意,這對(duì)于更現(xiàn)代的FItSNE算法來(lái)說(shuō)仍然是一個(gè)問(wèn)題。
tSNE執(zhí)行從高維到低維的非參數(shù)映射,這意味著它不利用驅(qū)動(dòng)觀察到的集群的特性(也稱為PCA加載)。
tSNE不能直接處理高維數(shù)據(jù),在將其插入tSNE之前,通常使用自動(dòng)編碼器或PCA執(zhí)行預(yù)降維
(1)定義了高維空間中任意兩點(diǎn)之間觀測(cè)距離的高斯概率,滿足對(duì)稱性規(guī)則。Eq。
(2)引入了困惑的概念作為一個(gè)約束,確定最優(yōu)σ為每個(gè)樣本。
(3)聲明了低維嵌入中點(diǎn)對(duì)之間距離的學(xué)生t分布。學(xué)生t分布是為了克服嵌入低維時(shí)的擁擠問(wèn)題。
(4)給出了Kullback-Leibler散度損失函數(shù),將高維概率投影到低維概率上,并給出了梯度下降優(yōu)化中使用的梯度的解析形式。
看看上面的圖,我想說(shuō)的是 t分布應(yīng)該提供全局距離信息,因?yàn)樗鼈儗⒏呔S空間中相距較遠(yuǎn)的點(diǎn)推到低維空間中更遠(yuǎn)的點(diǎn)。
然而,這種良好的意愿被成本函數(shù)(KL-divergence)的選擇所扼殺,我們將在后面看到其原因。
當(dāng)了解UMAP時(shí),我的第一印象是這是一種全新的、有趣的降維技術(shù),它基于堅(jiān)實(shí)的數(shù)學(xué)原理,因此與純機(jī)器學(xué)習(xí)半經(jīng)驗(yàn)算法tSNE非常不同。我的生物學(xué)同事告訴我,最初的UMAP論文“太數(shù)學(xué)化了”,看著論文的第二部分,我很高興地看到,嚴(yán)格而準(zhǔn)確的數(shù)學(xué)終于進(jìn)入生命和數(shù)據(jù)科學(xué)。然而,在閱讀UMAP文檔和觀看Leland McInnes在2018年SciPy大會(huì)上的演講時(shí),我感到困惑,覺(jué)得UMAP是另一種鄰居圖技術(shù),它與tSNE如此相似,以至于我很難理解UMAP與tSNE究竟有什么不同。
從UMAP論文中,雖然Leland McInnes試圖在附錄c中總結(jié)UMAP和tSNE之間的差異,但是它們之間的差異并不是很明顯。在這里,我將首先總結(jié)我所注意到的UMAP和tSNE之間的不同之處,然后嘗試解釋為什么這些不同是重要的,并找出它們的影響有多大。
ρ是一個(gè)重要的參數(shù),它代表了每個(gè)i數(shù)據(jù)點(diǎn)距離第一個(gè)最近鄰。這保證了流形的局部連接性。換句話說(shuō),這為每個(gè)數(shù)據(jù)點(diǎn)提供了一個(gè)局部自適應(yīng)指數(shù)核,因此距離度量在點(diǎn)與點(diǎn)之間變化。
ρ參數(shù)是唯一在UMAP部分2和3之間的橋梁。否則,我也看不出什么模糊單形建筑,即從第二節(jié)的拓?fù)鋽?shù)據(jù)分析,與從第三節(jié)UMAP的算法實(shí)現(xiàn),似乎在一天結(jié)束的時(shí)候模糊單形集導(dǎo)致最近鄰圖施工。
UMAP對(duì)高維或低維概率都不應(yīng)用標(biāo)準(zhǔn)化,這與tSNE非常不同,感覺(jué)很奇怪。然而,高或低維函數(shù)形式的概率可以看到他們已經(jīng)擴(kuò)展[0,1],事實(shí)證明,缺乏規(guī)范化的情況下,類似于情商分母。
(1),可以顯著降低計(jì)算時(shí)間高維圖像由于求和或集成是一個(gè)代價(jià)高昂的計(jì)算過(guò)程。想想馬爾可夫鏈蒙特卡羅(MCMC)它基本上是試圖近似地計(jì)算在貝葉斯規(guī)則的分母上的積分(UMAP使用最近鄰居的數(shù)量而不是perplexity)
(2)定義perplexity, UMAP則定義了沒(méi)有l(wèi)og2函數(shù)的最近鄰居k的個(gè)數(shù),即:
其中,對(duì)于默認(rèn)UMAP超參數(shù)a≈1.93,b≈0.79(實(shí)際上,對(duì)于min_dist = 0.001)。在實(shí)踐中,UMAP從非線性最小二乘擬合到帶有min_dist超參數(shù)的分段函數(shù)中找到a和b:
plt.figure(figsize=(20, 15))
y = np.linspace(0, 10, 1000)
my_prob = lambda y, a, b: np.power(1 + a*y**(2*b), -1)
plt.plot(y, my_prob(y, a = 1, b = 1))
plt.plot(y, my_prob(y, a = 1.93, b = 0.79))
plt.plot(y, my_prob(y, a = 1.93, b = 5))
plt.gca().legend(('a = 1, b = 1', 'a = 1.93, b = 0.79', 'a = 1.93, b = 5'), fontsize = 20)
plt.title('Low-Dimensional Probability of Pairwise Euclidean Distances', fontsize = 20)
plt.xlabel('Y', fontsize = 20); plt.ylabel('Q(Y)', fontsize = 20)
plt.show()
我們可以看到曲線族對(duì)參數(shù)b非常敏感,在大的參數(shù)b處,在小的參數(shù)y處,曲線族形成了一種高峰。這意味著在UMAP超參數(shù)min_dist之下,所有的數(shù)據(jù)點(diǎn)都是同樣緊密相連的。由于Q(Y)函數(shù)的行為幾乎像一個(gè)Heaviside階躍函數(shù),這意味著UMAP為所有在低維空間中相互靠近的點(diǎn)分配了幾乎相同的低維坐標(biāo)。min_dist正是導(dǎo)致在UMAP維數(shù)降低圖中經(jīng)常觀察到的超密集集群的原因。
為了演示如何準(zhǔn)確地找到a和b參數(shù),讓我們展示一個(gè)簡(jiǎn)單的分段函數(shù)(其中高峰部分是通過(guò)min_dist參數(shù)定義的),并使用函數(shù)族1 / (1+a*y^(2b))通過(guò)優(yōu)化來(lái)擬合它。curve_fit來(lái)自Scipy Python庫(kù)。作為擬合的結(jié)果,我們得到了函數(shù)1 / (1+a*y^(2b))的初值a和初值b。
from scipy import optimize
import matplotlib.pyplot as plt
import numpy as np
MIN_DIST = 1
x = np.linspace(0, 10, 300)
def f(x, min_dist):
y = []
for i in range(len(x)):
if(x[i] <= min_dist):
y.append(1)
else:
y.append(np.exp(- x[i] + min_dist))
return y
dist_low_dim = lambda x, a, b: 1 / (1 + a*x**(2*b))
p , _ = optimize.curve_fit(dist_low_dim, x, f(x, MIN_DIST))
print(p)
plt.figure(figsize=(20,15))
plt.plot(x, f(x, MIN_DIST), 'o')
plt.plot(x, dist_low_dim(x, p[0], p[1]), c = 'red')
plt.title('Non-Linear Least Square Fit of Piecewise Function', fontsize = 20)
plt.gca().legend(('Original', 'Fit'), fontsize = 20)
plt.xlabel('X', fontsize = 20)
plt.ylabel('Y', fontsize = 20)
plt.show()
UMAP使用圖拉普拉斯變換分配初始的低維坐標(biāo),與tSNE使用的隨機(jī)正常初始化形成對(duì)比。
然而,這應(yīng)該會(huì)對(duì)最終的低維表示產(chǎn)生較小的影響,至少在tSNE中是這樣的。
但是,這應(yīng)該會(huì)減少UMAP每次運(yùn)行時(shí)的更改,因?yàn)樗辉偈且粋€(gè)隨機(jī)初始化。
Linderman和Steinerberger提出了一個(gè)有趣的假設(shè),即在tSNE的初始階段最小化kl散度,并在早期進(jìn)行放大,這一假設(shè)的動(dòng)機(jī)是通過(guò)圖拉普拉斯變換來(lái)進(jìn)行初始化。
圖拉普拉斯、譜聚類、拉普拉斯Eignemaps、擴(kuò)散圖、譜嵌入等,實(shí)際上是指將矩陣分解和鄰接圖方法結(jié)合起來(lái)解決降維問(wèn)題的同一種有趣的方法。在這種方法中,我們首先構(gòu)造一個(gè)圖(或knn圖),然后通過(guò)構(gòu)造拉普拉斯矩陣用矩陣代數(shù)(鄰接矩陣和度矩陣)將其形式化,最后分解拉普拉斯矩陣,即求解特征值分解問(wèn)題。
我們可以使用scikit-learn Python庫(kù),并使用spectralembedded函數(shù)在演示數(shù)據(jù)集(即與癌癥相關(guān)的成纖維細(xì)胞(CAFs) scRNAseq數(shù)據(jù))上輕松地顯示初始的低維坐標(biāo):
from sklearn.manifold import SpectralEmbedding
model = SpectralEmbedding(n_components = 2, n_neighbors = 50)
se = model.fit_transform(np.log(X_train + 1))
plt.figure(figsize=(20,15))
plt.scatter(se[:, 0], se[:, 1], c = y_train.astype(int), cmap = 'tab10', s = 50)
plt.title('Laplacian Eigenmap', fontsize = 20)
plt.xlabel('LAP1', fontsize = 20)
plt.ylabel('LAP2', fontsize = 20)
plt.show()
最后,UMAP使用隨機(jī)梯度下降(SGD)代替常規(guī)梯度下降(GD),如tSNE / FItSNE,這既加快了計(jì)算速度,又減少了內(nèi)存消耗。
plt.figure(figsize=(20, 15))
x = np.linspace(0, 10, 1000)
sigma_list = [0.1, 1, 5, 10]
for sigma in sigma_list:
my_prob = lambda x: np.exp(-x**2 / (2*sigma**2))
plt.plot(x, my_prob(x))
plt.gca().legend(('$\sigma$ = 0.1','$\sigma$ = 1', '$\sigma$ = 5', '$\sigma$ = 10'),
fontsize = 20)
plt.title('High-Dimensional Probability of Pairwise Euclidean Distances', fontsize = 20)
plt.xlabel('X', fontsize = 20); plt.ylabel('P(X)', fontsize = 20)
plt.show()
有趣的是,如果我們擴(kuò)大成對(duì)歐幾里得距離的概率高維度成泰勒級(jí)數(shù)在σ→∞,我們會(huì)在第二近似冪律:
關(guān)于兩兩歐幾里得距離的冪律類似于多維定標(biāo)法(MDS)的成本函數(shù),MDS是通過(guò)保存每對(duì)點(diǎn)之間的距離來(lái)保存全局距離,而不管它們是相距很遠(yuǎn)還是很近。一個(gè)可以解釋這個(gè)大的σtSNE遠(yuǎn)程數(shù)據(jù)點(diǎn)之間的相互作用,所以是不完全正確的說(shuō)tSNE只能處理當(dāng)?shù)氐木嚯x。然而,我們通常會(huì)受到perplexity有限值的限制,Laurens van der Maaten建議perplexity的取值范圍在5到50之間,盡管在局部信息和全局信息之間可能會(huì)有一個(gè)很好的折衷,那就是使用平方根≈N^(1/2)來(lái)選擇perplexity,其中N為樣本量。相反的極限,σ→0,我們最終的極端“局部性”高維概率的行為類似于狄拉克δ函數(shù)的行為。
另一種理解tSNE“局部性”的方法是考慮KL-divergence函數(shù)。假設(shè)X是高維空間中點(diǎn)之間的距離Y是低維空間中點(diǎn)之間的距離
根據(jù)kl -散度的定義:
方程(9)的第一項(xiàng)對(duì)于X的大小都是趨近于0的,對(duì)于X的大小也是趨近于0的,因?yàn)橹笖?shù)趨近于1,而log(1)=0。對(duì)于大X,這一項(xiàng)仍然趨近于0因?yàn)橹笖?shù)前因子趨近于0的速度快于對(duì)數(shù)趨近于負(fù)無(wú)窮。因此,為了直觀地理解kl散度,只考慮第二項(xiàng)就足夠了:
這是一個(gè)看起來(lái)很奇怪的函數(shù),讓我們畫(huà)出KL(X, Y)
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.ticker import LinearLocator, FormatStrFormatter
fig = plt.figure(figsize=(20, 15))
ax = fig.gca(projection = '3d')
# Set rotation angle to 30 degrees
ax.view_init(azim=30)
X = np.arange(0, 3, 0.1)
Y = np.arange(0, 3, 0.1)
X, Y = np.meshgrid(X, Y)
Z = np.exp(-X**2)*np.log(1 + Y**2)
# Plot the surface.
surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm,linewidth=0, antialiased=False)
ax.set_xlabel('X', fontsize = 20)
ax.set_ylabel('Y', fontsize = 20)
ax.set_zlabel('KL (X, Y)', fontsize = 20)
ax.set_zlim(0, 2.2)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()
這個(gè)函數(shù)的形狀非常不對(duì)稱。如果點(diǎn)在高維度X之間的距離很小,指數(shù)因子變成1和對(duì)數(shù)項(xiàng)行為日志(1 + Y ^ 2)這意味著如果Y是在低維空間的距離大,將會(huì)有一個(gè)大的懲罰,因此tSNE試圖減少Y在小X為了減少罰款。相反,對(duì)于高維空間中的長(zhǎng)距離X, Y基本上可以是0到∞之間的任何值,因?yàn)橹笖?shù)項(xiàng)趨于0,并且總是勝過(guò)對(duì)數(shù)項(xiàng)。因此,在高維空間中相距遙遠(yuǎn)的點(diǎn),在低維空間中可能會(huì)相互靠近。因此,換句話說(shuō),tSNE并不能保證高維空間中相距較遠(yuǎn)的點(diǎn)在低維空間中會(huì)保持較遠(yuǎn)的距離。然而,它確實(shí)保證了在高維空間中相鄰的點(diǎn)在低維空間中保持相鄰。所以tSNE不是很擅長(zhǎng)遠(yuǎn)距離投射至低維,所以它只保留本地?cái)?shù)據(jù)結(jié)構(gòu)提供了σ不去∞。
與tSNE不同,UMAP使用交叉熵(CE)作為成本函數(shù),而不是KL-divergence
這導(dǎo)致了地方-全球結(jié)構(gòu)保護(hù)平衡的巨大變化。在X的小值處,我們得到了與tSNE相同的極限,因?yàn)榈诙?xiàng)由于前因子和對(duì)數(shù)函數(shù)比多項(xiàng)式函數(shù)慢的事實(shí)而消失:
因此,為了使懲罰規(guī)則最小化,Y坐標(biāo)必須非常小,即Y→0。這與tSNE的行為完全一樣。但是,在大X的相反極限,即X→∞時(shí),第一項(xiàng)消失,第二項(xiàng)的前因子為1,得到:
這里,如果Y很小,我們會(huì)得到一個(gè)很大的懲罰,因?yàn)閅在對(duì)數(shù)的分母上,因此,我們鼓勵(lì)Y很大,這樣,對(duì)數(shù)下的比率就變成了1,我們得到零懲罰。因此,我們?cè)赬→∞處得到Y(jié)→∞,所以從高維空間到低維空間的整體距離保持不變,這正是我們想要的。為了說(shuō)明這一點(diǎn),讓我們繪制UMAP CE成本函數(shù):
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.ticker import LinearLocator, FormatStrFormatter
fig = plt.figure(figsize=(20, 15))
ax = fig.gca(projection = '3d')
# Set rotation angle to 30 degrees
ax.view_init(azim=30)
X = np.arange(0, 3, 0.001)
Y = np.arange(0, 3, 0.001)
X, Y = np.meshgrid(X, Y)
Z = np.exp(-X**2)*np.log(1 + Y**2) + (1 - np.exp(-X**2))*np.log((1 + Y**2) / (Y**2+0.01))
# Plot the surface.
surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm,linewidth=0, antialiased=False)
ax.set_xlabel('X', fontsize = 20)
ax.set_ylabel('Y', fontsize = 20)
ax.set_zlabel('CE (X, Y)', fontsize = 20)
ax.set_zlim(0, 4.3)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))
# Add a color bar which maps values to colors.
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()
在這里,我們可以看到圖的“右”部分看起來(lái)與上面的kl散度曲面非常相似。這意味著在X低的時(shí)候,為了減少損失,我們?nèi)匀幌胍猋低。然而,當(dāng)X很大時(shí),Y的距離也要很大,因?yàn)槿绻苄?,CE (X, Y)的損失將是巨大的。記住,之前,對(duì)于KL (X, Y)曲面,在X很大的情況下,我們?cè)诟遈值和低Y值之間沒(méi)有差別,這就是為什么CE (X, Y)代價(jià)函數(shù)能夠保持全局距離和局部距離。
我們知道UMAP是速度比tSNE擔(dān)憂)時(shí)大量的數(shù)據(jù)點(diǎn),b)嵌入維數(shù)大于2或3,c)大量環(huán)境維度的數(shù)據(jù)集。在這里,讓我們?cè)囍私釻MAP要優(yōu)于tSNE來(lái)自于數(shù)學(xué)和算法實(shí)現(xiàn)。
tSNE和UMAP基本上都包含兩個(gè)步驟:
建立一個(gè)圖在高維度的帶寬和計(jì)算指數(shù)概率,σ,使用二進(jìn)制搜索和固定數(shù)量的最近的鄰居需要考慮。
通過(guò)梯度下降優(yōu)化低維表示。第二步是算法的瓶頸,它是連續(xù)的,不能是多線程的。由于tSNE和UMAP都執(zhí)行第二步,所以并不清楚為什么UMAP比tSNE更有效。
然而,我注意到UMAP的第一步比tSNE快得多。這有兩個(gè)原因:
首先,我們?nèi)サ袅俗罱彅?shù)量定義中的log部分,即不像tSNE那樣使用全熵:
由于在算法上,對(duì)數(shù)函數(shù)是通過(guò)泰勒級(jí)數(shù)展開(kāi)來(lái)計(jì)算的,而且在線性項(xiàng)前面加上一個(gè)對(duì)數(shù)前因子實(shí)際上并沒(méi)有增加多少,因?yàn)閷?duì)數(shù)函數(shù)比線性函數(shù)慢,所以最好完全跳過(guò)這一步。
第二個(gè)原因是我們忽略了高維概率的歸一化,即式(1)中用于tSNE的高維概率歸一化??梢哉f(shuō),這一小步實(shí)際上對(duì)演出產(chǎn)生了戲劇性的影響。這是因?yàn)榍蠛突蚍e分是一個(gè)計(jì)算開(kāi)銷(xiāo)很大的步驟。
接下來(lái),UMAP實(shí)際上在第二步中也變得更快了。這種改善也有幾個(gè)原因:
采用隨機(jī)梯度下降法(SGD)代替常規(guī)梯度下降法(GD),如tSNE或FItSNE。這提高了速度,因?yàn)閷?duì)于SGD,您可以從一個(gè)隨機(jī)樣本子集計(jì)算梯度,而不是像常規(guī)GD那樣使用所有樣本子集。除了速度之外,這還減少了內(nèi)存消耗,因?yàn)槟辉傩枰獮閮?nèi)存中的所有樣本保持梯度,而只需要為一個(gè)子集保持梯度。
我們不僅跳過(guò)了高維和低維概率的標(biāo)準(zhǔn)化。這也省去了第二階段(優(yōu)化低維嵌入)的昂貴求和。
由于標(biāo)準(zhǔn)的tSNE使用基于樹(shù)的算法進(jìn)行最近鄰搜索,由于基于樹(shù)的算法隨著維數(shù)的增加呈指數(shù)增長(zhǎng),所以生成超過(guò)2-3個(gè)嵌入維數(shù)的速度太慢。這個(gè)問(wèn)題在UMAP中通過(guò)去掉高維和低維概率的標(biāo)準(zhǔn)化得到了解決。
增加原始數(shù)據(jù)集的維數(shù),我們引入稀疏性,即我們得到越來(lái)越多的碎片化流形,即有時(shí)存在稠密區(qū)域,有時(shí)存在孤立點(diǎn)(局部破碎流形)。UMAP解決這個(gè)問(wèn)題通過(guò)引入本地連接ρ參數(shù)融合在一起(某種程度上)通過(guò)引入自適應(yīng)稀疏區(qū)域指數(shù)內(nèi)核,考慮了本地?cái)?shù)據(jù)連接。這就是為什么UMAP(理論上)可以處理任意數(shù)量的維度,并且在將其插入主維度縮減過(guò)程之前不需要預(yù)降維步驟(自動(dòng)編碼器、PCA)的原因。
在這篇文章中,我們了解到盡管tSNE多年來(lái)一直服務(wù)于單細(xì)胞研究領(lǐng)域,但它有太多的缺點(diǎn),如速度快、缺乏全球距離保存。UMAP總體上遵循了tSNE的哲學(xué),但是引入了一些改進(jìn),例如另一個(gè)成本函數(shù)和缺少高維和低維概率的標(biāo)準(zhǔn)化。
聯(lián)系客服