流形學習方法在處理高維資料時,能捕捉資料內在的非線性結構,提供不同於 PCA 的視角。然而,實際應用中,流形學習也面臨一些挑戰,例如難以處理缺失值和噪聲資料,引數選擇缺乏明確的指導原則,以及計算成本較高等問題。相較之下,PCA 對於噪聲和缺失值有較佳的容錯能力,且計算效率更高。因此,在實際應用中,建議先使用 PCA 進行初步探索,再根據需要選擇流形學習方法。本文以 Isomap 為例,展示其在人臉圖片資料集上的應用,並說明如何使用 Isomap 進行降維和視覺化。同時,也簡要介紹了 K-Means 演算法在資料分群上的應用,以及如何使用核化 K-Means 處理非線性邊界的資料。

人類對於流形學習方法的思考

儘管流形學習的例子很有說服力,但在實踐中,流形學習技術往往很難掌握,因此很少用於高維度資料的簡單質性視覺化以外的目的。以下是流形學習的一些特定挑戰,這些挑戰與PCA形成鮮明對比: 在流形學習中,沒有很好的框架來處理缺失資料。相比之下,PCA有一種簡單的迭代方法來處理缺失資料。 在流形學習中,資料中的噪音可以「短路」流形並大大改變嵌入。相比之下,PCA自然地從最重要的元件中過濾掉噪音。 流形嵌入結果通常嚴重依賴於所選鄰居的數量,一般沒有很好的量化方法來選擇最佳鄰居數量。相比之下,PCA不涉及這種選擇。 在流形學習中,輸出維度的全域性最佳數量很難確定。相比之下,PCA允許您根據解釋變異來找到輸出維度的數量。 在流形學習中,嵌入維度的含義不總是清晰的。在PCA中,主元件具有非常清晰的含義。 流形學習方法的計算成本隨著資料點數量的增加而增加(O[N^2]或O[N^3])。相比之下,PCA有一些隨機方法,可以更快地完成(雖然請參考megaman套件中一些更可擴充套件的流形學習實作)。 綜上所述,流形學習方法相比PCA的唯一明顯優勢是它們能夠保留資料中的非線性關係;因此,我傾向於只在先用PCA探索資料後才使用流形方法來探索資料。 Scikit-Learn實作了超過LLE和Isomap(我們在前幾章中使用過,並將在下一節中進行檢視)的幾個常見的流形學習變體:Scikit-Learn檔案中有一個很好的討論和比較。根據我的經驗,我會給出以下建議: 對於之前看到的S-curve等玩具問題,LLE及其變體(尤其是修改過的LLE)表現得非常好。這是在sklearn.manifold.LocallyLinearEmbedding中實作的。 對於來自真實世界源的高維度資料,LLE通常會產生糟糕的結果,而Isomap似乎通常會導致更有意義的嵌入。這是在sklearn.manifold.Isomap中實作的。 對於高度叢集的資料,t-分佈隨機鄰居嵌入(t-SNE)似乎效果很好,儘管它可能比其他方法慢得多。這是在sklearn.manifold.TSNE中實作的。 如果您有興趣感受一下這些方法是如何工作的,我建議您在本文中的資料上執行每種方法。 範例:臉部的Isomap 流形學習通常用於理解高維度資料點之間的關係。高維度資料的一個常見情況是影像:例如,一組每個影像有1,000個畫素的影像可以被視為一組1,000維空間中的點,每個畫素的亮度定義了該維度中的坐標。 為了演示,我們將在Labeled Faces in the Wild資料集上的部分資料上應用Isomap,我們之前在第43章和第45章中看到過這個資料集。執行此命令將下載資料集並將其快取到您的主目錄中以供稍後使用:

from sklearn.datasets import fetch_lfw_people
faces = fetch_lfw_people(min_faces_per_person=30)
faces.data.shape

輸出:

(2370, 2914)

