Tensorflow2.0學習(六) — 線性迴歸模型(燃油效率預測)

這一節開始主要講述Tensorflow官方提供的樣例代碼,我會對其中一些代碼部分進行修改並且詳細解釋大部分代碼的意思,方便初學的朋友們學習。這節課我們要完成的是一個線性迴歸模型的搭建及Auto MPG數據集的預測,順便附上官方代碼的鏈接:https://tensorflow.google.cn/tutorials/keras/regression

這一節我們使用的數據集爲Auto MPG數據集,我們需要根據該數據集提供的一些相關特徵(如氣缸數、排量和馬力等)搭建一個線性迴歸模型去預測一種汽車的燃油效率。

一.Auto MPG數據集的加載

1.導入相關庫。這裏也許有些朋友們不知道第一行future導進一些庫的意思,這行代碼存在的原因主要是因爲python2和python3版本的不同有時候會導致一些庫無法兼容使用,如果想在一個python版本使用另一個版本不兼容的函數,就需要導入這行代碼。然後seaborn庫作用則是用於畫圖。

from __future__ import absolute_import, division, print_function, unicode_literals
import pathlib
import matplotlib.pyplot as plt
import pandas as pd 
import seaborn as sns #畫圖
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

2.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")

3.爲數據集每列數據添加列名。其中MPG爲燃油效率,Displacement爲排水量,Horsepower爲馬力,Weight爲重量,Acceleration爲加速度,Model Year爲車型年份,origin代表車型的生產地。

column_names = ['MPG','Cylinders','Displacement','Horsepower','Weight','Acceleration', 'Model Year', 'Origin']

4.讀入數據。打開原數據文件我們可以發現裏面有一些數據是“?”,代表數據遺失。因此我們可以用na_values='?'將指定的這些數據標名爲NAN(未知值),而comment=’\t‘的意思是忽略以"\t"(一個製表符)開頭後的行內容,這部分內容不讀入,sep=' '的意思是將數據中有空白的部分當作分隔符,用來分割不同列的數據,最後skipinitialspace=True的意思則是忽略分隔符後的空白。

raw_dataset = pd.read_csv(dataset_path, names=column_names,na_values = "?", comment='\t',sep=" ", skipinitialspace=True)

5.顯示數據集部分數據集。tail()的意思是顯示數據後5行的內容。

dataset = raw_dataset.copy()
dataset.tail()

二.Auto MPG數據集的預處理

1.顯示爲空值(NAN)的特徵類別和數目。

dataset.isna().sum()

2.因爲空值數據不多,因此我們直接用dropna()函數刪除這些數據。

dataset = dataset.dropna()

3.將origin轉換成獨熱碼。pop爲移除的意思,同時也可以用變量儲存起來。

origin = dataset.pop('Origin') #移除origin特徵同時保存成變量
dataset['USA'] = (origin == 1)*1.0 
dataset['Europe'] = (origin == 2)*1.0
dataset['Japan'] = (origin == 3)*1.0
dataset.tail() #顯示後5行內容

4.分割訓練集和測試集。採用sample函數進行訓練集分割,其中frac參數爲分割比例,random_state=0意思取得的數據不重複,如果等於1則是代表取得的數據可以重複。接着測試集就是訓練集剩下的部分,我們用drop函數移除訓練集的部分,剩下的部分自然就是測試集,並用變量保存起來。

train_dataset = dataset.sample(frac=0.8,random_state=0) #分割80%訓練集,取不重複的數據
test_dataset = dataset.drop(train_dataset.index) #分割20測試集

5.用seaborn庫畫圖,將指定變量的圖畫出,diag_kind='kde'爲圖的設定,若是單變量圖(自己和自己比較)則是線性圖,若是不同變量比較則爲散點圖。

sns.pairplot(train_dataset[["MPG", "Cylinders", "Displacement", "Weight"]], diag_kind="kde")

6.我們可以用describe函數來查看數據集更詳細的查看一些數據集的參數,這樣我們就不用自己調用函數計算了。

train_stats = train_dataset.describe() #查看數據統計的參數值
train_stats.pop("MPG") #刪除燃油效率特徵,因爲是標籤
train_stats = train_stats.transpose() #行列轉置顯示
train_stats

7.因爲我們預測是燃油效率,因此需要將MPG(燃油效率)從數據集中取出作爲標籤。

train_labels = train_dataset.pop('MPG') #從數據集刪除並保存成變量作爲標籤
test_labels = test_dataset.pop('MPG')

