首頁>技術>

譯者:朱先忠

自組織映射的演變迭代gif動畫示意圖

1. 簡介

自組織映射(SOM)是由芬蘭赫爾辛基理工大學的Teuvo Kohonen在20世紀80年代提出的一種無監督機器學習算法。顧名思義,映射是在沒有他人指示的情況下自行組織的。這是一個受大腦神經網絡活動啟發而發明的模型。大腦皮層的另一個區域負責特定的活動。視覺、聽覺、嗅覺和味覺等感覺輸入通過突觸以自組織方式映射到相應皮層區域的神經元。眾所周知,輸出相似的神經元是鄰近的。SOM通過競爭性神經網絡進行訓練,這是一種類似於這些大腦機制的單層前饋神經網絡。

SOM算法相對簡單,但乍一看可能會有一些混亂,並且難以確定如何在實踐中應用它。這可能是因為SOM可以從多個角度理解的緣故吧。它類似於用於降維和可視化的主成分分析(PCA:一種通過正交變換將一組可能存在相關性的變量轉換為一組線性不相關的變量的統計方法)。自組織映射也可以被視為一種處理非線性降維的流形學習。SOM還因其矢量量化特性而應用於數據挖掘領域。該序列可以將高維可觀察數據表示到低維潛在空間,通常在二維正方形網格上,同時保留原始輸入空間的拓撲結構。但映射也可以用於投影新的數據點,並查看哪個簇屬於映射。

本文將努力解釋自組織映射的基本架構及其算法,並重點介紹其自組織方面。我們將使用基於Python的UCI機器學習庫中可用的數據集來開發一個SOM模型以解決聚類問題。然後,我們將看到映射在在線(連續)培訓期間是如何自組織的。最後,我們還會評估經過訓練的自組織映射,並討論其優點和侷限性。儘管SOM不是當下最流行的ML技術,在學術文獻之外也不太常見;然而,並沒有結論說,SOM不是解決所有問題的有效工具。訓練模型相對容易,訓練模型的可視化有助於向非技術類人員,例如審計師們,作出更直觀有效的解釋。我們將看到,該算法面臨的問題通常也完全可以在其他無監督方法領域中共享。

2. 架構和學習算法設計

自組織映射的神經網絡有一個輸入層和一個輸出層。第二層通常由m x n個神經元的二維網格組成。映射層的每個神經元與輸入層的所有神經元緊密連接,具有不同的權重值。

在競爭學習中,輸出層的神經元相互競爭以便被激活。比賽中獲勝的神經元是唯一可以激發的神經元;因此,它被稱為“贏家通吃”神經元。在自組織映射中,競爭過程是搜索與輸入模式最相似的神經元;獲勝者被稱為最佳匹配單元(BMU)。

作為獲勝標準的相似性可以通過幾種方式衡量。最常用的度量指標是歐幾里德距離;距離輸入信號最短的神經元成為BMU。

在SOM中,學習不僅適用於獲勝者,也適用於基於映射的物理上接近它的神經元。BMU享有與其鄰近神經元共同學習的特權。鄰域的定義由網絡設計者確定,最佳接近度取決於其他超參數。如果鄰域範圍太小,經過訓練的模型將遭受過度擬合,並且存在一些死亡神經元的風險,這些神經元永遠沒有機會改變。

在適應階段,BMU及其鄰近神經元調整其權重。學習的效果是使獲勝神經元和相鄰神經元的權重更接近輸入模式。例如,如果輸入信號為藍色,BMU神經元為淺藍色,則獲勝者的藍色略高於淺藍色。如果鄰居是黃色的,則會在當前顏色中添加一點藍色。

概括地講,自組織映射學習算法(在線學習)可以通過以下4個步驟來描述:

初始化

初始化映射層中神經元的權重。

競爭過程

選擇一個輸入樣本,並使用距離度量指標在n x m網格中的所有神經元中搜索最佳匹配單元。

合作過程

通過鄰域函數尋找BMU的鄰近神經元。

適應過程

通過將數值向輸入模式遷移來更新BMU和鄰居的權重。

如果達到最大訓練迭代次數,則退出;如果還沒有,則將迭代計數增加1,並從2開始重複上述過程。

3. 實戰演練

在本文中,我們開發的SOM將使用UCI ML存儲網站上可用的銀行票據認證數據集進行訓練。該數據文件共包含1372行,每行有4個特徵和1個標籤。其中,所有4個特徵都是不帶null的數值;標籤是二進制整數值。