我們有2,370個影像,每個影像有2,914個畫素。換句話說,這些影像可以被視為2,914維空間中的資料點!讓我們顯示其中幾個影像,以便我們記住自己正在處理什麼(見圖46-11)。

fig, ax = plt.subplots(4, 8, subplot_kw=dict(xticks=[], yticks=[]))
for i, axi in enumerate(ax.flat):

內容解密:

上述程式碼使用fetch_lfw_people函式從Scikit-Learn資料集載入臉部影像資料。然後,它使用plt.subplots建立一個4x8的子圖網格,以顯示部分臉部影像。subplot_kw引數用於關閉x和y軸上的刻度標籤,以便更好地顯示影像。

圖表翻譯:

此圖顯示了Labeled Faces in the Wild資料集中的部分臉部影像。每個影像是2,914維空間中的一個資料點,其中每個維度對應於影像中的一個畫素。Isomap演算法可以用於將這些高維度資料點降維到較低維度空間中,以便更好地視覺化和理解資料結構。

使用PCA和Isomap進行人臉圖片降維分析

在前面的章節中,我們曾經遇到過人臉圖片資料集,並使用PCA(主成分分析)對其進行降維分析。這次,我們將繼續探索如何使用PCA和Isomap(等距對映)對這些高維度資料進行降維,以便更好地理解圖片之間的關係。

首先,讓我們觀察一下原始的人臉圖片資料集。每張圖片都被表示為一個高維度向量,因此直接視覺化所有圖片之間的關係是一個挑戰。

import matplotlib.pyplot as plt
import numpy as np
from sklearn.decomposition import PCA
from sklearn.manifold import Isomap
from matplotlib import offsetbox

# 載入人臉圖片資料集
faces =...  # 載入資料集的程式碼

# 顯示前幾張人臉圖片
for i in range(10):
    plt.subplot(2, 5, i+1)
    plt.imshow(faces.images[i], cmap='gray')
    plt.axis('off')
plt.show()

接下來,我們使用PCA對人臉圖片資料集進行降維分析。PCA是一種線性降維技術,它可以幫助我們瞭解資料的內在結構。

# 建立PCA模型
pca_model = PCA(n_components=100, svd_solver='randomized')

# 對人臉圖片資料集進行降維
pca_data = pca_model.fit_transform(faces.data)

# 繪製累積變異數比率
plt.plot(np.cumsum(pca_model.explained_variance_ratio_))
plt.xlabel('n components')
plt.ylabel('cumulative variance')
plt.show()

從累積變異數比率圖中,我們可以看到,大約需要100個主成分才能保留90%的變異數。這表明資料具有很高的內在維度,難以用少量線性特徵描述。

為了更好地理解資料的非線性結構,我們可以使用Isomap對人臉圖片資料集進行降維。Isomap是一種非線性降維技術,它可以幫助我們發現資料中的非線性關係。

# 建立Isomap模型
isomap_model = Isomap(n_components=2)

# 對人臉圖片資料集進行降維
isomap_data = isomap_model.fit_transform(faces.data)

# 繪製降維後的資料
plt.scatter(isomap_data[:, 0], isomap_data[:, 1])
plt.show()

最後,我們可以定義一個函式,用於在降維後的空間中繪製原始圖片的縮圖。這可以幫助我們更好地理解降維後的資料結構。

def plot_components(data, model, images=None, ax=None, thumb_frac=0.05, cmap='gray'):
    ax = ax or plt.gca()
    proj = model.fit_transform(data)
    ax.plot(proj[:, 0], proj[:, 1], '.k')
    if images is not None:
        min_dist_2 = (thumb_frac * max(proj.max(0) - proj.min(0))) ** 2
        shown_images = np.array([2 * proj.max(0)])
        for i in range(data.shape[0]):
            dist = np.sum((proj[i] - shown_images) ** 2, 1)
            if np.min(dist) < min_dist_2:
                # 繪製縮圖
                imagebox = offsetbox.AnnotationBbox(offsetbox.Offsetimage(images[i], cmap=cmap), proj[i])
                ax.add_artist(imagebox)
    return ax

