深度 | 詳解可視化利器t-SNE算法:數無形時少直覺

2021-02-13 機器之心

本文介紹了 T 分布隨機近鄰嵌入算法,即一種十分強大的高維數據降維方法。我們將先簡介該算法的基本概念與直觀性理解,再從詳細分析與實現該降維方法,最後我們會介紹使用該算法執行可視化的結果。

T 分布隨機近鄰嵌入(T-Distribution Stochastic Neighbour Embedding)是一種用於降維的機器學習方法,它能幫我們識別相關聯的模式。t-SNE 主要的優勢就是保持局部結構的能力。這意味著高維數據空間中距離相近的點投影到低維中仍然相近。t-SNE 同樣能生成漂亮的可視化。

當構建一個預測模型時,第一步一般都需要理解數據。雖然搜索原始數據並計算一些基本的統計學數字特徵有助於理解它,但沒有什麼是可以和圖表可視化展示更為直觀的。然而將高維數據擬合到一張簡單的圖表(降維)通常是非常困難的,這就正是 t-SNE 發揮作用的地方。

在本文中,我們將探討 t-SNE 的原理,以及 t-SNE 將如何有助於我們可視化數據。


t-SNE 算法概念

這篇文章主要是介紹如何使用 t-SNE 進行可視化。雖然我們可以跳過這一章節而生成出漂亮的可視化,但我們還是需要討論 t-SNE 算法的基本原理。

t-SNE 算法對每個數據點近鄰的分布進行建模,其中近鄰是指相互靠近數據點的集合。在原始高維空間中,我們將高維空間建模為高斯分布,而在二維輸出空間中,我們可以將其建模為 t 分布。該過程的目標是找到將高維空間映射到二維空間的變換,並且最小化所有點在這兩個分布之間的差距。與高斯分布相比 t 分布有較長的尾部,這有助於數據點在二維空間中更均勻地分布。

控制擬合的主要參數為困惑度(Perplexity)。困惑度大致等價於在匹配每個點的原始和擬合分布時考慮的最近鄰數,較低的困惑度意味著我們在匹配原分布並擬合每一個數據點到目標分布時只考慮最近的幾個最近鄰,而較高的困惑度意味著擁有較大的「全局觀」。

因為分布是基於距離的,所以所有的數據必須是數值型。我們應該將類別變量通過二值編碼或相似的方法轉化為數值型變量,並且歸一化數據也是也十分有效,因為歸一化數據後就不會出現變量的取值範圍相差過大。

T 分布隨機近鄰嵌入算法(t-SNE)


Jake Hoare 的博客並沒有詳細解釋 t-SNE 的具體原理和推導過程,因此下面我們將基於 Geoffrey Hinton 在 2008 年提出的論文和 liam schoneveld 的推導與實現詳細介紹 t-SNE 算法。如果讀者對這一章節不感興趣,也可以直接閱讀下一章節 Jake Hoare 在實踐中使用 t-SNE 進行數據可視化。

因為 t-SNE 是基於隨機近鄰嵌入而實現的,所以首先我們需要理解隨機近鄰嵌入算法。

隨機近鄰嵌入(SNE)


假設我們有數據集 X,它共有 N 個數據點。每一個數據點 x_i 的維度為 D,我們希望降低為 d 維。在一般用於可視化的條件下,d 的取值為 2,即在平面上表示出所有數據。

SNE 通過將數據點間的歐幾裡德距離轉化為條件概率而表徵相似性(下文用 p_j|i 表示):


如果以數據點在 x_i 為中心的高斯分布所佔的概率密度為標準選擇近鄰,那麼 p_j|i 就代表 x_i 將選擇 x_j 作為它的近鄰。對於相近的數據點,條件概率 p_j|i 是相對較高的,然而對於分離的數據點,p_j|i 幾乎是無窮小量(若高斯分布的方差σ_i 選擇合理)。

其中σ_i 是以數據點 x_i 為均值的高斯分布標準差,決定σ_i 值的方法將在本章後一部分討論。因為我們只對成對相似性的建模感興趣,所以可以令 p_i|i 的值為零。

現在引入矩陣 Y,Y 是 N*2 階矩陣,即輸入矩陣 X 的 2 維表徵。基於矩陣 Y,我們可以構建一個分布 q,其形式與 p 類似。