首先,我們將數據隨機分為訓練數據和測試數據。我們使用所有4個特徵和在線訓練算法來訓練自組織映射。然後,我們通過使用訓練數據的標籤可視化映射來評估經過訓練的自組織映射。最後,我們可以基於訓練後的映射並使用測試數據來預測標籤。

通過這樣的實戰性演練,我們就可以證明:以無監督方式訓練的自組織映射可以用於使用標記數據集的分類。

(1)導入庫

複製
import numpy as npfrom numpy.ma.core import ceilfrom scipy.spatial import distance #距離計算from sklearn.preprocessing import MinMaxScaler #標準化from sklearn.model_selection import train_test_splitfrom sklearn.metrics import accuracy_score #評分from sklearn.metrics import confusion_matriximport matplotlib.pyplot as pltfrom matplotlib import animation, colors1.2.3.4.5.6.7.8.9.

(2)導入數據集(dataset)

複製
#鈔票認證數據集# https://archive.ics.uci.edu/ml/datasets/banknote+authentication# Dua, D. and Graff, C. (2019). UCI機器學習庫 [http://archive.ics.uci.edu/ml]. # 加州歐文:加利福尼亞大學信息與計算機科學學院。data_file = "data_banknote_authentication.txt"data_x = np.loadtxt(data_file, delimiter=",", skiprows=0, usecols=range(0,4) ,dtype=np.float64)data_y = np.loadtxt(data_file, delimiter=",", skiprows=0, usecols=(4,),dtype=np.int64)1.2.3.4.5.6.7.8.

注意,這裡的CSV文件需要從網站下載並存儲在本地目錄中。我們將使用文件中的前4列表示x,最後一列表示y。

(3)訓練和測試數據分割

複製
# 訓練和測試數據分割train_x, test_x, train_y, test_y = train_test_split(data_x, data_y, test_size=0.2, random_state=42)print(train_x.shape, train_y.shape, test_x.shape, test_y.shape) #形狀檢查1.2.3.

數據按0.8:0.2進行分割,以方便進行訓練和測試。因此,我們會看到,分別有1097個和275個觀測值。

(4)編寫幫助函數

複製
# 幫助函數# 數據歸一化def minmax_scaler(data):  scaler = MinMaxScaler()  scaled = scaler.fit_transform(data)  return scaled# 歐幾里德距離def e_distance(x,y):  return distance.euclidean(x,y)#曼哈頓距離def m_distance(x,y):  return distance.cityblock(x,y)# 最佳匹配單元搜索def winning_neuron(data, t, som, num_rows, num_cols):  winner = [0,0]  shortest_distance = np.sqrt(data.shape[1]) #用最大距離初始化  input_data = data[t]  for row in range(num_rows):    for col in range(num_cols):      distance = e_distance(som[row][col], data[t])      if distance < shortest_distance:         shortest_distance = distance        winner = [row,col]  return winner# 學習率和鄰域範圍計算def decay(step, max_steps,max_learning_rate,max_m_dsitance):  coefficient = 1.0 - (np.float64(step)/max_steps)  learning_rate = coefficient*max_learning_rate  neighbourhood_range = ceil(coefficient * max_m_dsitance)  return learning_rate, neighbourhood_range1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.

上述代碼中,minmax_scaler用於在0和1之間歸一化輸入數據。由於算法計算距離,我們應該將每個特徵的值縮放到相同的範圍,以避免其中任何一個特徵對距離計算的影響比其他特徵更大。

e_distance變量用於計算兩點之間的歐幾里德距離。變量m_distance用於獲得網格上兩點之間的曼哈頓距離。在我們的示例中,歐幾里德距離用於搜索獲勝神經元,而曼哈頓距離用於限制鄰域範圍。它通過應用矩形鄰域函數簡化了計算,其中位於距離BMU拓撲位置一定曼哈頓距離內的神經元在同一級別被激活。

winning_neuron在BMU中搜索樣本數據t。計算輸入信號與映射層中每個神經元之間的距離,並返回距離最短的神經元網格的行和列索引。

使用當前訓練步驟、最大訓練步驟數和最大鄰域範圍和學習速率並應用線性衰減算法,decay函數返回學習速率和鄰域範圍兩個值。

圖3-4-1鄰域範圍衰減情形(步長對鄰域範圍指標)

圖3-4-2鄰域範圍衰減(步長對學習速率指標)

(5)設置超參數

