?一、前言
????????在機器學習和數據科學領域,高維數據的可視化是一個極具挑戰但又至關重要的問題。高維數據難以直觀地理解和分析,而有效的可視化方法能夠幫助我們發現數據中的潛在結構、模式和關系。本文以經典的MNIST手寫數字數據集為例,探討如何利用t-分布隨機鄰域嵌入(t-SNE)這一強大的降維技術,將高維的圖像數據降維到二維空間,并進行可視化展示。通過本文,我們將深入了解t-SNE的原理、算法步驟,以及如何在Python中實現并應用它,從而更好地理解和探索高維數據的內在特性。
二、技術與原理簡介
????????在深入探討t-SNE之前,我們首先需要區分機器學習中的兩大主要范疇:監督學習和無監督學習。
????????1.?監督學習
????????監督學習是指在已知輸入數據和對應標簽的情況下,訓練模型學習輸入與輸出之間的映射關系。模型通過學習大量的帶標簽數據,能夠對新的、未見過的數據進行預測或分類。常見的監督學習算法包括:
- 線性回歸:?用于預測連續型變量。
- 邏輯回歸:?用于分類問題。
- 支持向量機 (SVM):?用于分類和回歸問題,尤其擅長處理高維數據。
- 決策樹:?基于樹狀結構進行決策,易于理解和解釋。
- 隨機森林:?集成多個決策樹,提高預測的準確性和魯棒性。
- 神經網絡:?模擬人腦神經元結構,能夠學習復雜的非線性關系。
????????2. 無監督學習
????????無監督學習是指在沒有標簽的情況下,訓練模型發現數據中的潛在結構和模式。模型通過分析數據的內在特征,能夠進行聚類、降維、關聯規則挖掘等任務。常見的無監督學習算法包括:
- 聚類:?將數據劃分為不同的簇,使得同一簇內的數據相似度較高,不同簇之間的數據相似度較低。常見的聚類算法包括K-means、層次聚類、DBSCAN等。
- 降維:?將高維數據降維到低維空間,同時盡可能保留數據的關鍵信息。常見的降維算法包括主成分分析 (PCA)、t-SNE、UMAP等。
- 關聯規則挖掘:?發現數據中不同項之間的關聯關系,例如購物籃分析。
????????3. 監督學習與無監督學習的區別
? ? ? ? 4. MNIST數據集簡介
????????MNIST (Modified National Institute of Standards and Technology database) 是一個經典的手寫數字數據集,廣泛應用于機器學習和深度學習領域。它包含60,000個訓練樣本和10,000個測試樣本,每個樣本都是一個28x28像素的灰度圖像,代表0到9之間的手寫數字。
????????4.1 數據格式
????????MNIST數據集通常以兩種格式提供:
- 圖像格式:?每個樣本都是一個圖像文件,例如PNG或JPEG格式。
- 數值格式:?每個樣本都被轉換為一個784維的向量,其中每個元素代表一個像素的灰度值 (0到255)。
? ? ? ?4.2 數據集特點
- 規模適中:?MNIST數據集的規模適中,既可以用于快速原型驗證,又可以用于訓練復雜的模型。
- 易于獲取:?MNIST數據集可以從多個來源免費獲取,例如Scikit-learn、TensorFlow等。
- 廣泛應用:?MNIST數據集被廣泛應用于各種機器學習和深度學習算法的評估和比較。
? ? ? ? 5. t-SNE算法原理與數學推導
? ? ? ? 5.1 算法核心思想
????????t-SNE(t-Distributed Stochastic Neighbor Embedding)是一種非線性降維技術,通過以下步驟實現高維數據到低維空間的映射:
- 計算高維相似度:在原始空間中,計算每對樣本間的相似度
- 構建低維嵌入空間:在目標空間(如2D)中,通過優化使相似度分布匹配
- 梯度下降優化:最小化兩空間分布的KL散度
? ? ? ? 5.2 數學公式詳解
????????5.2.1 高維相似度計算
????????對原始空間中的樣本對(𝑥𝑖,𝑥𝑗) ,定義條件概率:
其中𝜎𝑖 ?為高斯核帶寬,通過二分查找確定以滿足** perplexity **參數(控制鄰域大小)。
????????5.2.2 低維相似度建模
????????在目標空間中,定義聯合概率:
????????采用t-分布(自由度為1的Student分布)以增強對異常值的魯棒性。
? ? ? ? 5.2.3 目標函數優化
????????通過最小化KL散度實現分布匹配:
其中
????????優化過程使用梯度下降:
? ? ? ? 5.3 算法步驟流程
- 參數初始化:設置降維維度(如2D)、perplexity(通常5-50)、學習率等
- 高維相似度計算:為每個樣本計算條件概率矩陣𝑃P
- 低維初始化:隨機生成初始嵌入坐標𝑌Y
- 梯度下降優化:迭代更新𝑌Y以最小化KL散度
- 結果輸出:返回低維坐標矩陣
三、代碼詳解
????????本文的代碼主要分為以下幾個部分:
????????1. 導入庫
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from sklearn import datasets
from sklearn import manifold
%matplotlib inline
說明:
import matplotlib.pyplot as plt
: 導入matplotlib庫,用于繪制圖像。import numpy as np
: 導入numpy庫,用于進行數值計算。import pandas as pd
: 導入pandas庫,用于數據處理。import seaborn as sns
: 導入seaborn庫,用于數據可視化。from sklearn import datasets
: 導入sklearn庫中的datasets模塊,用于加載數據集。from sklearn import manifold
: 導入sklearn庫中的manifold模塊,用于降維。%matplotlib inline
: 在Jupyter Notebook中顯示圖像。
????????2. 加載數據
# 加載數據
data = datasets.fetch_openml('mnist_784', version=1, return_X_y=True)
pixel_values, targets = data
targets = targets.astype(int)# 將DataFrame轉換為numpy數組以便更容易操作
# 如果pixel_values已經是numpy數組,這一步可以跳過
if isinstance(pixel_values, pd.DataFrame):pixel_values_array = pixel_values.values
else:pixel_values_array = pixel_values
說明:
data = datasets.fetch_openml('mnist_784', version=1, return_X_y=True)
: 使用datasets.fetch_openml
函數加載MNIST數據集。'mnist_784'
表示數據集的名稱,version=1
表示數據集的版本,return_X_y=True
表示返回輸入數據和標簽。pixel_values, targets = data
: 將返回的數據解包為pixel_values
和targets
。pixel_values
包含圖像的像素值,targets
包含圖像的標簽。targets = targets.astype(int)
: 將標簽轉換為整數類型。if isinstance(pixel_values, pd.DataFrame):
: 檢查pixel_values
是否為pandas DataFrame類型。pixel_values_array = pixel_values.values
: 如果pixel_values
為pandas DataFrame類型,則將其轉換為numpy數組。else: pixel_values_array = pixel_values
: 否則,直接使用pixel_values
。
? ? ? ? 3. 顯示單個圖像
# 顯示單個圖像
single_image = pixel_values_array[1].reshape(28, 28)
plt.imshow(single_image, cmap='gray')
說明:
single_image = pixel_values_array[1].reshape(28, 28)
: 選擇第一個圖像,并將其reshape為28x28的矩陣。plt.imshow(single_image, cmap='gray')
: 使用plt.imshow
函數顯示圖像,cmap='gray'
表示使用灰度顏色映射。
????????4. t-SNE降維
# t-SNE降維
tsne = manifold.TSNE(n_components=2, random_state=42)
transformed_data = tsne.fit_transform(pixel_values_array[:3000])
說明:
tsne = manifold.TSNE(n_components=2, random_state=42)
: 創建一個t-SNE對象。n_components=2
表示將數據降維到二維空間,random_state=42
表示設置隨機種子,保證結果的可重復性。transformed_data = tsne.fit_transform(pixel_values_array[:3000])
: 使用fit_transform
函數對數據進行降維。這里只使用了前3000個樣本,因為t-SNE的計算復雜度較高。
? ? ? ? 5. 創建DataFrame用于可視化
# 創建DataFrame用于可視化
tsne_df = pd.DataFrame(np.column_stack((transformed_data, targets[:3000])),columns=["x", "y", "targets"]
)
tsne_df.loc[:, "targets"] = tsne_df.targets.astype(int)
說明:
tsne_df = pd.DataFrame(...)
: 創建一個pandas DataFrame對象,用于存儲降維后的數據和標簽。np.column_stack((transformed_data, targets[:3000]))
: 將降維后的數據和標簽按列拼接在一起。columns=["x", "y", "targets"]
: 設置DataFrame的列名。tsne_df.loc[:, "targets"] = tsne_df.targets.astype(int)
: 將DataFrame中的標簽轉換為整數類型。
? ? ? ? 6. 可視化
# 可視化
# 注意:在新版本的seaborn中,size參數已更改為height
try:grid = sns.FacetGrid(tsne_df, hue="targets", size=8)
except TypeError:grid = sns.FacetGrid(tsne_df, hue="targets", height=8)grid.map(plt.scatter, "x", "y").add_legend()
說明:
grid = sns.FacetGrid(tsne_df, hue="targets", size=8)
: 創建一個seaborn FacetGrid對象,用于可視化降維后的數據。hue="targets"
表示使用標簽作為顏色編碼,size=8
表示設置圖像的大小。grid.map(plt.scatter, "x", "y").add_legend()
: 使用plt.scatter
函數繪制散點圖,"x"
和"y"
表示散點圖的橫坐標和縱坐標,add_legend()
表示添加圖例。
? ? ? ? 7. 完整代碼
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from sklearn import datasets
from sklearn import manifold
%matplotlib inline# 加載數據
data = datasets.fetch_openml('mnist_784', version=1, return_X_y=True)
pixel_values, targets = data
targets = targets.astype(int)# 將DataFrame轉換為numpy數組以便更容易操作
# 如果pixel_values已經是numpy數組,這一步可以跳過
if isinstance(pixel_values, pd.DataFrame):pixel_values_array = pixel_values.values
else:pixel_values_array = pixel_values# 顯示單個圖像
single_image = pixel_values_array[1].reshape(28, 28)
plt.imshow(single_image, cmap='gray')# t-SNE降維
tsne = manifold.TSNE(n_components=2, random_state=42)
transformed_data = tsne.fit_transform(pixel_values_array[:3000])# 創建DataFrame用于可視化
tsne_df = pd.DataFrame(np.column_stack((transformed_data, targets[:3000])),columns=["x", "y", "targets"]
)
tsne_df.loc[:, "targets"] = tsne_df.targets.astype(int)# 可視化
# 注意:在新版本的seaborn中,size參數已更改為height
try:grid = sns.FacetGrid(tsne_df, hue="targets", size=8)
except TypeError:grid = sns.FacetGrid(tsne_df, hue="targets", height=8)grid.map(plt.scatter, "x", "y").add_legend()
四、總結與思考
????????本文以MNIST數據集為例,詳細介紹了如何使用t-SNE進行高維數據可視化。通過t-SNE降維,我們可以將784維的圖像數據降維到二維空間,并在散點圖上清晰地看到不同數字之間的分布情況。
????????t-SNE是一種強大的降維技術,但也有一些局限性:
- 計算復雜度高:?t-SNE的計算復雜度為O(n^2),對于大規模數據集,計算時間會非常長。
- 參數敏感:?t-SNE的性能受到參數的影響,例如困惑度 (perplexity) 和學習率 (learning_rate)。
- 全局結構失真:?t-SNE主要關注局部結構,可能會導致全局結構失真。
????????在實際應用中,我們需要根據具體情況選擇合適的降維技術。對于大規模數據集,可以考慮使用PCA或UMAP等更高效的算法。對于需要保留全局結構的場景,可以考慮使用Isomap或LLE等算法。
【作者聲明】
????????本文內容基于作者對基于t-SNE的MNIST數據集可視化探索實現過程的實驗與總結,所有數據和代碼均為原創。文章中的觀點僅代表個人見解,供讀者參考交流。若有任何問題或建議,歡迎在評論區留言討論,共同促進技術進步。
?【關注我們】
????????如果您對神經網絡、群智能算法及人工智能技術感興趣,歡迎點贊、收藏并轉發,與更多朋友一起探討與交流!