對於高維數據點 x_i 和 x_j 在低維空間中的映射點 y_i 和 y_j,計算一個相似的條件概率 q_j|i 是可以實現的。我們將計算條件概率 q_i|j 中用到的高斯分布的方差設置為 1/2。因此我們可以對映射的低維數據點 y_j 和 y_i 之間的相似度進行建模:


我們的總體目標是選擇 Y 中的一個數據點,然後其令條件概率分布 q 近似於 p。這一步可以通過最小化兩個分布之間的 KL 散度(損失函數)而實現,這一過程可以定義為:


因為我們希望能最小化該損失函數,所以我們可以使用梯度下降進行迭代更新,我們可能對如何迭代感興趣,但我們會在後文討論與實現。


使用 NumPy 構建歐幾裡德距離矩陣


計算 p_i|j 和 q_i|j 的公式都存在負的歐幾裡德距離平方,即-||x_i - x_j||^2,下面可以使用代碼實現這一部分:

def neg_squared_euc_dists(X):

   """Compute matrix containing negative squared euclidean

   distance for all pairs of points in input matrix X

   # Arguments:

       X: matrix of size NxD

   # Returns:

       NxN matrix D, with entry D_ij = negative squared

       euclidean distance between rows X_i and X_j

   """

   # Math? See https://stackoverflow.com/questions/37009647

   sum_X = np.sum(np.square(X), 1)

   D = np.add(np.add(-2 * np.dot(X, X.T), sum_X).T, sum_X)

   return -D

為了更高的計算效率,該函數使用矩陣運算的方式定義,該函數將返回一個 N 階方陣,其中第 i 行第 j 列個元素為輸入點 x_i 和 x_j 之間的負歐幾裡德距離平方。

使用過神經網絡的讀者可能熟悉 exp(⋅)/∑exp(⋅) 這樣的表達形式,它是一種 softmax 函數,所以我們定義一個 softmax 函數:

def softmax(X, diag_zero=True):

   """Take softmax of each row of matrix X."""

   # Subtract max for numerical stability

   e_x = np.exp(X - np.max(X, axis=1).reshape([-1, 1]))

   # We usually want diagonal probailities to be 0.

   if diag_zero:

       np.fill_diagonal(e_x, 0.)

   # Add a tiny constant for stability of log we take later

   e_x = e_x + 1e-8  # numerical stability

   return e_x / e_x.sum(axis=1).reshape([-1, 1])

注意我們需要考慮 p_i|i=0 這個條件,所以我們可以替換指數負距離矩陣的對角元素為 0,即使用 np.fill_diagonal(e_x, 0.) 方法將 e_x 的對角線填充為 0。

將這兩個函數放在一起後,我們能構建一個函數給出矩陣 P,且元素 P(i,j) 為上式定義的 p_i|j:

def calc_prob_matrix(distances, sigmas=None):

   """Convert a distances matrix to a matrix of probabilities."""

   if sigmas is not None:

       two_sig_sq = 2. * np.square(sigmas.reshape((-1, 1)))

       return softmax(distances / two_sig_sq)

   else:

       return softmax(distances)

困惑度


在上面的代碼段中,Sigmas 參數必須是長度為 N 的向量,且包含了每一個σ_i 的值,那麼我們如何取得這些σ_i 呢?這就是困惑度(perplexity)在 SNE 中的作用。條件概率矩陣 P 任意行的困惑度可以定義為:


其中 H(P_i) 為 P_i 的香農熵,即表達式如下:


在 SNE 和 t-SNE 中,困惑度是我們設置的參數(通常為 5 到 50 間)。我們可以為矩陣 P 的每行設置一個σ_i,而該行的困惑度就等於我們設置的這個參數。直觀來說,如果概率分布的熵較大,那麼其分布的形狀就相對平坦,該分布中每個元素的概率就更相近一些。

困惑度隨著熵增而變大,因此如果我們希望有更高的困惑度,那麼所有的 p_j|i(對於給定的 i)就會彼此更相近一些。換而言之,如果我們希望概率分布 P_i 更加平坦,那麼我們就可以增大σ_i。我們配置的σ_i 越大,概率分布中所有元素的出現概率就越接近於 1/N。實際上增大σ_i 會增加每個點的近鄰數,這就是為什麼我們常將困惑度參數大致等同於所需要的近鄰數量。