# 繪製降維後的資料和原始圖片的縮圖
plot_components(faces.data, isomap_model, images=faces.images)
plt.show()

透過這些步驟,我們可以更好地理解人臉圖片資料集的內在結構和非線性關係。

使用Isomap進行資料視覺化

在上一節中,我們使用了PCA和t-SNE對資料進行降維和視覺化。這次,我們將使用Isomap(Isometric Mapping)對LFW資料集進行視覺化。

Isomap原理

Isomap是一種非線性降維演算法,旨在保留資料的區域性結構和全域性結構。它透過計算資料點之間的幾何距離,然後使用這些距離來構建一個低維度的嵌入空間。

實作Isomap

我們可以使用scikit-learn函式庫中的Isomap類別來實作Isomap演算法。以下是實作Isomap的程式碼:

from sklearn.manifold import Isomap
import numpy as np
import matplotlib.pyplot as plt

# 載入LFW資料集
from sklearn.datasets import fetch_lfw_people
lfw_people = fetch_lfw_people()

# 對資料進行預處理
lfw_data = lfw_people.data

# 建立Isomap物件
isomap = Isomap(n_components=2)

# 對資料進行降維
lfw_isomap = isomap.fit_transform(lfw_data)

# 對結果進行視覺化
plt.figure(figsize=(10, 10))
plt.scatter(lfw_isomap[:, 0], lfw_isomap[:, 1])
plt.show()

結果分析

結果顯示,Isomap對LFW資料集進行降維和視覺化的效果很好。從圖中可以看出,資料點在低維度空間中呈現出明顯的聚類別結構。

MNIST資料集視覺化

接下來,我們將使用Isomap對MNIST資料集進行視覺化。MNIST資料集是一個手寫字型資料集,包含70,000個28x28的影像。

from sklearn.datasets import fetch_openml
mnist = fetch_openml('mnist_784')

# 對資料進行預處理
mnist_data = np.asarray(mnist.data)

# 建立Isomap物件
isomap = Isomap(n_components=2)

# 對資料進行降維
mnist_isomap = isomap.fit_transform(mnist_data[::30])

# 對結果進行視覺化
plt.figure(figsize=(10, 10))
plt.scatter(mnist_isomap[:, 0], mnist_isomap[:, 1])
plt.show()

結果分析

結果顯示,Isomap對MNIST資料集進行降維和視覺化的效果也很好。從圖中可以看出,資料點在低維度空間中呈現出明顯的聚類別結構。

圖表翻譯:

此圖示為使用Isomap對MNIST資料集進行降維和視覺化的結果。圖中,每個點代表一個手寫字型影像,在低維度空間中呈現出明顯的聚類別結構。這表明,Isomap演算法能夠有效地保留資料的區域性結構和全域性結構。

內容解密:

以上程式碼實作了使用Isomap對LFW和MNIST資料集進行降維和視覺化。Isomap演算法透過計算資料點之間的幾何距離,然後使用這些距離來構建一個低維度的嵌入空間。結果顯示,Isomap對兩個資料集進行降維和視覺化的效果都很好,能夠有效地保留資料的區域性結構和全域性結構。

使用Isomap進行資料降維

在上一節中,我們使用Isomap(Isometric Mapping)進行資料降維。Isomap是一種非線性降維演算法,能夠有效地保留資料的區域性結構和全域性結構。下面是使用Isomap進行資料降維的例子:

from sklearn.manifold import Isomap
import matplotlib.pyplot as plt

# 載入MNIST資料集
from sklearn.datasets import fetch_mldata
mnist = fetch_mldata('MNIST original')

# 選擇一部分資料進行降維
target = mnist.target[::30]
data = mnist.data[::30]

# 建立Isomap模型
model = Isomap(n_components=2)

# 對資料進行降維
proj = model.fit_transform(data)