複製
# 超參數num_rows = 10num_cols = 10max_m_dsitance = 4max_learning_rate = 0.5max_steps = int(7.5*10e3)# num_nurons = 5*np.sqrt(train_x.shape[0])# grid_size = ceil(np.sqrt(num_nurons))# print(grid_size)1.2.3.4.5.6.7.8.9.10.

超參數是指那些在訓練算法之前就需要選擇的不可訓練參數。它們分別是神經元的數量、SOM網格的維數、訓練步驟的數量、學習速率和BMU的鄰域範圍。

在本例中,我們為網格設置了較小的數字(10×10),但使用了啟發式方法來實現超參數選擇。我們可以使用[5*sqrt(訓練樣本數)]公式來選擇神經元的數量。我們有1097個訓練樣本,因此可以在網格上創建5*sqrt(1097)=165.60個神經元。因為我們有一個二維正方形網格,所以數字的平方根表示每個維度可以有多少個神經元。sqrt的上限(165.40)=13,所以映射的尺寸是13*13。

訓練步驟的數量可能需要至少(500×n行×m列)才能收斂。我們可以將步數設置為500*13*13=84500。可以將學習速率和鄰域範圍設置為較大的數值,並逐漸減小。建議使用不同的超參數集進行實驗以進行改進。

最大鄰域範圍和學習率的初始值可以設置為較大的數字。如果速率太小,可能會導致擬合過度,因此需要更多的學習訓練步驟。

(6)開始訓練

複製
#主函數train_x_norm = minmax_scaler(train_x) # 歸一化# 初始wx.qq.com自組織映射num_dims = train_x_norm.shape[1] # 輸入數據的維數np.random.seed(40)som = np.random.random_sample(size=(num_rows, num_cols, num_dims)) # 構建映射#開始訓練迭代for step in range(max_steps):  if (step+1) % 1000 == 0:    print("Iteration: ", step+1) # 每1k次打印出當前迭代值  learning_rate, neighbourhood_range = decay(step, max_steps,max_learning_rate,max_m_dsitance)  t = np.random.randint(0,high=train_x_norm.shape[0]) # 訓練數據的隨機索引  winner = winning_neuron(train_x_norm, t, som, num_rows, num_cols)  for row in range(num_rows):    for col in range(num_cols):      if m_distance([row,col],winner) <= neighbourhood_range:        som[row][col] += learning_rate*(train_x_norm[t]-som[row][col]) #更新鄰接點的權重print("SOM training completed")1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.

在應用輸入數據歸一化後,我們使用網格上每個神經元的0到1之間的隨機值初始化映射。然後使用衰減函數decay計算學習速率和鄰近範圍。從訓練數據中隨機選擇樣本輸入觀察值,並搜索最佳匹配單元。最後,基於曼哈頓距離準則,選擇包括獲勝者在內的鄰接點神經元進行學習,並調整權重。

(7)顯示訓練後的SOM中的標籤信息

在上一步中,我們完成了訓練。因為這是無監督學習,我們的問題中存在標籤數據;所以,我們現在可以將標籤投影到映射上。這一步驟是通過兩步來實現的。首先,收集每個神經元的標籤。其次,將單個標籤投影到每個神經元以構建標籤映射。

複製
#收集標籤label_data = train_ymap = np.empty(shape=(num_rows, num_cols), dtype=object)for row in range(num_rows):  for col in range(num_cols):    map[row][col] = [] # 置空存儲標籤的列表for t in range(train_x_norm.shape[0]):  if (t+1) % 1000 == 0:    print("sample data: ", t+1)  winner = winning_neuron(train_x_norm, t, som, num_rows, num_cols)  map[winner[0]][winner[1]].append(label_data[t]) # 獲勝神經元的標籤1.2.3.4.5.6.7.8.9.10.11.12.13.14.

上述代碼中,我們創建了與SOM相同的網格。對於每個訓練數據,我們搜索獲勝的神經元,並將觀察標籤添加到每個BMU的列表中。

複製
# 構建標籤映射label_map = np.zeros(shape=(num_rows, num_cols),dtype=np.int64)for row in range(num_rows):  for col in range(num_cols):    label_list = map[row][col]    if len(label_list)==0:      label = 2    else:      label = max(label_list, key=label_list.count)    label_map[row][col] = labeltitle = ("Iteration " + str(max_steps))cmap = colors.ListedColormap(["tab:green", "tab:red", "tab:orange"])plt.imshow(label_map, cmap=cmap)plt.colorbar()plt.title(title)plt.show()1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.