搜索σ_i


為了確保矩陣 P 每一行的困惑度 Perp(P_i) 就等於我們所希望的值,我們可以簡單地執行一個二元搜索以確定σ_i 能得到我們所希望的困惑度。這一搜索十分簡單,因為困惑度 Perp(P_i) 是隨σ_i 增加而遞增的函數,下面是基本的二元搜索函數:

def binary_search(eval_fn, target, tol=1e-10, max_iter=10000,

                 lower=1e-20, upper=1000.):

   """Perform a binary search over input values to eval_fn.

   # Arguments

       eval_fn: Function that we are optimising over.

       target: Target value we want the function to output.

       tol: Float, once our guess is this close to target, stop.

       max_iter: Integer, maximum num. iterations to search for.

       lower: Float, lower bound of search range.

       upper: Float, upper bound of search range.

   # Returns:

       Float, best input value to function found during search.

   """

   for i in range(max_iter):

       guess = (lower + upper) / 2.

       val = eval_fn(guess)

       if val > target:

           upper = guess

       else:

           lower = guess

       if np.abs(val - target) <= tol:

           break

   return guess

為了找到期望的σ_i,我們需要將 eval_fn 傳遞到 binary_search 函數,並且將σ_i 作為它的參數而返回 P_i 的困惑度。

以下的 find_optimal_sigmas 函數確實是這樣做的以搜索所有的σ_i,該函數需要採用負歐幾裡德距離矩陣和目標困惑度作為輸入。距離矩陣的每一行對所有可能的σ_i 都會執行一個二元搜索以找到能產生目標困惑度的最優σ。該函數最後將返回包含所有最優σ_i 的 NumPy 向量。

def calc_perplexity(prob_matrix):

   """Calculate the perplexity of each row

   of a matrix of probabilities."""

   entropy = -np.sum(prob_matrix * np.log2(prob_matrix), 1)

   perplexity = 2 ** entropy

   return perplexity

def perplexity(distances, sigmas):

   """Wrapper function for quick calculation of

   perplexity over a distance matrix."""

   return calc_perplexity(calc_prob_matrix(distances, sigmas))

def find_optimal_sigmas(distances, target_perplexity):

   """For each row of distances matrix, find sigma that results

   in target perplexity for that role."""

   sigmas = []

   # For each row of the matrix (each point in our dataset)

   for i in range(distances.shape[0]):

       # Make fn that returns perplexity of this row given sigma

       eval_fn = lambda sigma: \

           perplexity(distances[i:i+1, :], np.array(sigma))

       # Binary search over sigmas to achieve target perplexity

       correct_sigma = binary_search(eval_fn, target_perplexity)

       # Append the resulting sigma to our output array

       sigmas.append(correct_sigma)

   return np.array(sigmas)

對稱 SNE


現在估計 SNE 的所有條件都已經聲明了,我們能通過降低成本 C 對 Y 的梯度而收斂到一個良好的二維表徵 Y。因為 SNE 的梯度實現起來比較難,所以我們可以使用對稱 SNE,對稱 SNE 是 t-SNE 論文中一種替代方法。

在對稱 SNE 中,我們最小化 p_ij 和 q_ij 的聯合概率分布與 p_i|j 和 q_i|j 的條件概率之間的 KL 散度,我們定義的聯合概率分布 q_ij 為:


該表達式就如同我們前面定義的 softmax 函數,只不過分母中的求和是對整個矩陣進行的,而不是當前的行。為了避免涉及到 x 點的異常值,我們不是令 p_ij 服從相似的分布,而是簡單地令 p_ij=(p_i|j+p_j|i)/2N。

我們可以簡單地編寫這些聯合概率分布 q 和 p:

def q_joint(Y):

   """Given low-dimensional representations Y, compute

   matrix of joint probabilities with entries q_ij."""

   # Get the distances from every point to every other

   distances = neg_squared_euc_dists(Y)

   # Take the elementwise exponent

   exp_distances = np.exp(distances)

   # Fill diagonal with zeroes so q_ii = 0

   np.fill_diagonal(exp_distances, 0.)

   # Divide by the sum of the entire exponentiated matrix

   return exp_distances / np.sum(exp_distances), None