# 繪製降維後的資料
plt.scatter(proj[:, 0], proj[:, 1], c=target, cmap=plt.cm.get_cmap('jet', 10))
plt.clim(-0.5, 9.5)
plt.show()

這個例子中,我們使用Isomap將MNIST資料集中的資料降維到二維空間。然後,我們使用matplotlib繪製降維後的資料。由於Isomap是一種非線性降維演算法,能夠有效地保留資料的區域性結構和全域性結構,因此降維後的資料能夠很好地反映原始資料的結構。

使用k-means進行聚類別

在這一節中,我們將介紹k-means聚類別演算法。k-means是一種常用的聚類別演算法,能夠將資料分成k個聚類別。下面是使用k-means進行聚類別的例子:

from sklearn.cluster import KMeans
import numpy as np
import matplotlib.pyplot as plt

# 建立一些隨機資料
np.random.seed(0)
data = np.random.rand(100, 2)

# 建立k-means模型
model = KMeans(n_clusters=5)

# 對資料進行聚類別
model.fit(data)

# 繪製聚類別結果
plt.scatter(data[:, 0], data[:, 1], c=model.labels_)
plt.show()

這個例子中,我們使用k-means將一些隨機資料分成5個聚類別。然後,我們使用matplotlib繪製聚類別結果。由於k-means是一種常用的聚類別演算法,因此能夠有效地將資料分成不同的聚類別。

圖表翻譯:

上述程式碼中,我們使用Isomap和k-means兩種不同的演算法對資料進行降維和聚類別。Isomap是一種非線性降維演算法,能夠有效地保留資料的區域性結構和全域性結構。而k-means是一種常用的聚類別演算法,能夠將資料分成k個聚類別。這兩種演算法都能夠有效地幫助我們瞭解資料的結構和特點。

內容解密:

上述程式碼中,我們使用了兩種不同的演算法:Isomap和k-means。Isomap是一種非線性降維演算法,能夠有效地保留資料的區域性結構和全域性結構。k-means是一種常用的聚類別演算法,能夠將資料分成k個聚類別。這兩種演算法都能夠有效地幫助我們瞭解資料的結構和特點。透過使用這兩種演算法,我們可以更好地理解資料的內在結構和特點,並且可以更好地進行資料分析和挖掘。

瞭解 K-Means 演算法

K-Means 演算法是一種常用的無監督學習演算法,主要用於資料分群。其基本假設是每個資料點都更接近自己的群集中心,而不是其他群集中心。這些假設是 K-Means 模型的基礎。

資料生成與視覺化

首先,讓我們生成一個二維的資料集,包含四個不同的群集。為了強調這是一種無監督學習演算法,我們不會在視覺化中顯示標籤。

from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
import numpy as np

X, y_true = make_blobs(n_samples=300, centers=4, cluster_std=0.60, random_state=0)
plt.scatter(X[:, 0], X[:, 1], s=50)
plt.show()

K-Means 演算法應用

接下來,我們使用 Scikit-Learn 中的 KMeans 類別來進行分群。這裡我們設定 n_clusters 引數為 4,表示我們想要分出四個群集。

from sklearn.cluster import KMeans

kmeans = KMeans(n_clusters=4)
kmeans.fit(X)
y_kmeans = kmeans.predict(X)

plt.scatter(X[:, 0], X[:, 1], c=y_kmeans, s=50, cmap='viridis')
centers = kmeans.cluster_centers_
plt.scatter(centers[:, 0], centers[:, 1], c='black', s=200)
plt.show()

Expectation-Maximization 演算法

K-Means 演算法使用了一種叫做 Expectation-Maximization (E-M) 的方法來找到群集。這個方法包括兩個步驟:Expectation 步驟(E 步驟)和 Maximization 步驟(M 步驟)。

  1. 初始化:隨機選擇一些群集中心。
  2. 重複直到收斂
    • E 步驟:將每個資料點指派給最近的群集中心。
    • M 步驟:更新群集中心為其指派資料點的平均值。

K-Means 演算法實作

以下是 K-Means 演算法的一個基本實作:

from sklearn.metrics import pairwise_distances_argmin
import numpy as np

def find_clusters(X, n_clusters, rseed=2):
    # 1. 隨機選擇群集中心
    rng = np.random.RandomState(rseed)
    i = rng.permutation(X.shape[0])[:n_clusters]
    centers = X[i]

    while True:
        # E 步驟:將每個資料點指派給最近的群集中心
        labels = pairwise_distances_argmin(X, centers)

        # M 步驟:更新群集中心
        new_centers = np.array([X[labels == i].mean(axis=0) for i in range(n_clusters)])

        # 檢查是否收斂
        if np.all(centers == new_centers):
            break

        centers = new_centers

    return centers, labels

# 測試
centers, labels = find_clusters(X, 4)
plt.scatter(X[:, 0], X[:, 1], c=labels, s=50, cmap='viridis')
plt.scatter(centers[:, 0], centers[:, 1], c='black', s=200)
plt.show()

這個實作展示了 K-Means 演算法的基本步驟,包括初始化、E 步驟和 M 步驟。它可以有效地將資料分成不同的群集,並且對於理解 Expectation-Maximization 演算法有著重要的參考價值。

K-Means 演算法深度剖析

K-Means 是一種廣泛使用的無監督學習演算法,主要用於資料分群(Clustering)。其基本思想是將資料點分配到最接近的中心點(Centroid),並根據這些中心點更新分群結果。然而,K-Means 也有一些限制和挑戰,包括難以確保全域最佳解、需要事先指定分群數量以及對非線性邊界的限制。

K-Means 演算法步驟

  1. 初始化中心點:隨機選擇初始中心點。
  2. 分配標籤:根據每個資料點與中心點的距離,將其分配到最接近的中心點。
  3. 更新中心點:計算每個分群中所有資料點的平均值,作為新的中心點。
  4. 檢查收斂:如果新的中心點與舊的中心點相同,則演算法收斂,否則回到步驟2。

K-Means 的挑戰

  • 全域最佳解:K-Means 不保證能找到全域最佳解,因為初始中心點的選擇可能導致演算法收斂到區域性最佳解。為了避免這個問題,通常會多次執行演算法,以不同的隨機初始中心點開始。
  • 分群數量:K-Means 需要事先指定分群數量(K)。如果事先不知道最佳的分群數量,可以使用如輪廓分析(Silhouette Analysis)等方法來評估不同分群數量下的結果。
  • 線性邊界:K-Means 假設分群之間的邊界是線性的,這對於具有複雜幾何結構的資料集可能不適用。這種情況下,可以考慮使用其他能夠處理非線性邊界的演算法,如高斯混合模型(Gaussian Mixture Models)或 DBSCAN 等。

實際應用

在實際應用中,K-Means 可以用於客戶分段、市場研究、影像分割等領域。然而,需要根據具體問題選擇合適的分群數量,並可能需要結合其他技術來處理複雜的邊界情況。

程式碼實作

import numpy as np
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt

# 生成隨機資料
np.random.seed(0)
X = np.random.rand(100, 2)

# 定義KMeans模型
kmeans = KMeans(n_clusters=4, random_state=0)

# 執行KMeans
labels = kmeans.fit_predict(X)

# 繪製結果
plt.scatter(X[:, 0], X[:, 1], c=labels, s=50, cmap='viridis')
plt.show()

圖表翻譯

KMeans 分群結果圖

此圖展示了使用 KMeans 演算法對隨機生成的 2D 資料進行分群的結果。不同顏色代表了不同的分群。從圖中可以看到,KMeans 能夠有效地將資料點分配到不同的分群中,但其效果取決於初始中心點的選擇和分群數量的設定。

內容解密