為了構造一個標籤映射,我們通過多數投票將單個標籤分配給映射上的每個神經元。對於未選擇BMU的神經元,我們將類別值2指定為無法識別。圖3-7-1和3-7-2分別顯示了為第一次迭代和最終迭代創建的標籤映射。在開始時,許多神經元既不是0也不是1,分類標籤似乎是隨機分散的;而最終的迭代清楚地顯示了類別0和1之間的區域分離,儘管我們在最終迭代中看到了兩個不屬於任何一個類別的單元。

Figure 3–7–1 第一次迭代創建的標籤映射

Figure 3–7–2 最終迭代創建的標籤映射

注意:如開始的圖形一樣,原文這裡的圖3-7-3是一個動畫gif,顯示了SOM從第一步到最大75000步的演變,方便我們清楚地看到映射的結構。

Figure 3–7–3 SOM訓練動畫

(8)預測測試集標籤

複製
#測試數據集# 利用訓練好的自組織映射,搜索測試數據對應的獲勝節點,得到獲勝節點的標籤data = minmax_scaler(test_x) # normalisationwinner_labels = []for t in range(data.shape[0]): winner = winning_neuron(data, t, som, num_rows, num_cols) row = winner[0] col = winner[1] predicted = label_map[row][col] winner_labels.append(predicted)print("Accuracy: ",accuracy_score(test_y, np.array(winner_labels)))1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.

最後,我們可以使用訓練後的映射對測試數據進行二元分類。我們將測試x數據歸一化,並搜索每個觀察t的MBU,返回與神經元相關的標籤。運行結果說明,本訓練返回了非常精確的結果,即我們的示例獲得了一個非常好的數字,如圖3-8所示。

Figure 3–8 預測結果非常理想,精確度為1.0

4. 評估

在上面的示例項目中,我們演示瞭如何為分類問題實現無監督自組織映射。我們使用沒有標籤的數據集對映射進行了訓練,並通過在映射上投影標籤來確認訓練結果。正如預期的那樣,我們可以觀察到每個類別都有清晰的區域,其中神經元具有相似的屬性,彼此距離較近。最後,我們用一個不可預見的測試數據集測試了映射,並測量了預測精度。

值得提醒的是,我們用於上述示例的數據僅是一個小而乾淨的數據集,具有有限的觀察值和特徵。在現實生活中,數據科學家面臨的問題在維度上要高得多,標記的數據集並不完全可用。即使它們可用,其質量也可能不那麼完全可靠。例如,在檢測銀行的惡意交易時,不要期望根據陽性案例檢查所有交易,這可能是明智的態度;在真實數據集中,可能只有少數陽性案例被標記。

在將自組織映射應用於真實場景時,我們將面臨一些挑戰。首先,如果我們沒有標記的數據集,我們就無法測量損失。我們無法驗證經過訓練的映射的可靠性。映射的質量在很大程度上取決於數據本身的特徵。歸一化數據預處理對於基於距離的算法至關重要。數據集的先驗分析對於理解數據點的分佈也很重要。特別是對於無法可視化的高維數據,我們可以使用其他降維技術,如主成分分析和奇異值分解(SVD)技術等。

此外,如果拓撲映射的形狀與潛在空間中數據點的分佈無關,則訓練可能不會成功。雖然我們在示例中使用了正方形網格,但我們必須仔細設計映射的形狀。推薦的方法之一是使用主成分分析前兩個主成分的解釋方差的比率。然而,如果時間允許,值得嘗試不同的超參數進行精細調整。

就算法的計算成本而言,訓練時間複雜度取決於迭代次數、特徵數和神經元數。SOM最初是為順序學習而設計的,但在某些情況下,批量學習方法是首選的。隨著大數據的數據量增加,可能有必要研究更有效的學習算法。在我們的示例中,我們使用了稱為氣泡的矩形鄰域函數進行簡化。對於訓練迭代,我們可以監控自組織映射的形成,並檢查在循環過程中如何學習映射。訓練步驟數量的減少直接影響計算的數量。

最後需要說明的是,本文中沒有介紹批量學習算法有關內容。其實,如果實際問題有關的數據集合比較有限時,則使用批量處理算法是一個不錯的選擇。事實上,Kohonen指出,批處理算法是有效的,可推薦用於實際應用。

3
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 汙水處理除磷技術未來的發展——極限除磷