def p_conditional_to_joint(P):

   """Given conditional probabilities matrix P, return

   approximation of joint distribution probabilities."""

   return (P + P.T) / (2. * P.shape[0])

同樣可以定義 p_joint 函數輸入數據矩陣 X 並返回聯合概率 P 的矩陣,此外我們還能一同估計要求的σ_i 和條件概率矩陣:

def p_joint(X, target_perplexity):

   """Given a data matrix X, gives joint probabilities matrix.

   # Arguments

       X: Input data matrix.

   # Returns:

       P: Matrix with entries p_ij = joint probabilities.

   """

   # Get the negative euclidian distances matrix for our data

   distances = neg_squared_euc_dists(X)

   # Find optimal sigma for each row of this distances matrix

   sigmas = find_optimal_sigmas(distances, target_perplexity)

   # Calculate the probabilities based on these optimal sigmas

   p_conditional = calc_prob_matrix(distances, sigmas)

   # Go from conditional to joint probabilities matrix

   P = p_conditional_to_joint(p_conditional)

   return P

所以現在已經定義了聯合概率分布 p 與 q,若我們計算了這兩個聯合分布,那麼我們能使用以下梯度更新低維表徵 Y 的第 i 行:


在 Python 中,我們能使用以下函數估計梯度,即給定聯合概率矩陣 P、Q 和當前低維表徵 Y 估計梯度:

def symmetric_sne_grad(P, Q, Y, _):

   """Estimate the gradient of the cost with respect to Y"""

   pq_diff = P - Q  # NxN matrix

   pq_expanded = np.expand_dims(pq_diff, 2)  #NxNx1

   y_diffs = np.expand_dims(Y, 1) - np.expand_dims(Y, 0)  #NxNx2

   grad = 4. * (pq_expanded * y_diffs).sum(1)  #Nx2

   return grad

為了向量化變量,np.expand_dims 方法將十分有用,該函數最後返回的 grad 為 N*2 階矩陣,其中第 i 行為 dC/dy_i。一旦我們計算完梯度,那麼我們就能利用它執行梯度下降,即通過梯度下降迭代式更新 y_i。

估計對稱 SNE


前面已經定義了所有的估計對稱 SNE 所需要的函數,下面的訓練函數將使用梯度下降算法迭代地計算與更新權重。

def estimate_sne(X, y, P, rng, num_iters, q_fn, grad_fn, learning_rate,

                momentum, plot):

   """Estimates a SNE model.

   # Arguments

       X: Input data matrix.

       y: Class labels for that matrix.

       P: Matrix of joint probabilities.

       rng: np.random.RandomState().

       num_iters: Iterations to train for.

       q_fn: Function that takes Y and gives Q prob matrix.

       plot: How many times to plot during training.

   # Returns:

       Y: Matrix, low-dimensional representation of X.

   """

   # Initialise our 2D representation

   Y = rng.normal(0., 0.0001, [X.shape[0], 2])

   # Initialise past values (used for momentum)

   if momentum:

       Y_m2 = Y.copy()

       Y_m1 = Y.copy()

   # Start gradient descent loop

   for i in range(num_iters):

       # Get Q and distances (distances only used for t-SNE)

       Q, distances = q_fn(Y)

       # Estimate gradients with respect to Y

       grads = grad_fn(P, Q, Y, distances)

       # Update Y

       Y = Y - learning_rate * grads

       if momentum:  # Add momentum

           Y += momentum * (Y_m1 - Y_m2)

           # Update previous Y's for momentum

           Y_m2 = Y_m1.copy()

           Y_m1 = Y.copy()

       # Plot sometimes

       if plot and i % (num_iters / plot) == 0:

           categorical_scatter_2d(Y, y, alpha=1.0, ms=6,

                                  show=True, figsize=(9, 6))

   return Y

為了簡化表達,我們將使用 MNIST 數據集中標籤為 0、1 和 8 的 200 個數據點,該過程定義在 main() 函數中:

# Set global parameters

