TensorFlow2 初級教程(2):迴歸問題——汽車燃油效率預測

大家好!我是【AI 菌】,一枚愛彈吉他的程序員。我熱愛AI、熱愛分享、熱愛開源! 這博客是我對學習的一點總結與思考。如果您也對 深度學習、機器視覺、數據結構與算法、編程 等感興趣,可以關注我的動態,我們一起學習,一起進步~
我的博客地址爲:【AI 菌】的博客
我的Github項目地址是:【AI 菌】的Github

在這裏插入圖片描述
前言:
這個專欄我將分享我的 TensorFlow2 學習過程,力爭打造一個的輕鬆而高效的TensorFlow2入門學習教程,想學習的小夥伴可以關注我的動態!我們一起學習,一起進步!

相關文章:【TF2.0深度學習實戰——圖像分類】


一、迴歸問題

機器學習中有兩大基本問題:分類問題和迴歸問題。分類(classification) 的目的是從一系列的類別中選擇出一個分類,如果是針對圖片進行分類,就是圖片分類問題,這一部分可參見我上一個專欄:【TF2.0深度學習實戰——圖像分類】。在機器學習中,另一個重要的問題就是迴歸問題 (regression) 。它的目的是預測出如價格或概率這樣連續的輸出值。

本次我們學習一個基本的迴歸問題,用來預測汽車消耗燃油的效率。我們使用經典的 Auto MPG 數據集,構建了一個用來預測70年代末到80年代初汽車燃油效率的模型。爲了做到這一點,我們將爲該模型提供許多那個時期的汽車描述。這個描述包含:氣缸數,排量,馬力以及重量等。

Auto MPG 數據集部分樣本如下表所示:
在這裏插入圖片描述

二、數據集準備

(1)數據集下載與導入

# 下載AUTO-MPG數據集
dataset_path = keras.utils.get_file("auto-mpg.data", "http://archive.ics.uci.edu/ml/machine-learning-databases/auto-mpg/auto-mpg.data")

# 使用pandas導入數據集
column_names = ['MPG','Cylinders','Displacement','Horsepower','Weight',
                'Acceleration', 'Model Year', 'Origin']
raw_dataset = pd.read_csv(dataset_path, names=column_names,
                      na_values = "?", comment='\t',
                      sep=" ", skipinitialspace=True)
dataset = raw_dataset.copy()
dataset.tail()

(2)數據清洗

dataset.isna().sum()  # 數據集中包括一些未知值
dataset = dataset.dropna()  # 刪除未知行

# origin列實際上代表分類,將origin列轉換爲獨熱碼(one-hot)
origin = dataset.pop('Origin')  
dataset['USA'] = (origin == 1)*1.0
dataset['Europe'] = (origin == 2)*1.0
dataset['Japan'] = (origin == 3)*1.0
dataset.tail()

將origin列轉換爲獨熱碼後,原來數據集樣本變爲:

在這裏插入圖片描述

(3)數據集劃分

# 拆分訓練數據集和測試數據集
train_dataset = dataset.sample(frac=0.8, random_state=0)
test_dataset = dataset.drop(train_dataset.index)

(4)數據檢查

使用 seaborn 庫快速查看訓練集中幾對列的聯合分佈。

# 使用seaborn進行數據檢查
sns.pairplot(train_dataset[["MPG", "Cylinders", "Displacement", "Weight"]], diag_kind="kde")  

聯合分佈如下:

在這裏插入圖片描述

(5)分離標籤

由於標籤MPG列存在於下載的數據集中,因此需要單獨分離開來。

train_labels = train_dataset.pop('MPG')
test_labels = test_dataset.pop('MPG')

(6)數據規範化

def norm(x):
  return (x - train_stats['mean']) / train_stats['std']
normed_train_data = norm(train_dataset)
normed_test_data = norm(test_dataset)

三、模型搭建與訓練

(1)模型的搭建

model = keras.Sequential([
    layers.Dense(64, activation='relu', input_shape=[len(train_dataset.keys())]),
    layers.Dense(64, activation='relu'),
    layers.Dense(1)
  ])

(2)模型的裝配

optimizer = tf.keras.optimizers.RMSprop(0.001)
model.compile(loss='mse',
                optimizer=optimizer,
                metrics=['mae', 'mse'])

