假設你正在分析基因表達資料,希望不僅找出基因群體,還想了解這些群體之間的階層關係,以便更深入地理解基因功能的組織結構。
解決方案:凝聚式階層叢集
凝聚式階層叢集(Agglomerative Clustering)是一種自下而上的方法,能夠構建叢集的層次結構:
# 載入必要函式庫from sklearn import datasets
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import AgglomerativeClustering
# 載入資料
iris = datasets.load_iris()
features = iris.data
# 標準化特徵
scaler = StandardScaler()
features_std = scaler.fit_transform(features)
# 建立凝聚式叢集物件
cluster = AgglomerativeClustering(n_clusters=3, linkage='ward')
# 訓練模型
model = cluster.fit(features_std)
# 檢視叢整合員
print(model.labels_)
這段程式碼實作了凝聚式階層叢集:
- 建立AgglomerativeClustering物件,指定叢集數量為3,連結策略為’ward’(最小化合併叢集的方差)
- 使用標準化後的鳶尾花資料訓練模型
- 輸出每個觀測值所屬的叢集標籤
階層式叢集的原理與應用策略
凝聚式叢集是一種強大、靈活的階層式叢集演算法。其運作方式是:
- 初始時,每個觀測值被視為自己的叢集
- 根據某種準則,合併最相似的兩個叢集
- 重複步驟2,直到達到某個終止條件(如達到指定的叢集數量)
在scikit-learn的AgglomerativeClustering中,連結引數linkage
決定了叢集合併的策略,主要有三種選擇:
- ward:最小化合併叢集的方差(預設選項,通常效果最好)
- average:最小化叢集間觀測值的平均距離
- complete:最小化叢集間觀測值的最大距離
另外兩個重要引數是:
- affinity:決定計算距離的度量方式(如歐幾裡德、曼哈頓等)
- n_clusters:設定演算法嘗試找到的叢集數量
階層式叢集的主要優勢在於它能提供資料的層次結構檢視,這在許多應用中非常有價值。例如,在基因表達分析中,它可以幫助研究人員理解基因之間的層次關係;在市場細分中,它可以揭示客戶群體之間的結構性關係。
階層式叢集還可以透過樹狀圖(dendrogram)直觀地表示,幫助我們確定適當的叢集數量。雖然scikit-learn的AgglomerativeClustering不直接支援樹狀圖,但我們可以使用SciPy的階層叢集功能來生成:
import matplotlib.pyplot as plt
from scipy.cluster.hierarchy import dendrogram, linkage
# 使用SciPy計算階層叢集
Z = linkage(features_std, method='ward')
# 繪製樹狀圖
plt.figure(figsize=(12, 6))
dendrogram(Z)
plt.title('階
## 神經網路的基礎架構與運作機制
神經網路已成為現代機器學習的核心技術,特別是在處理複雜模式識別問題時展現出驚人的效能。經過多年的實踐,我發現理解神經網路的基本架構是掌握這項技術的關鍵起點。
### 前饋神經網路的三層結構
前饋神經網路(Feedforward Neural Networks)包含三種基本層級:
1. **輸入層(Input Layer)**:位於神經網路的起始位置,每個單元包含一個觀測值的單一特徵。例如,若一個觀測值有100個特徵,則輸入層就有100個節點。
2. **隱藏層(Hidden Layers)**:位於輸入層與輸出層之間,雖名為「隱藏」,但實際上並不神秘。這些隱藏層逐步將輸入層的特徵值轉換成能夠被輸出層處理,並最終近似目標類別的表示形式。
3. **輸出層(Output Layer)**:位於神經網路的末端,將隱藏層的輸出轉換成適合當前任務的值。例如,若目標是二元分類別可以使用一個單元的輸出層,該單元使用sigmoid函式將輸出縮放至0到1之間,代表預測的類別機率。
當神經網路包含許多隱藏層(例如10、100或甚至1000層)時,我們稱之為「深度」網路,其應用則被稱為深度學習。
### 神經網路的學習過程
神經網路的學習過程是一個迭代最佳化過程,主要包含以下步驟:
1. **初始化**:神經網路通常以小的隨機值(來自高斯分佈或均勻分佈)初始化所有引數。
2. **前向傳播(Forward Propagation)**:當一個觀測值(或更常見的是一組稱為批次的觀測值)被輸入網路後,網路輸出的值會與觀測值的真實值使用損失函式進行比較。
3. **反向傳播(Backpropagation)**:演算法會「向後」遍歷網路,識別每個引數對預測值與真實值之間誤差的貢獻程度。
4. **引數調整**:在每個引數處,最佳化演算法會確定每個權重應該如何調整以改善輸出。
神經網路透過對訓練資料中的每個觀測值重複前向傳播和反向傳播的過程來學習,迭代更新引數值。每次所有觀測值都被送入網路一次稱為一個「週期」(epoch),訓練通常包含多個週期。
## Keras:神經網路實作的高階工具
在實作神經網路時,Keras是一個極為流行的Python函式庫eras是一個高階函式庫用其他函式庫ensorFlow和Theano作為其「引擎」。使用Keras的好處在於我們可以專注於網路設計與訓練,將張量操作的細節留給底層函式庫。
使用Keras程式建立的神經網路可以使用CPU(如筆電)和GPU(專用深度學習電腦)進行訓練。在實際應用中,強烈建議使用GPU訓練神經網路;然而,為了學習目的,本文中的神經網路都足夠小與簡單,可以在幾分鐘內在筆電上完成訓練。只需注意,當網路更大與訓練資料更多時,使用CPU的訓練速度會顯著慢於使用GPU。
## 神經網路的資料預處理
### 標準化特徵資料
在神經網路中,資料預處理是確保模型能夠有效學習的關鍵步驟。標準化(Standardization)是最常用的預處理方法之一,它確保所有特徵具有相同的尺度。
以下是使用scikit-learn的StandardScaler進行特徵標準化的範例:
```python
# 載入函式庫
from sklearn import preprocessing
import numpy as np
# 建立特徵
features = np.array([[-100.1, 3240.1],
[-200.2, -234.1],
[5000.5, 150.1],
[6000.6, -125.1],
[9000.9, -673.1]])
# 建立標準化器
scaler = preprocessing.StandardScaler()
# 轉換特徵
features_standardized = scaler.fit_transform(features)
# 顯示特徵
features_standardized
執行結果:
array([[-1.12541308, 1.96429418],
[-1.15329466, -0.50068741],
[ 0.29529406, -0.22809346],
[ 0.57385917, -0.42335076],
[ 1.40955451, -0.81216255]])
上面的程式碼示範瞭如何使用scikit-learn的StandardScaler對特徵資料進行標準化。首先建立一個包含5個樣本、每個樣本有2個特徵的資料集,然後例項化一個StandardScaler物件,使用其fit_transform方法對資料進行標準化處理。標準化後,每個特徵的均值為0,標準差為1。
可以透過檢查第一個特徵的均值和標準差來確認標準化的效果:
# 列印均值和標準差
print("Mean:", round(features_standardized[:,0].mean()))
print("Standard deviation:", features_standardized[:,0].std())
執行結果:
Mean: 0.0
Standard deviation: 1.0
為什麼標準化對神經網路如此重要?
在實踐中,我發現標準化對神經網路的效能有顯著影響,主要有以下原因:
引數初始化與特徵尺度:神經網路的引數通常初始化為小的隨機數值。當特徵值遠大於引數值時,網路往往表現不佳。
特徵組合問題:由於一個觀測值的特徵值在透過各個單元時會被組合,所以保持所有特徵在相同尺度上非常重要。
最佳化率:標準化後的特徵可以讓梯度下降等最佳化法更有效地工作,加速收斂過程。
因此,最佳實踐是將每個特徵標準化,使特徵值具有0均值和1標準差。這可以透過scikit-learn的StandardScaler輕鬆實作。不過,在某些情況下(例如當所有特徵都是二元特徵時),標準化可能並不是必要的。
設計神經網路
設計神經網路是一項需要同時考慮藝術與科學的任務。雖然存在一些常用的架構模式,但選擇正確的架構在很大程度上仍是一門藝術,也是許多研究的主題。
使用Keras建立神經網路
以下是使用Keras的Sequential模型設計神經網路的範例:
# 載入函式庫
from keras import models
from keras import layers
# 啟動神經網路
network = models.Sequential()
# 增加具有ReLU啟用函式的全連線層
network.add(layers.Dense(units=16, activation="relu", input_shape=(10,)))
# 增加具有ReLU啟用函式的全連線層
network.add(layers.Dense(units=16, activation="relu"))
# 增加具有sigmoid啟用函式的全連線層
network.add(layers.Dense(units=1, activation="sigmoid"))
# 編譯神經網路
network.compile(loss="binary_crossentropy", # 交叉熵
optimizer="rmsprop", # 均方根傳播
metrics=["accuracy"]) # 精確度效能指標
這段程式碼展示瞭如何使用Keras建立一個三層神經網路(不包括輸入層)。網路使用Sequential模型,這是一個線性堆積積的層級模型。
首先增加的是第一個隱藏層,它有16個單元,使用ReLU啟用函式,並指定輸入形狀為10(表示每個樣本有10個特徵)。接著增加第二個隱藏層,同樣有16個單元和ReLU啟用函式。最後增加輸出層,只有1個單元,使用sigmoid啟用函式,適合二元分類別務。
網路編譯時指定了損失函式(binary_crossentropy,適合二元分類別、最佳化(rmsprop)和評估指標(accuracy)。這樣完成了神經網路的設計與設定。
神經網路設計的關鍵決策
在使用Keras構建前饋神經網路時,需要做出一系列關於網路架構和訓練過程的選擇。讓我們回顧一下隱藏層中每個單元的工作流程:
- 接收多個輸入
- 對每個輸入使用引數值進行加權
- 將所有加權輸入與偏置(通常為1)相加
- 通常應用某種函式(稱為啟用函式)
- 將輸出傳送到下一層的單元
設計神經網路時,我們需要做出以下關鍵決策:
1. 層級單元數量與啟用函式
對於隱藏層和輸出層,必須定義每層中包含的單元數量和啟用函式。總體而言,層中的單元越多,網路學習複雜模式的能力越強。然而,更多的單元可能會導致網路過度擬合訓練資料,從而影響在測試資料上的表現。
對於隱藏層,一個流行的啟用函式是修正線性單元(ReLU):
$f(z) = max(0, z)$
其中z是加權輸入和偏置的總和。如我們所見,如果z大於0,啟用函式回傳z;否則,函式回傳0。這個簡單的啟用函式具有許多理想的特性,使其成為神經網路中的熱門選擇。
2. 隱藏層的數量
我們需要定義網路中使用的隱藏層數量。更多的層允許網路學習更複雜的關係,但計算成本也更高。在實踐中,我發現逐步增加層數並觀察效能變化是一個有效的方法。
3. 輸出層的結構與啟用函式
輸出層的性質通常由網路的目標決定。以下是一些常見的輸出層模式:
- *二元分類別:一個使用sigmoid啟用函式的單元。
- *多類別分類別:k個單元(其中k是目標類別的數量)和softmax啟用函式。
- 迴歸(預測連續值):一個沒有啟用函式的單元(或使用線性啟用函式)。
這些設計決策直接影響神經網路的學習能力和效能。在實踐中,通常需要嘗試不同的設定並評估其效果,以找到最適合特定問題的網路架構。
神經網路設計的藝術與實踐
設計一個有效的神經網路架構是一個反覆試驗的過程。在我的實踐中,發現以下幾點尤為重要:
從簡單開始:先從較少的層和節點開始,逐步增加複雜度,觀察模型效能的變化。
關注過擬合:當模型在訓練集上表現極佳但在驗證集上表現不佳時,考慮使用正則化技術或減少模型複雜度。
啟用函式的選擇:不同的問題可能需要不同的啟用函式。ReLU通常是一個好的起點,但有時Leaky ReLU、ELU或tanh可能更適合特定任務。
批次大小的影響:批次大小影響訓練速度和模型最終效能。較小的批次可能導致更好的泛化能力,但訓練速度較慢。
學習率的調整:適當的學習率對模型收斂至關重要。過大的學習率可能導致模型無法收斂,過小的學習率則使訓練過慢。
解決實際問題時,我通常會先分析資料特性,然後根據問題類別選擇適當的網路架構起點,接著透過實驗調整超引數,最終找到最佳設定。
神經網路的設計既是科學也是藝術,需要理論知識與實踐經驗的結合。隨著對問題領域和資料特性的深入理解,我們能夠更有效地
神經網路模型設計的關鍵決策
設計神經網路模型時,我們需要做出一系列關鍵決策,這些決策會直接影響模型的學習能力與最終效能。在多年的深度學習專案實踐中,我發現理解這些基礎設計原則比盲目套用複雜架構更為重要。
輸出層與損失函式的選擇
神經網路的輸出層設計與損失函式選擇必須與問題類別相符。根據問題性質,我們通常會遵循以下原則:
二元分類別題
- 輸出層:單一單元,使用sigmoid啟用函式
- 損失函式:二元交叉熵(binary cross-entropy)
sigmoid函式將輸出壓縮在0到1之間,完美對應二元分類別的機率值。
多元分類別題
- 輸出層:N個單元(N為類別數),使用softmax啟用函式
- 損失函式:分類別叉熵(categorical cross-entropy)
softmax確保所有類別的機率總和為1,適合處理互斥多類別的分類別題。
迴歸問題
- 輸出層:單一單元,不使用啟用函式(線性輸出)
- 損失函式:均方誤差(mean square error)
對於迴歸問題,我們希望直接預測數值,因此不需要將輸出轉換為機率值。
最佳化的選擇
最佳化可以視為在損失函式的「地形」上尋找最低點的策略。常見的最佳化包括:
- 隨機梯度下降(Stochastic Gradient Descent, SGD)
- 帶動量的隨機梯度下降(SGD with momentum)
- 均方根傳播(Root Mean Square Propagation, RMSProp)
- 自適應動量估計(Adaptive Moment Estimation, Adam)
每種最佳化都有其優缺點,在實務上我常根據問題特性選擇適合的最佳化略。例如,RMSProp在處理非靜態目標時表現優異,而Adam則因其自適應學習率特性在許多情況下成為首選。
Keras模型建立方式
Keras提供兩種建立神經網路的方法:
- Sequential模型:透過堆積積層來建立網路,適合大多數實際應用場景
- 函式式API:更靈活的建立方式,適合研究人員實作複雜的網路架構
對於大多數實務應用,Sequential模型已經足夠靈活與易於使用。
二元分類別經網路的訓練實作
讓我們實際動手建立一個用於二元分類別神經網路。這裡我們將使用IMDB電影評論資料集來實作一個情感分析模型,判斷評論是正面還是負面。
# 載入必要函式庫
import numpy as np
from keras.datasets import imdb
from keras.preprocessing.text import Tokenizer
from keras import models
from keras import layers
# 設定隨機種子以確保結果可重現
np.random.seed(0)
# 設定特徵數量
number_of_features = 1000
# 載入電影評論資料與目標向量
(data_train, target_train), (data_test, target_test) = imdb.load_data(
num_words=number_of_features)
# 將電影評論資料轉換為獨熱編碼特徵矩陣
tokenizer = Tokenizer(num_words=number_of_features)
features_train = tokenizer.sequences_to_matrix(data_train, mode="binary")
features_test = tokenizer.sequences_to_matrix(data_test, mode="binary")
# 開始建立神經網路
network = models.Sequential()
# 增加具有ReLU啟用函式的全連線層
network.add(layers.Dense(units=16,
activation="relu",
input_shape=(number_of_features,)))
# 增加另一個具有ReLU啟用函式的全連線層
network.add(layers.Dense(units=16, activation="relu"))
# 增加具有sigmoid啟用函式的輸出層
network.add(layers.Dense(units=1, activation="sigmoid"))
# 編譯神經網路
network.compile(loss="binary_crossentropy", # 交叉熵
optimizer="rmsprop", # 均方根傳播
metrics=["accuracy"]) # 準確率評估指標
# 訓練神經網路
history = network.fit(features_train, # 特徵
target_train, # 目標向量
epochs=3, # 訓練輪數
verbose=1, # 顯示訓練過程
batch_size=100, # 每批次觀測數
validation_data=(features_test, target_test)) # 測試資料
這段程式碼實作了一個完整的二元分類別經網路訓練流程:
資料載入與預處理:
- 我們從IMDB資料集載入25,000條訓練評論和25,000條測試評論
- 使用Tokenizer將文字轉換為二元特徵矩陣,每條評論用1000個最常見單詞的出現情況表示
網路架構:
- 第一層:16個神經元的全連線層,使用ReLU啟用函式,指定輸入形狀為1000個特徵
- 第二層:另一個16個神經元的全連線層,使用ReLU啟用函式
- 輸出層:單一神經元,使用sigmoid啟用函式輸出0-1之間的值,代表評論為正面的機率
編譯設定:
- 損失函式:二元交叉熵,適合二元分類別題
- 最佳化:RMSProp,有效處理非靜態目標
- 評估指標:準確率
訓練過程:
- 設定訓練3個輪次(epochs)
- 每批次處理100個樣本
- 使用測試資料進行驗證
在實際應用時,我發現對於文字分類別務,一個簡單的雙層神經網路往往能達到不錯的效果,無需過度複雜的架構。這個模型在IMDB資料集上能達到約86%的準確率,這對於僅使用單詞出現頻率特徵的模型來說是相當不錯的。
多元分類別經網路的實作
接下來,讓我們實作一個多元分類別經網路。這次我們將使用路透社新聞資料集,目標是將新聞文章分類別46個不同的類別中。
# 載入必要函式庫
import numpy as np
from keras.datasets import reuters
from keras.utils.np_utils import to_categorical
from keras.preprocessing.text import Tokenizer
from keras import models
from keras import layers
# 設定隨機種子
np.random.seed(0)
# 設定特徵數量
number_of_features = 5000
# 載入特徵和目標資料
data = reuters.load_data(num_words=number_of_features)
(data_train, target_vector_train), (data_test, target_vector_test) = data
# 將特徵資料轉換為獨熱編碼特徵矩陣
tokenizer = Tokenizer(num_words=number_of_features)
features_train = tokenizer.sequences_to_matrix(data_train, mode="binary")
features_test = tokenizer.sequences_to_matrix(data_test, mode="binary")
# 將目標向量進行獨熱編碼,建立目標矩陣
target_train = to_categorical(target_vector_train)
target_test = to_categorical(target_vector_test)
# 開始建立神經網路
network = models.Sequential()
# 增加具有ReLU啟用函式的全連線層
network.add(layers.Dense(units=100,
activation="relu",
input_shape=(number_of_features,)))
# 增加另一個具有ReLU啟用函式的全連線層
network.add(layers.Dense(units=100, activation="relu"))
# 增加具有softmax啟用函式的輸出層
network.add(layers.Dense(units=46, activation="softmax"))
# 編譯神經網路
network.compile(loss="categorical_crossentropy", # 分類別叉熵
optimizer="rmsprop", # 均方根傳播
metrics=["accuracy"]) # 準確率評估指標
# 訓練神經網路
history = network.fit(features_train, # 特徵
target_train, # 目標
epochs=3, # 3個訓練輪次
verbose=0, # 不顯示輸出
batch_size=100, # 每批次觀測數
validation_data=(features_test, target_test)) # 測試資料
這段程式碼實作了一個多元分類別經網路,用於將新聞文章分類別46個不同類別:
資料處理的差異:
- 我們使用了路透社新聞資料集,包含46個不同的新聞類別
- 使用
to_categorical
函式將目標向量轉換為獨熱編碼矩陣,這是多元分類別必要步驟
網路架構的調整:
- 我們增加了隱藏層的神經元數量到100個,因為多類別分類別題通常需要更大的網路容量
- 輸出層有46個神經元,對應46個新聞類別
- 使用softmax啟用函式確保所有類別預測機率總和為1
損失函式變化:
- 使用categorical_crossentropy而非binary_crossentropy,適用於多類別分類別題
輸出處理:
- softmax函式將確保所有46個輸出單元的值總和為1,每個值代表文章屬於對應類別的機率
從二元分類別多元分類別主要差異在於:
- 輸出層神經元數量從1個變為類別數量(46個)
- 啟用函式從sigmoid變為softmax
- 損失函式從binary_crossentropy變為categorical_crossentropy
- 目標值需要轉換為獨熱編碼格式
在實務應用中,當面對類別數量較多的多元分類別題時,我會傾向於使用更深的網路架構或增加每層的神經元數量,以確保模型有足夠的容量學習複雜的分類別界。
神經網路訓練過程的深入理解
當我們使用Keras的fit
方法訓練神經網路時,有幾個關鍵引數需要特別注意:
批次大小(batch_size)的影響
批次大小決定了在引數更新前處理多少樣本。這個引數對訓練過程有顯著影響:
- 較小的批次大小:更新更頻繁,可能幫助逃離區域性最小值,但訓練噪聲更大
- 較大的批次大小:更新較穩定,計算效率更高,但可能陷入區域性最小值
在實務上,我通常從較小的批次大小(如32或64)開始測試,然後根據訓練穩定性和硬體記憶體限制調整。
訓練輪次(epochs)的選擇
訓練輪次是模型看到整個訓練資料集的次數。選擇適當的輪次數量至關重要:
- 輪次過少:模型未能充分學習,導致欠擬合
- 輪次過多:可能導致過擬合,模型開始記憶訓練資料而非學習泛化規則
在實際應用中,我會使用早停法(early stopping),監控驗證集效能,當效能不再提升時停止訓練。
Keras中的History物件
與scikit-learn不同,Keras的fit
方法回傳一個History物件,而不是訓練好的模型本身。這個History物件包含訓練過程中每個輪次的損失值和效能指標,對於分析模型訓練過程非常有用。
# 檢視訓練歷史
print(history.history['loss']) # 訓練損失
print(history.history['val_loss']) # 驗證損失
print(history.history['accuracy']) # 訓練準確率
print(history.history['val_accuracy']) # 驗證準確率
透過繪製這些指標的變化趨勢,我們可以診斷模型是否存在過擬合、欠擬合或其他訓練問題。
神經網路設計的實用技巧
在多年的深度學習實踐中,我總結了一些實用的神經網路設計技巧:
網路層數與寬度的選擇
- 較簡單的問題:1-2個隱藏層通常足夠
- 複雜問題:可能
神經網路的多元應用:從分類別迴歸的技術解析
神經網路的強大之處在於其適應性—從分類別迴歸,從預測到模式識別,這種靈活性使其成為現代機器學習的核心工具。在實際應用中,瞭解如何針對不同問題類別調整神經網路架構至關重要。本文將探討神經網路在多類別分類別迴歸及預測方面的實作技巧。
多類別分類別解構Reuters新聞分型別
在處理Reuters新聞分類別題時,玄貓發現神經網路的架構調整對準確率有顯著影響。這個案例涉及11,228條新聞報導,每條報導需分類別46個主題之一。與二元分類別同,多類別分類別要特殊的設計考量。
資料準備的關鍵
將新聞報導轉換為機器可理解的格式是第一步挑戰。這裡採用了詞袋模型(Bag of Words),將每條新聞轉換為5,000個二元特徵,每個特徵表示特定詞是否出現在該新聞中。
對於目標變數,使用了獨熱編碼(One-hot Encoding):
# 檢視目標矩陣
target_train
# 輸出結果
array([[ 0., 0., 0., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 0., 0., 0.],
...,
[ 0., 0., 0., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 0., 0., 0.]])
這個矩陣中的每一行代表一條新聞報導,每行有46個值(對應46個類別),僅有一個位置為1.0,其餘為0.0,表示該新聞屬於哪個類別。這種編碼方式將類別標籤轉換為神經網路能夠處理的數值格式,同時保留了類別之間的獨立性。
多類別分類別網路架構調整
與二元分類別比,多類別分型別需要做出四個關鍵調整:
隱藏層單元數增加:為了捕捉46個類別之間更複雜的關係,需要增加隱藏層的神經元數量。
輸出層設計:輸出層必須包含46個單元(每類別個),並使用softmax啟用函式。這使網路能夠輸出46個值的陣列,總和為1,代表樣本屬於各類別的機率。
損失函式選擇:採用適合多類別分類別categorical_crossentropy(分類別叉熵)損失函式。
評估指標:使用accuracy作為評估指標,直接反映分類別準確性。
在實作多類別分類別,玄貓建議特別關注輸出層的設計和損失函式的選擇,這兩點對模型效能有決定性影響。過去玄貓曾遇到一個專案,僅僅透過將輸出層從sigmoid改為softmax並調整損失函式,準確率就提升了近15%。
神經網路迴歸:預測連續值的技術實作
神經網路不僅限於分類別題,在迴歸任務中同樣表現出色。下面探討如何構建和訓練用於迴歸的神經網路模型。
迴歸網路的構建流程
以下是使用Keras構建迴歸神經網路的完整實作:
# 載入所需函式庫
import numpy as np
from keras.preprocessing.text import Tokenizer
from keras import models
from keras import layers
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
from sklearn import preprocessing
# 設定隨機種子
np.random.seed(0)
# 生成特徵矩陣和目標向量
features, target = make_regression(n_samples=10000,
n_features=3,
n_informative=3,
n_targets=1,
noise=0.0,
random_state=0)
# 將資料分為訓練集和測試集
features_train, features_test, target_train, target_test = train_test_split(
features, target, test_size=0.33, random_state=0)
# 初始化神經網路
network = models.Sequential()
# 增加具有ReLU啟用函式的全連線層
network.add(layers.Dense(units=32,
activation="relu",
input_shape=(features_train.shape[1],)))
# 增加具有ReLU啟用函式的全連線層
network.add(layers.Dense(units=32, activation="relu"))
# 增加沒有啟用函式的全連線層
network.add(layers.Dense(units=1))
# 編譯神經網路
network.compile(loss="mse", # 均方誤差
optimizer="RMSprop", # 最佳化法
metrics=["mse"]) # 均方誤差評估指標
# 訓練神經網路
history = network.fit(features_train, # 特徵
target_train, # 目標向量
epochs=10, # 迭代次數
verbose=0, # 不輸出訓練過程
batch_size=100, # 每批觀測數
validation_data=(features_test, target_test)) # 測試資料
這段程式碼示了迴歸神經網路的完整構建過程。首先使用scikit-learn的make_regression生成模擬資料,包含10,000個樣本和3個特徵。然後構建一個三層神經網路:兩個具有ReLU啟用函式的隱藏層(每層32個單元),以及一個沒有啟用函式的輸出層(單一單元)。關鍵點是最後一層沒有使用啟用函式,這允許網路輸出任意範圍的連續值,而不是像分類別題那樣被限制在特定範圍內。
迴歸與分類別關鍵差異
迴歸神經網路與分類別路有三個關鍵差異:
輸出層設計:迴歸模型的輸出層通常只有一個單元,與不使用啟用函式。這與二元分類別用sigmoid或多類別分類別用softmax的做法不同。
損失函式選擇:迴歸問題通常使用均方誤差(MSE)作為損失函式,公式為:
MSE = (1/n) * Σ(y_i - ŷ_i)²
其中n是觀測數量,y_i是第i個觀測的實際目標值,ŷ_i是模型對第i個觀測的預測值。
評估指標:同樣使用MSE或其變體(如RMSE、MAE)而非準確率來評估模型效能。
在實際應用中,玄貓發現迴歸神經網路對特徵縮放非常敏感。雖然上面的例子使用了模擬資料,但在實際專案中,特徵標準化幾乎總是必要的。曾經在一個預測專案中,僅僅透過標準化特徵,玄貓將模型誤差降低了近40%。
使用神經網路進行預測的實用技巧
訓練完成後,如何使用神經網路進行預測?這看似簡單,但實際操作中有許多細節需要注意。
預測流程示範
以下是使用Keras訓練二元分型別並進行預測的完整範例:
# 載入所需函式庫
import numpy as np
from keras.datasets import imdb
from keras.preprocessing.text import Tokenizer
from keras import models
from keras import layers
# 設定隨機種子
np.random.seed(0)
# 設定我們想要的特徵數
number_of_features = 10000
# 從IMDB電影資料載入資料和目標向量
(data_train, target_train), (data_test, target_test) = imdb.load_data(
num_words=number_of_features)
# 將IMDB資料轉換為獨熱編碼特徵矩陣
tokenizer = Tokenizer(num_words=number_of_features)
features_train = tokenizer.sequences_to_matrix(data_train, mode="binary")
features_test = tokenizer.sequences_to_matrix(data_test, mode="binary")
# 初始化神經網路
network = models.Sequential()
# 增加具有ReLU啟用函式的全連線層
network.add(layers.Dense(units=16,
activation="relu",
input_shape=(number_of_features,)))
# 增加具有ReLU啟用函式的全連線層
network.add(layers.Dense(units=16, activation="relu"))
# 增加具有sigmoid啟用函式的全連線層
network.add(layers.Dense(units=1, activation="sigmoid"))
# 編譯神經網路
network.compile(loss="binary_crossentropy", # 交叉熵
optimizer="rmsprop", # 均方根傳播最佳化
metrics=["accuracy"]) # 準確率評估指標
# 訓練神經網路
history = network.fit(features_train, # 特徵
target_train, # 目標向量
epochs=3, # 迭代次數
verbose=0, # 不輸出訓練過程
batch_size=100, # 每批觀測數
validation_data=(features_test, target_test)) # 測試資料
# 預測試集的類別
predicted_target = network.predict(features_test)
這段程式碼示瞭如何使用IMDB電影評論資料集訓練情感分析模型,並使用它進行預測。關鍵部分是最後一行,使用network.predict()方法對測試集進行預測。對於這個二元分類別題,輸出是每個觀測屬於正面評論(類別1)的機率。例如,可以檢視第一個觀測被預測為正面評論的機率:
# 檢視第一個觀測被預測為類別1的機率
predicted_target[0]
# 輸出結果
array([ 0.83937484], dtype=float32)
這表示模型有約84%的信心認為第一條評論是正面的。在實際應用中,通常會設定一個閾值(如0.5)來將機率轉換為具體的類別預測。
預測結果的處理技巧
根據問題類別,預測結果的處理方式不同:
*二元分類別:輸出是單一機率值,需要設定閾值(通常為0.5)決定類別。
*多類別分類別:輸出是機率分佈陣列,通常取最大機率對應的類別作為預測結果。
迴歸問題:輸出直接是預測的連續值,可能需要進行反標準化處理。
玄貓在實際專案中發現,對於不平衡資料集,調整預測閾值是提高模型效果的簡單有效方法。例如,在一個詐欺檢測系統中,將閾值從0.5降低到0.3,大幅提高了對少數類別詐欺案例)的識別率,雖然增加了誤報率,但在該業務場景下是可接受的權衡。