- UMAP(Uniform Manifold Approximation and Projection)是一種強大的維度降低技術,它允許我們將高維度數據集映射到低維度空間,同時盡可能保留原始數據的結構。這種方法特別適用於大規模數據集和機器學習任務,因為它不僅效率高,而且能夠揭示數據的內在結構和模式。
- UMAP的工作原理基於拓撲學的概念,它首先在高維空間中構建一個近似幾何結構,然後試圖在低維空間中以最佳方式再現這種結構。這樣,UMAP不僅能夠有效地降低數據的維度,而且還能在降維過程中保留數據點之間的相對距離和分布,使得降維後的數據依然能夠反映出原始數據集的關鍵特性和結構。
- UMAP廣泛應用於各種領域,包括生物信息學、社會網絡分析、影像處理等,它對於數據可視化、特徵提取和機器學習模型的預處理具有重要意義。與其他維度降低方法相比,UMAP在保持局部結構的同時,還能夠揭示數據的全局分布,使其成為維度降低和數據探索領域的一個強有力的工具。
- 步驟 1: 安裝必要的庫
- 確保已安裝以下必要的Python庫:
- numpy
- matplotlib
- sklearn
- umap-learn
- 如果尚未安裝,可以使用pip進行安裝,例如:
- pip install numpy matplotlib scikit-learn umap-learn
- 確保已安裝以下必要的Python庫:
- 步驟 2: 生成模擬數據
- 我們將使用scikit-learn的
**make_blobs**
函數來生成一組模擬的高維數據。
- 我們將使用scikit-learn的
# 生成模擬數據 X:(300,10) y:(300) 類別為5類 X, y = make_blobs(n_samples=300, centers=5, n_features=10, random_state=42)
- 步驟 3: 使用UMAP進行降維
- 然後,我們將使用UMAP對這些數據進行降維,將數據從高維空間映射到二維空間,以便於可視化。
umap_model = UMAP(n_neighbors=5, min_dist=0.3, n_components=2, random_state=42) X_reduced = umap_model.fit_transform(X)
- 步驟 4: 可視化降維後的數據
- 最後,我們將使用matplotlib可視化降維後的結果。由於降成兩維,因此畫出所有數據的x,y 座標

# 可視化降維後的數據
plt.figure(figsize=(8, 6))
plt.scatter(X_reduced[:, 0], X_reduced[:, 1], c=y, cmap='Spectral', s=5) plt.title('UMAP Dimensionality Reduction') plt.colorbar(label='Group ID') plt.show()
完整程式碼
import numpy as np
from sklearn.datasets import make_blobs
from umap import UMAP
import matplotlib.pyplot as plt
# 生成模擬數據
X, y = make_blobs(n_samples=300, centers=5, n_features=10, random_state=42)
# 使用UMAP進行降維
umap_model = UMAP(n_neighbors=5, min_dist=0.3, n_components=2, random_state=42)
X_reduced = umap_model.fit_transform(X)
# 可視化降維後的數據
plt.figure(figsize=(8, 6))
plt.scatter(X_reduced[:, 0], X_reduced[:, 1], c=y, cmap='Spectral', s=5)
plt.title('UMAP Dimensionality Reduction')
plt.colorbar(label='Group ID')
# plt.show()
plt.savefig("image/UMAP_example.png")
多組資料集完整程式碼
import numpy as np
from sklearn.datasets import make_blobs
from matplotlib import pyplot as plt
from umap import UMAP
class UMAPVisualizer:
def __init__(self, n_components=2, n_neighbors=30, min_dist=0.1, random_state=None):
self.n_components = n_components
self.n_neighbors = n_neighbors
self.min_dist = min_dist
self.random_state = random_state
self.data = []
self.labels = []
self.dataset_ids = [] # 保存每個點屬於的數據集ID
self.dataset_props = {} # 用字典保存每個數據集的顏色深淺設置
def add_data(self, features, labels, dataset_id, dataset_color_intensity=1.0):
self.data.append(features)
self.labels.extend(labels)
self.dataset_ids.extend([dataset_id] * len(labels))
if dataset_id not in self.dataset_props:
self.dataset_props[dataset_id] = {'color_intensity': dataset_color_intensity}
def run_umap(self):
all_data = np.concatenate(self.data, axis=0)
self.umap_results = UMAP(init='random', densmap=True, n_components=self.n_components, random_state=self.random_state).fit_transform(all_data)
def visualize(self, save_path=None):
unique_labels = list(set(self.labels))
# base_colors = plt.cm.tab10(np.linspace(0, 1, len(unique_labels)))
base_colors = plt.cm.Set1(np.linspace(0, 1, len(unique_labels)))
plt.figure(figsize=(10, 10))
for i, label in enumerate(unique_labels):
for dataset_id in self.dataset_props:
indices = [idx for idx, (lbl, ds_id) in enumerate(zip(self.labels, self.dataset_ids)) if lbl == label and ds_id == dataset_id]
intensity = self.dataset_props[dataset_id]['color_intensity']
# 調整顏色的亮度,使之根據數據集的不同而有所變化
adjusted_color = base_colors[i] * intensity
plt.scatter(self.umap_results[indices, 0], self.umap_results[indices, 1],
color=[adjusted_color], label=f"Dataset {dataset_id}: {label}", alpha=0.8)
plt.legend()
plt.title('UMAP Visualization')
if save_path:
plt.savefig(save_path)
# 生成模擬數據
def main():
features1, labels1 = make_blobs(n_samples=100, centers=2, n_features=2, random_state=42)
features2, labels2 = make_blobs(n_samples=100, centers=2, n_features=2, random_state=43)
visualizer = UMAPVisualizer(random_state=42)
visualizer.add_data(features1, labels1, dataset_id="a", dataset_color_intensity=0.5) # 淺色
visualizer.add_data(features2, labels2, dataset_id="b", dataset_color_intensity=0.9) # 深色
visualizer.run_umap()
visualizer.visualize(save_path="image/test_set_umap.jpg")
if __name__=="__main__":
main()