8.數據歸一化,歸一化的作用就不反覆再提了,前幾節有說到。

def norm(x):
    return (x - train_stats['mean']) / train_stats['std']
normed_train_data = norm(train_dataset) #對訓練集進行歸一化
normed_test_data = norm(test_dataset) #對測試集進行歸一化

9.顯示歸一化後的數據。

print(normed_train_data)

三.模型建立

1.我們直接模型的層搭建和優化器部分包裝成一個函數。這裏注意的是層的最後一層不用激活函數,因爲我們做的是線性迴歸預測是具體數值,不是分類概率,輸入的特徵dim爲9,如上圖所示有9個特徵,優化器使用RMSprop,學習率選擇爲0.001,損失函數選擇爲mse(mean-square error   均方誤差)。度量的參數爲mae(絕對值誤差)和mse(均方誤差)的loss。

def build_model():
    model = keras.Sequential([
    layers.Dense(64, activation='relu',input_dim=9),
    layers.Dense(64, activation='relu'),
    layers.Dense(1)
  ])

    optimizer = tf.keras.optimizers.RMSprop(0.001) #優化器

    model.compile(loss='mse',                      #模型設置
                optimizer=optimizer,
                metrics=['mae', 'mse'])
    return model

model = build_model()

2.打印模型概要。

model.summary()

3.在未訓練前,送入一些數據到模型中預測,看看結果。

example_batch = normed_train_data[:10] #取前10個數據
example_result = model.predict(example_batch) #預測
example_result

四.模型訓練

1.訓練模型。

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

2.這裏我們可以用pandas將訓練的記錄保存起來,幫助更方便地顯示並且我們還可以在上面添加一些其它參數如訓練次數等。

hist = pd.DataFrame(history.history)
hist['epoch'] = history.epoch #添加訓練次數列
hist.tail() #顯示後5行

3.定義訓練過程顯示函數,將訓練過程可視化爲圖。這裏我們不採用官方教程的代碼,而是用我們之前幾節所寫的函數,更簡介一些,具體參數意思可參照前幾節內容。

def show_train_history(train_history,epoch,train,validation,y_limit):
    plt.plot(epoch,train_history.history[train]) 
    plt.plot(epoch,train_history.history[validation])
    plt.title('Train History')
    plt.xlabel('epoch')
    plt.ylabel(train)
    plt.ylim(y_limit) #限制顯示的y的大小
    plt.legend(['train','validation'],loc='upper left')
show_train_history(history,hist['epoch'],'mae','val_mae',[0,5])
show_train_history(history,hist['epoch'],'mse','val_mse',[0,20])

4.從訓練數據上看,結果到了後面越來越糟糕,那我是否有辦法在訓練結果變糟糕之前提取停止訓練呢?這邊有一個函數爲EarlyStopping,意思爲提早停止。其中monitor參數爲我們要監督的參數,patience爲可以忍受結果變壞的訓練次數。這裏代碼的意思就是我們監督val_loss這個值,當它的結果連續變壞10次,我們則就停止訓練。之後我們將這個值作爲callback傳入訓練模型中,重新進行訓練。

model=build_model()
early_stop = keras.callbacks.EarlyStopping(monitor='val_loss',patience=10) #提早停止訓練
history = model.fit(normed_train_data,train_labels,epochs=1000,validation_split=0.2,verbose=2,callbacks=[early_stop]) #模型訓練
plot_history(history)

我們可以觀察到訓練次數在77次就停止了。

五.模型測試和預測

1.模型測試集測試。

loss, mae, mse = model.evaluate(normed_test_data, test_labels, verbose=2) #測試
print("Testing set Mean Abs Error: {:5.2f} MPG".format(mae))

2.模型預測,並畫圖顯示。這裏離散圖的意思爲標籤和預測值的偏離,如果我們的預測值和標籤相等,則會像圖中的直線一樣,否則就會偏離這條直線,如其中離散點所示。

test_predictions = model.predict(normed_test_data).flatten() #轉一維
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]) #畫直線

3.計算標籤和預測值的loss差,並用直方圖顯示,其中bins代表直方圖的頻數。

error= test_predictions-test_labels
plt.hist(error,bins=25) #直方圖顯示
plt.xlabel("Prediction Error [MPG]")
_ = plt.ylabel("Count")

 

以上就是本節的內容,這一節我對官方的代碼進行了比較詳細的解釋,相信大家看完之後應該可以更直觀的理解源代碼的意思了,謝謝你們的觀看和支持!

 

 

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