上述程式碼展示瞭如何使用 Scikit-Learn 中的 KMeans 類別來進行分群。首先,生成了一些隨機 2D 資料點。然後,定義了一個 KMeans 模型,指定了分群數量 (n_clusters=4) 和隨機種子 (random_state=0) 以確保結果可重複。接著,使用 fit_predict 方法執行 KMeans 演算法,得到每個資料點的標籤。最後,使用 Matplotlib 繪製了分群結果,資料點的顏色根據其所屬的分群而定。這個過程展示瞭如何使用 KMeans 進行簡單的分群分析。

使用 K-Means 演算法進行資料分群

K-Means 演算法是一種常用的無監督學習演算法,適用於資料分群。然而,在處理非線性邊界的資料時,K-Means 演算法可能會失敗。為瞭解決這個問題,我們可以使用核化 K-Means 演算法。

核化 K-Means 演算法

核化 K-Means 演算法是透過將資料投影到高維空間中,然後使用 K-Means 演算法進行分群。這種方法可以有效地處理非線性邊界的資料。Scikit-Learn 中的 SpectralClustering 估計器實作了一種核化 K-Means 演算法,使用最近鄰圖來計算高維空間中的資料表示,然後使用 K-Means 演算法進行分群。

from sklearn.cluster import SpectralClustering
import numpy as np
import matplotlib.pyplot as plt

# 載入資料
from sklearn.datasets import make_moons
X, y = make_moons(200, noise=.05, random_state=0)

# 使用 SpectralClustering 估計器進行分群
model = SpectralClustering(n_clusters=2, affinity='nearest_neighbors', assign_labels='kmeans')
labels = model.fit_predict(X)

# 繪製結果
plt.scatter(X[:, 0], X[:, 1], c=labels, s=50, cmap='viridis')
plt.show()

K-Means 演算法的限制

K-Means 演算法有一個限制,即每次迭代都需要存取整個資料集,這使得演算法在處理大型資料集時可能會很慢。為瞭解決這個問題,可以使用批次 K-Means 演算法,例如 Scikit-Learn 中的 MiniBatchKMeans 估計器。

K-Means 演算法的應用

儘管 K-Means 演算法有其限制,但它仍然可以在很多情況下發揮作用。以下是兩個例子:

例子 1:K-Means 演算法在數字資料上的應用

我們可以使用 K-Means 演算法對數字資料進行分群。數字資料集包含 1,797 個樣本,每個樣本有 64 個特徵,代表 8x8 影像中每個畫素的亮度。

from sklearn.datasets import load_digits
digits = load_digits()
print(digits.data.shape)

from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=10, random_state=0)
clusters = kmeans.fit_predict(digits.data)
print(kmeans.cluster_centers_.shape)

例子 2:視覺化分群結果

我們可以視覺化分群結果,以瞭解每個分群的特徵。

import matplotlib.pyplot as plt

fig, ax = plt.subplots(2, 5, figsize=(8, 3))
centers = kmeans.cluster_centers_.reshape(10, 8, 8)

for axi, center in zip(ax.flat, centers):
    axi.imshow(center, cmap='gray')
    axi.set_title('Cluster %d' % (axi.get_title() + 1))
plt.show()

這些例子展示了 K-Means 演算法在不同情況下的應用和限制。

從技術架構視角來看,流形學習方法提供了一種根據資料內在結構的非線性降維方法,相較於線性降維的PCA,它能更好地捕捉高維資料中的非線性關係,並在諸如人臉識別、手寫數字識別等領域展現出其獨特的優勢。然而,流形學習方法也存在一些挑戰,例如引數敏感性、計算複雜度高以及對噪聲資料的敏感性等。尤其在高維資料場景下,如何有效地選擇鄰居數量、確定輸出維度以及解釋嵌入維度的含義,仍是技術上的難點。綜合評估後,玄貓認為,流形學習方法在處理非線性結構資料時具有潛力,但仍需針對其侷限性進行改進,並結合實際應用場景進行調優,才能更好地發揮其作用。未來,隨著演算法的最佳化和計算能力的提升,預計流形學習方法將在更多領域得到更廣泛的應用,並與深度學習等技術融合,推動資料分析和機器學習的進一步發展。