(3)模型的訓練

EPOCHS = 1000
history = model.fit(
  normed_train_data, train_labels,
  epochs=EPOCHS, validation_split=0.2, verbose=2)

(4)訓練的可視化

def plot_history(history):
  hist = pd.DataFrame(history.history)
  hist['epoch'] = history.epoch

  plt.figure()
  plt.xlabel('Epoch')
  plt.ylabel('Mean Abs Error [MPG]')
  plt.plot(hist['epoch'], hist['mae'],
           label='Train Error')
  plt.plot(hist['epoch'], hist['val_mae'],
           label='Val Error')
  plt.ylim([0, 5])
  plt.legend()

  plt.figure()
  plt.xlabel('Epoch')
  plt.ylabel('Mean Square Error [$MPG^2$]')
  plt.plot(hist['epoch'], hist['mse'],
           label='Train Error')
  plt.plot(hist['epoch'], hist['val_mse'],
           label='Val Error')
  plt.ylim([0, 20])
  plt.legend()
  plt.show()
  
plot_history(history)

可視化結果:
在這裏插入圖片描述
在這裏插入圖片描述
上圖表顯示在約80個 epochs 之後誤差非但沒有改進,反而出現惡化。 因此我們可以更新 model.fit 調用,當驗證值沒有提高上是自動停止訓練。 具體的作法就是:使用一個 EarlyStopping callback 來測試每個 epoch 的訓練條件。如果經過一定數量的 epochs 後沒有改進,就自動停止訓練。

四、停訓與預測

(1)提前停止訓練

由於訓練到一定epochs後,模型的誤差可能不再變化,甚至在惡化,這時就可以提前停止訓練,節省時間。

# patience 值用來檢查改進 epochs 的數量
early_stop = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)
history = model.fit(normed_train_data, train_labels, epochs=EPOCHS,
                    validation_split=0.2, verbose=1, callbacks=[early_stop])

使用 EarlyStopping callback 連續檢測10個epochs,如果誤差沒有變小,就停止訓練。結果如下:
在這裏插入圖片描述
在這裏插入圖片描述
從上圖可以發現:加了 EarlyStopping callback 後,模型提前停止訓練了,在訓練到50個epochs左右時,誤差就沒有再縮小,從而提前停止訓練。

(2)預測效果

以上都是在訓練和驗證集上的測試效果,下面我們將對測試集進行預測,來測試模型的泛化效果。

# 平均預測誤差
loss, mae, mse = model.evaluate(normed_test_data, test_labels, verbose=2)
print("Testing set Mean Abs Error: {:5.2f} MPG".format(mae))
test_predictions = model.predict(normed_test_data).flatten()

# 可視化預測效果:prediction-truth圖
plt.figure()
plt.scatter(test_labels, test_predictions)
plt.xlabel('True Values [MPG]')
plt.ylabel('Predictions [MPG]')
plt.axis('equal')
plt.axis('square')
plt.xlim([0,plt.xlim()[1]])
plt.ylim([0,plt.ylim()[1]])
_ = plt.plot([-100, 100], [-100, 100])

# 誤差分佈圖
plt.figure()
error = test_predictions - test_labels
plt.hist(error, bins = 25)
plt.xlabel("Prediction Error [MPG]")
_ = plt.ylabel("Count")
plt.show()

測試集上的預測效果如下:

  1. 平均誤差。平均誤差爲1.98。
Testing set Mean Abs Error:  1.98 MPG
  1. prediction-truth圖。橫軸表示真實的值,縱軸表示的是預測的值。可見預測值很貼近真實值。

在這裏插入圖片描述

  1. 誤差分佈。橫軸是預測誤差,縱軸是統計的每個誤差對應的樣本數。
    在這裏插入圖片描述
    由上圖可見,它不是完全的高斯分佈,可以推斷出,這是因爲樣本的數量很小所導致的。

完整代碼已經上傳github倉庫:https://github.com/Keyird/TensorFlow2-for-beginner
如果對你有幫助的話,歡迎star收藏~

最好的關係是互相成就,各位的「三連」就是【AI 菌】創作的最大動力,我們下期見!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章