本篇繼續來整理我讀布留川英一寫的 "強化式學習-打造最強通用演算法 AlphaZero" 這本書的摘要筆記, 本系列之前的筆記參考 :
以下是我讀完第三章 "深度學習" 第二個演練範例 (波士頓房地產預測) 的摘要筆記, 此處是用深度學習來處理迴歸問題, 迴歸 (regression) 用來預測連續變數的值, 例如薪資, 股價, 房地產價格等, 此例是希望以訓練好的模型, 可依照房間數, 犯罪率, 便利性等特徵去預測波士頓的房價.
- 設定 matplotlib 內嵌圖形 :
%matplotlib inline - 匯入套件模組 : from tensorflow.keras.datasets import boston_housingfrom tensorflow.keras.layers import Activation, Dense, Dropoutfrom tensorflow.keras.models import Sequentialfrom tensorflow.keras.callbacks import EarlyStoppingfrom tensorflow.keras.optimizers import Adamimport pandas as pdimport numpy as npimport matplotlib.pyplot as plt
- 下載資料集 :(train_data, train_labels), (test_data, test_labels)=boston_housing.load_data()
Downloading data from
https://storage.googleapis.com/tensorflow/tf-keras-datasets/boston_housing.npz
57344/57026 [==============================] - 0s 0us/step
65536/57026 [==================================] - 0s 0us/step其中訓練資料集 train_data 有 404 筆 (含 13 個特徵), 測試資料集 test_data 有 102 筆. 此資料集有如下 13 個特徵, 故輸入層安排 13 個神經元與其對接 :特徵 說明 CRIM 人均犯罪率 ZN 面積 >= 25000 平方英尺的住宅用地比率 INDUS 非零售業商業用地所佔面積比率 CHAS 是否在查爾斯河沿岸 (1=是, 0=否) NOX 一氧化碳濃度 RM 住宅平均房間數 AGE 1940 年之前建造之物件比率 DIS 與波士頓五個就業機構之間的加權距離 RAD 通往環狀高速公路的便利程度 TAX 每 10000 美元的不動產稅率總計 PTRATIO 各城鎮的兒童與教師比率 B 1000(bk-0.03)**2, bk=各城鎮的黑人比率 LSTAT 從事低薪職業的人口百分比 (%) 接下來的兩個密集層都是 64 個神經元, 且都使用 ReLu 激活函數. 最後輸出層只需要一個神經元, 因為要預測的房屋價格是單一數值 (即迴歸值). 注意, 此模型沒有使用丟棄層, 因為此資料集訓練筆數僅 404 筆, 且深度也沒有很深, 權重參數不多, 根據經驗若使用丟棄層將使準確率降低. - 檢視資料集 :
檢視資料型態 :結果全部都是 Numpy 陣列 <class 'numpy.ndarray'>.print(type(train_data)) # <class 'numpy.ndarray'>print(type(train_labels)) # <class 'numpy.ndarray'>print(type(test_data)) # <class 'numpy.ndarray'>print(type(test_labels)) # <class 'numpy.ndarray'>
檢視資料型狀 :print(train_data.shape) # (404, 13)print(train_labels.shape) # (404,)print(test_data.shape) # (102, 13)print(test_labels.shape) # (102,)
檢視前五筆練資料 :print(train_data[0:5])
可見都是令人眼花撩亂的浮點數組成的 2D 陣列, 每一筆都有 13 個特徵之數值. 可以將這些資料丟給 Pandas 轉成 DataFrame 物件較容易觀察 :column_names=['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE','DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT']df=pd.DataFrame(train_data, columns=column_names)df.head()
檢視前五筆訓練標籤 (答案) :print(train_labels[0:5]) # [15.2 42.3 50. 21.1 17.7] - 資料預處理 :
包含兩步驟 : 資料集洗牌 (reshuffle) 與正規化 (normalize), 這可以獲得更好的訓練成果. 洗牌是將訓練資料的順序打亂 (其標籤也會同步打亂, 但保持不變之對應關係) :order = np.random.randint(0,404, size=404) train_data = train_data[order] train_labels = train_labels[order]
正規化是將各特徵的數值都轉成正規值, 避免某些數值較大的特徵 (例如 TAX) 主宰了權重之調整, 最常使用的正規化方法是轉成平均值為 0, 標準差為 1 的正規值, 計算方式是將特徵的值減掉該特徵所有值的平均值, 再除以該特徵所有值的標準差 :# 訓練集正規化mean=train_data.mean(axis=0)std=train_data.std(axis=0)train_data=(train_data - mean) / stdtest_data=(test_data - mean) / std
經過這兩道程序後再用 Pandas 來觀察前五筆訓練資料 :column_names=['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE','DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT']df=pd.DataFrame(train_data, columns=column_names)df.head()
可見數值原本是好幾百的 TAX 欄位都縮到平均值 0 附近了 (因為洗牌是隨機的, 前五筆數值會與書上不同). - 建構神經網路 :
建立兩個隱藏層的神經網路 :
注意, 迴歸問題的輸出層不需要激活函數.model=Sequential()model.add(Dense(16, activation='relu', input_shape=(13,)))model.add(Dense(16, activation='relu'))model.add(Dense(1)) - 編譯模型 :model.compile(loss='mse', optimizer=Adam(learning_rate=0.001), metrics=['mae'])書上用的學習率參數 lr 已經被廢棄了, 要改用 learning_rate.
- 設定早期停止回呼函數 :early_stop=EarlyStopping(monitor='val_loss', patience=20)
參數 monitor 用來指定訓練時要監視的對象, 此處設為 'val_loss' 表示要監視驗證誤差; patience 參數用來指定可容忍的訓練周期數, 此處設為 20 表示若超過 20 個周期監視對象並未再進步就停止訓練. - 訓練模型 :history=model.fit(train_data, train_labels, batch_size=32, epochs=500,validation_split=0.2, callbacks=[early_stop])
注意, callbacks 參數值為一個串列, 亦即訓練模型時可指定多個回呼函數 :(略)
可見雖然指定做 500 輪訓練, 但到 235 輪時就因為誤差已連續 20 個 epoch 都沒再改善而停止訓練以避免讓模型因無效訓練反而越變越糟. - 繪製訓練過程圖形 :plt.plot(history.history['mae'], label='train mae')plt.plot(history.history['val_mae'], label='val mae')plt.xlabel('epoch')plt.ylabel('mae')plt.legend(loc='best')plt.ylim([0,5])plt.show()
- 用測試集進行評估 :test_loss, test_mae=model.evaluate(test_data, test_labels)print('loss:{:.3f}\nmae: {:.3f}'.format(test_loss, test_mae))
4/4 [==============================] - 0s 3ms/step - loss: 17.8420 - mae: 2.7829 loss:17.842 mae: 2.783
測試集評估結果誤差約 2.78 (理想值是 0). - 用前 10 筆資料做預測 :# 顯示測試集的標籤價格print('前 10 筆測試標籤:',np.round(test_labels[0:10]))# 顯示預測結果的價格test_predictions=model.predict(test_data[0:10]).flatten()print('前 10 筆預測結果:',np.round(test_predictions))
結果如下 :
前 10 筆測試標籤: [ 7. 19. 19. 27. 22. 24. 31. 23. 20. 23.]
前 10 筆預測結果: [ 9. 19. 22. 35. 25. 21. 25. 21. 20. 23.]
以上演練筆記本參考 :
# https://github.com/tony1966/colab/blob/main/reinforcement_learning_ch3_boston.ipynb
書附檔案中的筆記本參考 :
# https://github.com/tony1966/colab/blob/main/3_1_regression.ipynb
沒有留言:
張貼留言