NUM_POINTS = 200            # Number of samples from MNIST

CLASSES_TO_USE = [0, 1, 8]  # MNIST classes to use

PERPLEXITY = 20

SEED = 1                    # Random seed

MOMENTUM = 0.9

LEARNING_RATE = 10.

NUM_ITERS = 500             # Num iterations to train for

TSNE = False                # If False, Symmetric SNE

NUM_PLOTS = 5               # Num. times to plot in training

def main():

   # numpy RandomState for reproducibility

   rng = np.random.RandomState(SEED)

   # Load the first NUM_POINTS 0's, 1's and 8's from MNIST

   X, y = load_mnist('datasets/',

                     digits_to_keep=CLASSES_TO_USE,

                     N=NUM_POINTS)

   # Obtain matrix of joint probabilities p_ij

   P = p_joint(X, PERPLEXITY)

   # Fit SNE or t-SNE

   Y = estimate_sne(X, y, P, rng,

            num_iters=NUM_ITERS,

            q_fn=q_tsne if TSNE else q_joint,

            grad_fn=tsne_grad if TSNE else symmetric_sne_grad,

            learning_rate=LEARNING_RATE,

            momentum=MOMENTUM,

            plot=NUM_PLOTS)

構建 t-SNE


前面我們已經分析了很多關於隨機近鄰嵌入的方法與概念,並推導出了對稱 SNE,不過幸運的是對稱 SNE 擴展到 t-SNE 是非常簡單的。真正的區別僅僅是我們定義聯合概率分布矩陣 Q 的方式,在 t-SNE 中,我們 q_ij 的定義方法可以變化為: 


上式通過假設 q_ij 服從自由度為 1 的學生 T 分布(Student t-distribution)而推導出來。Van der Maaten 和 Hinton 注意到該分布有非常好的一個屬性,即計數器(numerator)對於較大距離在低維空間中具有反平方變化規律。本質上,這意味著該算法對於低維映射的一般尺度具有不變性。因此,最優化對於相距較遠的點和相距較近的點都有相同的執行方式。

這就解決了所謂的「擁擠問題」,即當我們試圖將一個高維數據集表徵為 2 或 3 個維度時,很難將鄰近的數據點與中等距離的數據點區分開來,因為這些數據點都聚集在一塊區域。

我們能使用以下函數計算新的 q_ij:

def q_tsne(Y):

   """t-SNE: Given low-dimensional representations Y, compute

   matrix of joint probabilities with entries q_ij."""

   distances = neg_squared_euc_dists(Y)

   inv_distances = np.power(1. - distances, -1)

   np.fill_diagonal(inv_distances, 0.)

   return inv_distances / np.sum(inv_distances), inv_distances

注意我們使用 1. - distances 代替 1. + distances,該距離函數將返回一個負的距離。現在剩下的就是重新估計損失函數對 Y 的梯度,t-SNE 論文中推導該梯度的表達式為:


同樣,我們很容易按照計算對稱 SNE 梯度的方式構建 t-SNE 的梯度計算方式:

def tsne_grad(P, Q, Y, inv_distances):

   """Estimate the gradient of t-SNE cost with respect to Y."""

   pq_diff = P - Q

   pq_expanded = np.expand_dims(pq_diff, 2)

   y_diffs = np.expand_dims(Y, 1) - np.expand_dims(Y, 0)

   # Expand our inv_distances matrix so can multiply by y_diffs

   distances_expanded = np.expand_dims(inv_distances, 2)

   # Multiply this by inverse distances matrix

   y_diffs_wt = y_diffs * distances_expanded

   # Multiply then sum over j's

   grad = 4. * (pq_expanded * y_diffs_wt).sum(1)

   return grad

以上我們就完成了 t-SNE 的具體理解與實現,那麼該算法在具體數據集中的可視化效果是怎樣的呢?Jake Hoare 給出了實現可視化的效果與對比。

t-SNE 可視化


下面,我們將要展示 t-SNE 可視化高維數據的結果,第一個數據集是基於物理特徵分類的 10 種不同葉片。這種情況下,t-SNE 需要使用 14 個數值變量作為輸入,其中就包括葉片的生長率和長寬比等。下圖展示了 2 維可視化輸出,植物的種類(標籤)使用不同的顏色表達。


