跳轉到

3.1 DNN Regression

範例程式:Open In Colab

迴歸任務的目標是預測連續數值,例如設備耗電量、產品良率、客戶消費金額、溫度、油耗、感測器讀值或風險分數。和分類任務不同,迴歸模型不是回答「是哪一類」,而是回答「數值是多少」。

本篇使用 scikit-learn 內建的 Diabetes Dataset 建立表格資料 DNN 迴歸模型,完整示範資料切分、標準化、Dense DNN 建模、EarlyStopping、MAE/RMSE/R2 評估、逐筆預測與模型保存。

1. 迴歸任務在學什麼?

假設每一列是一筆樣本,每個欄位是一個數值特徵,最後有一個欄位是想預測的連續目標。DNN Regression 要學的是輸入特徵和目標值之間的關係。

任務 輸入特徵 預測目標
設備耗電預測 溫度、轉速、負載、時間 耗電量
品質預測 製程參數、原料批次、環境條件 良率
客戶價值預測 瀏覽次數、購買次數、會員等級 未來消費金額
感測器數值預測 歷史讀值、環境特徵、設備狀態 下一期讀值

迴歸模型最後一層通常只有一個神經元,而且不使用 sigmoidsoftmax

tf.keras.layers.Dense(1)

原因是迴歸輸出不是機率,也不是類別,而是一個連續實數。

2. Diabetes Dataset 資料說明

Notebook 使用:

data = load_diabetes(as_frame=True)
df = data.frame.copy()

Diabetes Dataset 是一個小型迴歸資料集。每筆資料包含 10 個數值特徵,目標值是疾病進展的連續數值。這份資料乾淨、可重現、執行速度快,適合作為表格 DNN 迴歸的入門範例。

實務專案中,這一步通常會換成讀取自己的 CSV:

df = pd.read_csv('your_data.csv')

觀察資料時,至少要確認三件事:

  1. 每一列是否是一筆樣本。
  2. 哪些欄位是模型輸入特徵。
  3. 哪個欄位是要預測的連續目標。

Note

迴歸任務很容易受到極端目標值影響。若目標值有明顯離群值,MSE 會被少數大誤差主導,建模前應先檢查資料品質,必要時考慮目標轉換或離群值處理。

3. 切分資料與標準化

本篇將資料切成 train、validation、test 三份:

x_train_full, x_test, y_train_full, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)
x_train, x_valid, y_train, y_valid = train_test_split(
    x_train_full, y_train_full, test_size=0.2, random_state=42
)

三份資料用途不同:

資料 用途
train 更新模型權重
validation 觀察訓練過程與 EarlyStopping
test 最後評估泛化能力

接著使用 StandardScaler

scaler = StandardScaler()
x_train = scaler.fit_transform(x_train)
x_valid = scaler.transform(x_valid)
x_test = scaler.transform(x_test)

fit_transform() 只能用在訓練集。validation/test 只能使用訓練集學到的平均值與標準差做 transform(),避免資料洩漏。

4. 建立 DNN 迴歸模型

model = tf.keras.Sequential([
    tf.keras.layers.Input(shape=(x_train.shape[1],)),
    tf.keras.layers.Dense(64, activation='relu'),
    tf.keras.layers.Dense(32, activation='relu'),
    tf.keras.layers.Dense(1)
])

這個模型可以拆成三個部分理解:

  1. Input:告訴模型每筆資料有幾個特徵。
  2. Dense hidden layers:學習特徵之間的非線性組合。
  3. Dense(1):輸出一個連續預測值。

編譯時使用 MSE 作為 loss,MAE 作為監控指標:

model.compile(
    optimizer=tf.keras.optimizers.Adam(learning_rate=0.01),
    loss='mse',
    metrics=['mae']
)

MSE 對大誤差比較敏感,適合作為訓練目標;MAE 單位和目標值一致,較容易解讀。

5. 訓練模型與 EarlyStopping

callbacks = [
    tf.keras.callbacks.EarlyStopping(
        monitor='val_loss',
        patience=20,
        restore_best_weights=True
    )
]

EarlyStopping 會在 validation loss 長時間沒有改善時停止訓練,並還原到 validation loss 最好的權重。這可以避免模型在訓練集上越學越好,但 validation set 開始變差。

6. 迴歸模型評估

迴歸任務常見指標:

指標 解讀
MAE 平均差多少,單位和目標值相同
RMSE 對大誤差更敏感,單位和目標值相同
R2 解釋變異比例,越接近 1 越好

Notebook 會建立 regression_report(),分別計算 train、valid、test。觀察結果時不要只看 train。若 train 很好但 test 明顯差很多,代表模型可能過擬合;若 train 和 test 都不好,可能是特徵不足、模型不合適,或資料本身噪音太大。

7. 預測新資料

sample = x_test[:5]
pred = model.predict(sample, verbose=0).ravel()

模型輸出後可以和真實值放在同一張表中比較:

pd.DataFrame({
    'actual': y_test[:5],
    'predicted': pred,
    'error': pred - y_test[:5]
})

整體指標可以告訴我們模型平均表現,逐筆預測則能讓我們理解模型錯在哪些樣本上。

8. 保存與載入模型

Keras 建議使用 .keras 格式保存模型:

model.save('dnn_regression_model.keras')
loaded_model = tf.keras.models.load_model('dnn_regression_model.keras')

Info

如果標準化流程沒有包進模型,部署時也要保存同一個 scaler。否則新資料沒有用同一組平均值與標準差轉換,模型輸入分布會和訓練時不同。

9. 如何套用自己的資料?

df = pd.read_csv('your_data.csv')
target_col = 'your_target'
feature_cols = [col for col in df.columns if col != target_col]

X = df[feature_cols].values.astype('float32')
y = df[target_col].values.astype('float32')

若資料包含類別欄位,先不要直接塞進這篇的純數值 DNN。可以改看 3.6 Mixed Feature DNN,用 Keras preprocessing layer 同時處理數值與類別欄位。

10. 常見調整方向

  1. 調整 hidden layer 的寬度,例如 32、64、128。
  2. 調整 learning rate,例如 0.001、0.003、0.01。
  3. 加入 Dropout 或 L2 regularization,降低過擬合。
  4. 對偏態目標值做 log transform。
  5. 使用更多有效特徵,通常比盲目加深模型更重要。

11. 小結

DNN Regression 的核心流程是:準備數值特徵、切分資料、標準化、建立 Dense DNN、使用 MSE/MAE 訓練、用 MAE/RMSE/R2 評估,最後保存模型。這篇可以作為表格迴歸任務的基礎模板。