iT邦幫忙

2024 iThome 鐵人賽

DAY 13
0

今天是第13天我們可以寫一些Lstm模型訓練的東西,以下是程式碼

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Dropout
from tensorflow.keras.callbacks import ModelCheckpoint, ReduceLROnPlateau, EarlyStopping
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.losses import Huber
from tensorflow.keras.regularizers import l1, l2
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# 定義函數來創建LSTM模型的訓練資料集
def create_dataset(dataset, size):
    question, ans = [], []
    for i in range(len(dataset) - size):
        q_array = dataset[i:i + size]  # 取出從i開始的size大小的數據作為問題
        a_array = dataset[i + size]    # 將第i+size個數據作為答案
        ans.append(a_array)
        question.append(q_array)
    return np.array(question), np.array(ans)  # 返回問題和答案對,轉換為NumPy陣列

# 設定回顧窗口大小
lookback = 8

# 建立LSTM模型
model = Sequential([
    # 第一層LSTM,返回完整的序列,用L1正則化來防止過度擬合
    LSTM(200, activation='relu', return_sequences=True, input_shape=(lookback, 2), kernel_regularizer=l1(0.1)),
    Dropout(0.1),  # 丟棄10%的神經元來防止過度擬合
    # 第二層LSTM,僅返回最終輸出,用L2正則化來防止過度擬合
    LSTM(200, activation='relu', return_sequences=False, kernel_regularizer=l2(0.1)),
    # 最後一層全連接層,輸出2個單位(x, y),用L1正則化
    Dense(2, kernel_regularizer=l1(0.1))
])

# 編譯模型,使用Adam優化器和Huber損失函數
model.compile(optimizer=Adam(learning_rate=0.00025), loss=Huber())

# 讀取數據,僅選取"x"和"y"列並轉換為浮點型
input_data = pd.read_csv("1fish_11000.csv")
input_data = input_data[["x", "y"]].values.astype('float32')

# 創建訓練和測試資料集
train, test = create_dataset(input_data, lookback)

# 印出訓練和測試資料集的形狀
print(train.shape)
print(test.shape)

# 定義回調函數
early_stopping = EarlyStopping(monitor='val_loss', patience=50, restore_best_weights=True)  # 提早停止訓練,防止過度擬合
reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=10, min_lr=1e-6)  # 當模型停止改善時減少學習率
checkpoint = ModelCheckpoint('best_model.keras', monitor='val_loss', save_best_only=True, mode='min')  # 保存最佳模型

# 訓練模型,設定12000個epoch,批次大小為回顧窗口大小
history = model.fit(train, test, epochs=12000, batch_size=lookback, callbacks=[checkpoint, early_stopping, reduce_lr])