物種 Acer palmatum 的數據點在右上角形成了一個橙色集群,這表明它的葉子和其他物種有很大的不同。該示例中類別通常會有很好的分組,相同物種的葉子(同一顏色的數據點)趨向於彼此靠緊聚集在一起。左下角有兩種顏色的數據點靠近在一起,說明這兩個物種的葉子形狀十分相似。

最近鄰準確度表明給定兩個隨機點,它們是相同物種的概率是多少。如果這些數據點完美地根據不同物種而分類,那麼準確度就會非常接近 100%,高準確度意味著數據能被乾淨地分為不同的集群。

調整困惑度


下面,我們對可樂品牌做了類似的分析。為了演示困惑度(perplexity)的影響,我們首先需要將困惑度設置為較低的值 2,每個數據點的映射只考慮最近鄰。如下,我們將看到許多離散的小集群,並且每一個集群只有少量的數據點。


下面我們將 t-SNE 的困惑度設置為 100,我們可以看到數據點變得更加擴散,並且同一類之間的聯繫變弱。


在該案例中,可樂本身就要比樹葉更難分割,即使一類數據點某個品牌要更集中一些,但仍然沒有明確的邊界。

在實踐中,困惑度並沒以一個絕對的標準,不過一般選擇 5 到 50 之間會有比較好的結果。並且在這個範圍內,t-SNE 一般是比較魯棒的。

預測的解釋


度量數據點之間的角度或距離並不能推斷出任何數據上的具體或定量的信息,所以 t-SNE 的預測更多的是用於可視化數據。

在模型搭建前期直觀地挖掘數據模式有助於指導數據科學下一步進程。如果 t-SNE 能很好地分割數據點,那麼機器學習同樣也能找到一種將未知新數據投影到相應類別的好方法。給定一種預測算法,我們就能實現很高的準確度。

上例中每一個類別都是孤立分類的,因此簡單的機器學習模型就能將該類別與其他類別分離開。但如果類別重疊,我們可能就要構建更精細的模型做出預測。如下所示,如果我們按照某個品牌的偏好從 1 到 5 進行分類,那麼類別可能更加離散、更難以預測,最近鄰精度也會相對較低。



對比 PCA


很自然我們就希望將 t-SNE 和其他降維算法做比較。降維算法中比較流行的是主成分分析法(PCA),PCA 會尋找能儘可能保留數據方差的新維度。有較大的方差的數據保留的信息就越多,因為彼此不同的數據可以提供不同的信息,所以我們最好是保留彼此分離的數據點,因為它們提供了較大的方差。

下面是採用 PCA 算法對上文的樹葉類別進行降維的結果,我們看到雖然左側的橙色是分離的,但其它類別都有點混合在一起。這是因為 PCA 並不關心局部的最近鄰關係,此外 PCA 是一種線性方法,所以它表徵非線性關係可能效果並不是很好。不過 PCA 算法在壓縮數據為更小的特徵向量而投入到預測算法中有很好地表現,這一點它要比 t-SNE 效果更好。



結語


t-SNE 是一種可視化高維數據的優秀算法,它經常要比其它降維算法生成更具特點的可視化結果。在數據分析中,獲得數據的先驗知識總是很重要的,正如華羅庚先生說過:數無形時少直覺,形少數時難入微,我們只有先理解了數據的大概分布,然後再能選擇具體的算法對這些數據進一步分析。數形結合百般好,隔離分家萬事休,也許高維數據的可視化與機器學習算法的結合才是數據分析的正確打開方式。

參考連結:

http://www.jmlr.org/papers/volume9/vandermaaten08a/vandermaaten08a.pdf

https://www.displayr.com/using-t-sne-to-visualize-data-before-prediction/

https://nlml.github.io/in-raw-numpy/in-raw-numpy-t-sne/

本文為機器之心整理,轉載請聯繫本公眾號獲得授權

✄---

加入機器之心(全職記者/實習生):hr@jiqizhixin.com

投稿或尋求報導:content@jiqizhixin.com

廣告&商務合作:bd@jiqizhixin.com

相關焦點

  • t-SNE:可視化效果最好的降維算法
    對於數據科學專業人員來說,有必要對工作數據進行可視化和深入了解,以便更好地完成工作,我們可以使用降維技術降維技術的另一個最受歡迎的用例是在訓練ML模型時降低計算複雜度。通過使用降維技術,數據集的大小已經縮小,與此同時,有關原始數據的信息也已應用於低維數據。因此,機器學習算法從輸入數據集中學習既簡單又省時。
  • 大數據可視化利器-流形學習t-SNE
    文 | 光大科技大數據部 額日和1 數據可視化與降維2 算法原理簡介3 t-SNE實現和應用4.擁擠問題可以簡單理解為可視化時各個簇聚集在一起,無法區分。為解決該問題,t-SNE在高維空間中使用高斯分布,而在低維空間中使用自由度為1的學生分布(t-distribution)。相較於高斯分布,學生分布有著長尾的特點,使得高維度下距離適中的點在映射後能夠有一個較大的距離,如下圖所示:
  • 通俗理解一個常用的降維算法(t-SNE)
    當我們想對高維數據集進行分類,但又不清楚這個數據集有沒有很好的可分性(同類之間間隔小、異類之間間隔大)時,可以通過降維算法將數據投影到二維或三維空間中。很久以前,就有人提出一種降維算法,主成分分析(PCA) 降維法,中間其他的降維算法陸續出現,比如 多維縮放(MDS),線性判別分析(LDA),等度量映射(Isomap)。
  • t-SNE原理總覽
    引言:t-SNE 是一種非線性降維算法,非常適用於高維數據降維到2維或者3維,進行可視化。
  • 快學學大牛最愛的t-SNE算法吧(附Python/R代碼)
    現在,一定會有很多人心裡想著「我會使用PCA來降維和可視化」。 好吧,你是對的! PCA絕對是具有大量特徵的數據集的降維和可視化的不錯選擇。 但是,假如你能使用比PCA更先進的東西將會怎樣呢?如果你可以很容易地找出非線性的模式呢? 在本文中,我將告訴你一個比PCA(1933)更有效、被稱為t-SNE(2008)的新算法。
  • 比PCA降維更高級——(R/Python)t-SNE聚類算法實踐指南
    關於PCA  現實中大多數人會使用PCA進行降維和可視化,但為什麼不選擇比PCA更先進的東西呢?關於PCA的介紹可以閱讀該文獻。本文講解比PCA(1933)更有效的算法t-SNE(2008)。本文內容1 什麼是t-SNE?2 什麼是降維?
  • 你真的會用 t-SNE 麼?有關 t-SNE 的小技巧
    【導讀】t-SNE[1] 是高維數據可視化的一個重要工具,但是在真實的使用場景中,t-SNE 的表現,總是令人很困惑。
  • sklearn與機器學習系列專題之降維(七)一文弄懂t-SNE特徵篩選&降維
    ,小編也不知道,隨緣吧)裡,小編在此再次介紹一種流行學習方法——t-Distributed 隨機鄰域嵌入算法(t-distributed stochastic neighbor embedding,t-SNE),該算法的初衷也是用於可視化高維複雜的數據結構,因此,也經常被用來和LLE算法作對比(如在LLE專題中的實戰一欄已作對比)。
  • t-SNE:最好的降維方法之一
    Visualizing data using t-SNE. Journal of Machine Learning Research, 9(Nov), 2579-2605.[3] Maaten, L. V. D., & Hinton, G. (2008). Visualizing data using t-SNE.
  • 人人都可以輕鬆繪製炫酷的t-SNE圖啦~
    主成分分析(PCA)是提煉數據信息的有效方法,但是PCA降維在面對龐大的數據信息可視化時顯得無力。t分布隨機鄰接嵌入(t-SNE)屬於非線性降維,在大數據可視化中的表現明顯優於PCA,成為數據可視化算法中的翹楚。t-SNE通過單細胞測序分析進入生物學研究者的視野,也使得很多人誤以為t-SNE降維是單細胞測序分析的獨有內容。
  • 【乾貨】深度學習必備:隨機梯度下降(SGD)優化算法及可視化
    來源:CSDN 授權轉載作者:Sebastian Ruder譯者:一隻鳥的天空【新智元導讀】梯度下降算法是機器學習中使用非常廣泛的優化算法,也是眾多機器學習算法中最常用的優化方法。Early Stopping         Gradient noise梯度下降算法是通過沿著目標函數J(θ)參數θ∈R的梯度(一階導數)相反方向−∇θJ(θ)來不斷更新模型參數來到達目標函數的極小值點(收斂),更新步長為η。
  • Adam 優化算法詳解
    這在深度學習領域起著至關重要的作用(可能是整個人工智慧),因為您選擇的優化算法可能是在數分鐘,數小時或數天(有時甚至是數周)內獲得高質量結果的區別。在這篇文章中,我們將闡述:什麼是Adam Optimizer?
  • 《專利分析可視化》作圖詳解
    本文是《專利分析可視化》中所有圖表的作圖詳解文章連結清單。對於太簡單的圖表(文中灰色字體),就不寫作圖詳解了。
  • 人工智慧黑盒揭秘:深度神經網絡可視化技術
    相比較其他深度、前饋神經網絡,CNN 需要的參數更少,能夠更好的利用 GPU 作大規模並行處理,使之成為一種頗具吸引力的深度學習結構。DeconvNet 技術除了可以觀察解釋 CNN 內部結構外,還可以用來排除模型建立和調試時遇到的問題,以及通過分析內部結果來得到更好的模型。研究表明 CNN 模型一大優勢就是預測精確度與內部隱藏層的局部結構有很強的關聯。
  • 基於TensorFlow理解三大降維技術:PCA、t-SNE 和自編碼器
    為了幫助理解,他還為其中每種相關算法編寫了代碼(也發布在了 GitHub 上)。機器之心對本文進行了編譯介紹。代碼地址:https://github.com/eliorc/Medium/blob/master/PCA-tSNE-AE.ipynb在這篇文章中,我將盡我所能揭秘三種降維技術:PCA、t-SNE 和自編碼器。
  • 深度學習最常用的學習算法:Adam優化算法
    聽說你了解深度學習最常用的學習算法:Adam優化算法?-深度學習世界。深度學習常常需要大量的時間和機算資源進行訓練,這也是困擾深度學習算法開發的重大原因。雖然我們可以採用分布式並行訓練加速模型的學習,但所需的計算資源並沒有絲毫減少。而唯有需要資源更少、令模型收斂更快的最優化算法,才能從根本上加速機器的學習速度和效果,Adam 算法正為此而生!
  • 常用算法詳解——列印楊輝三角形
    在中國南宋數學家楊輝1261年所著的《詳解九章算法》一書中出現。在歐洲,這個表叫做帕斯卡三角形。帕斯卡(1623----1662)是在1654年發現這一規律的,比楊輝要遲393年,比賈憲遲600年。楊輝三角是中國古代數學的傑出研究成果之一,它把二項式係數圖形化,把組合數內在的一些代數性質直觀地從圖形中體現出來,是一種離散型的數與形的結合。
  • 深度 | 從修正Adam到理解泛化:概覽2017年深度學習優化算法的最新研究進展
    在這篇博客中,我將介紹深度學習優化算法中幾個最有意義的進展以及最有潛力的方向。這篇博客假定讀者熟悉 SGD 和適應性學習率方法,如 Adam。如果想快速入門,可以查看 Ruder 以前的博客以概覽當前已有的梯度下降優化算法:深度解讀最流行的優化算法:梯度下降,或參見更加基礎與入門的文章:目標函數的經典優化算法介紹。
  • 深度 KDnuggets 官方調查:數據科學家最常用的十種算法
    我們注意到最常用的方法仍然是回歸、聚類、決策樹/Rules 和可視化。職業類型% 投票者比例平均算法使用個數% 監督算法使用度% 無監督算法使用度% 元使用度%其他方法使用度1產業59%8.494%81%
  • tsne-高維數據的降維與可視化
    假設數據是均勻採樣於一個高維歐氏空間中的低維流形,流形學習就是從高維採樣數據中恢復低維流形結構,即找到高維空間中的低維流形,並求出相應的嵌入映射,以實現維數約簡或者數據可視化。它是從觀測到的現象中去尋找事物的本質,找到產生數據的內在規律。