# 繪製模型的損失變化
plt.plot(history.history['loss'], label='Loss', c="g")
plt.title('Model Loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()

# 繪製模型的準確度變化
plt.plot(history.history.get('accuracy', []), label='accuracy', c="b")  # 使用get來處理不存在的'accuracy'
plt.title('Model Accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()
plt.show()

# 保存最終的模型
model.save('new lstm.h5')

1. 匯入所需的庫

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Dropout
from tensorflow.keras.callbacks import ModelCheckpoint, ReduceLROnPlateau, EarlyStopping
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.losses import Huber
from tensorflow.keras.regularizers import l1, l2
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
  • tensorflow.keras: 這是Keras API的一部分,整合在TensorFlow中,用於建立和訓練深度學習模型。

    • Sequential: 這是一個線性堆疊模型,用於逐層構建神經網路。
    • LSTM: 一種特殊的遞歸神經網路層(Long Short-Term Memory),非常適合處理序列數據。
    • Dense: 全連接層,通常用於神經網路的最後幾層來進行輸出。
    • Dropout: 一種正則化技術,用於防止模型過度擬合。
    • ModelCheckpoint: 用來在訓練過程中保存模型的最佳狀態。
    • ReduceLROnPlateau: 用來在模型性能停止提升時減小學習率。
    • EarlyStopping: 用來在模型性能不再提升時提前停止訓練。
    • Adam: 一種常用的優化器,適合處理大部分深度學習問題。
    • Huber: 損失函數的一種,對於處理異常值更為穩健。
    • l1, l2: 用來進行L1和L2正則化,以防止過度擬合。
  • numpy: 這是一個科學計算庫,用於處理大型多維數組和矩陣運算。

  • pandas: 用於數據操作和分析,特別是在讀取和處理資料表格式的數據時非常方便。

  • matplotlib.pyplot: 用來繪製圖表,視覺化數據和模型的訓練過程。

2. 資料集創建函數 create_dataset

def create_dataset(dataset, size):
    question, ans = [], []
    for i in range(len(dataset) - size):
        q_array = dataset[i:i + size]  # 取出從i開始的size大小的數據作為問題
        a_array = dataset[i + size]    # 將第i+size個數據作為答案
        ans.append(a_array)
        question.append(q_array)
    return np.array(question), np.array(ans)  # 返回問題和答案對,轉換為NumPy陣列
  • create_dataset 函數: 此函數將一連串的數據分割成「問題-答案」對,用於訓練LSTM模型。
    • dataset: 輸入的數據集,這裡是斑馬魚的xy座標。
    • size: 回顧窗口的大小,決定模型在進行預測時需要參考的歷史數據長度。
    • question: 這是LSTM的輸入數據,形狀是(size, 2),表示該窗口內的xy座標。
    • ans: 這是對應於question的正確答案,即下個時間點的xy座標。

這個函數實際上是生成了LSTM訓練時所需的樣本序列,比如:

  • 如果size是8,那麼LSTM每次會查看8個數據點來預測第9個數據點的xy座標。

3. 設置回顧窗口大小

lookback = 8
  • lookback: 回顧窗口大小,這裡設為8,表示LSTM模型會查看過去8個時間點的數據來進行預測。

4. 建立LSTM模型

model = Sequential([
    LSTM(200, activation='relu', return_sequences=True, input_shape=(lookback, 2), kernel_regularizer=l1(0.1)),
    Dropout(0.1),
    LSTM(200, activation='relu', return_sequences=False, kernel_regularizer=l2(0.1)),
    Dense(2, kernel_regularizer=l1(0.1))
])
  • 模型架構:
    • 第一層LSTM:

      • units=200: LSTM單元的數量,也就是隱藏層的神經元數量。
      • activation='relu': 使用ReLU激活函數,這種激活函數能有效避免梯度消失問題。
      • return_sequences=True: 這個參數表示該層將輸出序列,而不是單個向量,這樣後續層能接收到完整的序列。
      • input_shape=(lookback, 2): 輸入數據的形狀,lookback代表時間步長,2代表特徵數量(xy座標)。
      • kernel_regularizer=l1(0.1): 使用L1正則化來防止過度擬合。
    • Dropout層:

      • Dropout(0.1): 在訓練過程中,隨機丟棄10%的神經元,這樣可以有效減少過度擬合。
    • 第二層LSTM:

      • return_sequences=False: 這一層只返回最後的輸出,不再返回序列,適合作為最終的特徵提取層。
      • kernel_regularizer=l2(0.1): 使用L2正則化來防止過度擬合。
    • Dense層:

      • Dense(2): 最後一層全連接層輸出2個單位(即xy座標),用於預測下一步的座標。
      • kernel_regularizer=l1(0.1): 再次使用L1正則化來防止過度擬合。

5. 編譯模型

model.compile(optimizer=Adam(learning_rate=0.00025), loss=Huber())
  • 編譯模型:
    • optimizer=Adam(learning_rate=0.00025): 使用Adam優化器,設置學習率為0.00025
    • loss=Huber(): 使用Huber損失函數,這種損失函數在處理異常值時更穩健,比均方誤差更能應對噪聲。

6. 數據加載與預處理

input_data = pd.read_csv("1fish_11000.csv")
input_data = input_data[["x", "y"]].values.astype('float32')
train, test = create_dataset(input_data, lookback)
  • 讀取數據:

    • input_data = pd.read_csv("1fish_11000.csv"): 從CSV文件讀取數據。
    • input_data = input_data[["x", "y"]].values.astype('float32'): 選取xy列,並將數據轉換為float32類型,以便於TensorFlow處理。
  • 創建訓練和測試數據集:

    • 使用create_dataset函數,將數據創建成訓練和測試用的樣本對。

7. 訓練模型

early_stopping = EarlyStopping(monitor='val_loss', patience=50, restore_best_weights=True)
reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=10, min_lr=1e-6)
checkpoint = ModelCheckpoint('best_model.keras', monitor='val_loss', save_best_only=True, mode='min')
history = model.fit(train, test, epochs=12000, batch_size=lookback, callbacks=[checkpoint, early_stopping, reduce_lr])
  • 定義回調函數:

    • early_stopping: 監控驗證損失val_loss,如果50個epoch內沒有改善,則停止訓練,並恢復到性能最佳的權重。

    • reduce_lr: 監控驗證損失val_loss,如果10個epoch內沒有改善,將學習率減少一半,直到達到最低學習率1e-6

    • checkpoint: 監控驗證損失val_loss,並將最佳模型權重保存為best_model.keras

  • 模型訓練:

    • model.fit(train, test, epochs=12000, batch_size=lookback, callbacks=[checkpoint, early_stopping, reduce_lr]): 開始訓練模型,指定如下參數:
      • train: 訓練數據(即問題部分)。
      • test: 驗證數據(即答案部分)。
      • epochs=12000: 訓練的最大迭代次數設為12000。
      • batch_size=lookback: 每次更新權重時使用lookback個樣本作為一個批次。
      • callbacks=[checkpoint, early_stopping, reduce_lr]: 使用定義好的回調函數來控制訓練過程。

8. 視覺化模型訓練過程

plt.plot(history.history['loss'], label='Loss', c="g")
plt.title('Model Loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()

plt.plot(history.history['accuracy'], label='accuracy', c="b")
plt.title('Model Accuracy')
plt.xlabel('Epochs')
plt.ylabel('accuracy')
plt.legend()
plt.show()
  • 損失函數圖:

    • plt.plot(history.history['loss'], label='Loss', c="g"): 繪製損失函數隨著epoch的變化。
    • plt.title('Model Loss'): 設置圖表標題。
    • plt.xlabel('Epochs'), plt.ylabel('Loss'): 設置x軸和y軸的標籤。
    • plt.legend(): 顯示圖例。
    • plt.show(): 顯示損失圖表。
  • 準確率圖:

    • plt.plot(history.history['accuracy'], label='accuracy', c="b"): 繪製準確率隨著epoch的變化。
    • 其他設置與損失函數圖相似。

9. 保存模型

model.save('new lstm.h5')
  • model.save('new lstm.h5'): 將訓練好的模型權重和結構保存到文件new lstm.h5中,方便之後的加載和推理使用。

整體流程總結

這個程式碼的主要目的是使用LSTM模型來預測斑馬魚的xy座標。它從讀取數據開始,經過數據預處理,接著構建LSTM模型,並設置了一系列的正則化和回調函數來防止過度擬合。最後,模型進行了訓練,並將訓練過程中的損失和準確率進行了視覺化,並保存了最終的模型。

這段程式碼的設計針對的是時序數據預測,特別適合於斑馬魚的行為分析或者其他類似的生物行為預測任務。


上一篇
day 12 斑馬魚使用者介面
下一篇
day 14 Yolo辨識輪匡是否變形
系列文
LSTM結合Yolo v8對於多隻斑馬魚行為分析30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言