最全TensorFlow2.0學(xué)習(xí)路線 www.mashangxue123.com
在回歸問題中,我們的目標(biāo)是預(yù)測連續(xù)值的輸出蕴茴,如價格或概率。
將此與分類問題進(jìn)行對比,分類的目標(biāo)是從類列表中選擇一個類(例如奥喻,圖片包含蘋果或橙色,識別圖片中的哪個水果)非迹。
本章節(jié)采用了經(jīng)典的Auto MPG 數(shù)據(jù)集环鲤,并建立了一個模型來預(yù)測20世紀(jì)70年代末和80年代初汽車的燃油效率。為此憎兽,我們將為該模型提供該時段內(nèi)許多汽車的描述冷离,此描述包括以下屬性:氣缸,排量纯命,馬力和重量西剥。
此實例使用tf.keras API,有關(guān)信息信息扎附,請參閱Keras指南蔫耽。
# 使用seaborn進(jìn)行pairplot數(shù)據(jù)可視化,安裝命令
pip install 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
# tensorflow2 安裝命令 pip install tensorflow==2.0.0-alpha0
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
print(tf.__version__)
1. Auto MPG數(shù)據(jù)集
該數(shù)據(jù)集可從UCI機器學(xué)習(xí)庫獲得。
1.1. 獲取數(shù)據(jù)
首先下載數(shù)據(jù)集:
dataset_path = keras.utils.get_file("auto-mpg.data", "http://archive.ics.uci.edu/ml/machine-learning-databases/auto-mpg/auto-mpg.data")
dataset_path
用pandas導(dǎo)入數(shù)據(jù)
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()
MPG | Cylinders | Displacement | Horsepower | Weight | Acceleration | Model Year | Origin | |
---|---|---|---|---|---|---|---|---|
393 | 27.0 | 4 | 140.0 | 86.0 | 2790.0 | 15.6 | 82 | 1 |
394 | 44.0 | 4 | 97.0 | 52.0 | 2130.0 | 24.6 | 82 | 2 |
395 | 32.0 | 4 | 135.0 | 84.0 | 2295.0 | 11.6 | 82 | 1 |
396 | 28.0 | 4 | 120.0 | 79.0 | 2625.0 | 18.6 | 82 | 1 |
397 | 31.0 | 4 | 119.0 | 82.0 | 2720.0 | 19.4 | 82 | 1 |
1.2. 清理數(shù)據(jù)
數(shù)據(jù)集包含一些未知值
dataset.isna().sum()
MPG 0
Cylinders 0
Displacement 0
Horsepower 6
Weight 0
Acceleration 0
Model Year 0
Origin 0
dtype: int64
這是一個入門教程匙铡,所以我們就簡單地刪除這些行图甜。
dataset = dataset.dropna()
“Origin”這一列實際上是分類,而不是數(shù)字鳖眼。 所以把它轉(zhuǎn)換為獨熱編碼:
origin = dataset.pop('Origin')
dataset['USA'] = (origin == 1)*1.0
dataset['Europe'] = (origin == 2)*1.0
dataset['Japan'] = (origin == 3)*1.0
dataset.tail()
MPG | Cylinders | Displacement | Horsepower | Weight | Acceleration | Model Year | USA | Europe | Japan | |
---|---|---|---|---|---|---|---|---|---|---|
393 | 27.0 | 4 | 140.0 | 86.0 | 2790.0 | 15.6 | 82 | 1.0 | 0.0 | 0.0 |
394 | 44.0 | 4 | 97.0 | 52.0 | 2130.0 | 24.6 | 82 | 0.0 | 1.0 | 0.0 |
395 | 32.0 | 4 | 135.0 | 84.0 | 2295.0 | 11.6 | 82 | 1.0 | 0.0 | 0.0 |
396 | 28.0 | 4 | 120.0 | 79.0 | 2625.0 | 18.6 | 82 | 1.0 | 0.0 | 0.0 |
397 | 31.0 | 4 | 119.0 | 82.0 | 2720.0 | 19.4 | 82 | 1.0 | 0.0 | 0.0 |
1.3. 將數(shù)據(jù)分為訓(xùn)練集和測試集
現(xiàn)在將數(shù)據(jù)集拆分為訓(xùn)練集和測試集黑毅,我們將在模型的最終評估中使用測試集。
train_dataset = dataset.sample(frac=0.8,random_state=0)
test_dataset = dataset.drop(train_dataset.index)
1.4. 檢查數(shù)據(jù)
快速瀏覽訓(xùn)練集中幾對列的聯(lián)合分布:
sns.pairplot(train_dataset[["MPG", "Cylinders", "Displacement", "Weight"]], diag_kind="kde")
另外查看整體統(tǒng)計數(shù)據(jù):
train_stats = train_dataset.describe()
train_stats.pop("MPG")
train_stats = train_stats.transpose()
train_stats
count | mean | std | min | 25% | 50% | 75% | max | |
---|---|---|---|---|---|---|---|---|
Cylinders | 314.0 | 5.477707 | 1.699788 | 3.0 | 4.00 | 4.0 | 8.00 | 8.0 |
Displacement | 314.0 | 195.318471 | 104.331589 | 68.0 | 105.50 | 151.0 | 265.75 | 455.0 |
Horsepower | 314.0 | 104.869427 | 38.096214 | 46.0 | 76.25 | 94.5 | 128.00 | 225.0 |
Weight | 314.0 | 2990.251592 | 843.898596 | 1649.0 | 2256.50 | 2822.5 | 3608.00 | 5140.0 |
Acceleration | 314.0 | 15.559236 | 2.789230 | 8.0 | 13.80 | 15.5 | 17.20 | 24.8 |
Model Year | 314.0 | 75.898089 | 3.675642 | 70.0 | 73.00 | 76.0 | 79.00 | 82.0 |
USA | 314.0 | 0.624204 | 0.485101 | 0.0 | 0.00 | 1.0 | 1.00 | 1.0 |
Europe | 314.0 | 0.178344 | 0.383413 | 0.0 | 0.00 | 0.0 | 0.00 | 1.0 |
Japan | 314.0 | 0.197452 | 0.398712 | 0.0 | 0.00 | 0.0 | 0.00 | 1.0 |
1.5. 從標(biāo)簽中分割特征
將目標(biāo)值或“標(biāo)簽”與特征分開钦讳,此標(biāo)簽是您訓(xùn)練的模型進(jìn)行預(yù)測的值:
train_labels = train_dataset.pop('MPG')
test_labels = test_dataset.pop('MPG')
1.6. 標(biāo)準(zhǔn)化數(shù)據(jù)
再看一下上面的train_stats
塊矿瘦,注意每個特征的范圍有多么不同。
使用不同的比例和范圍對特征進(jìn)行標(biāo)準(zhǔn)化是一個很好的實踐愿卒,雖然模型可能在沒有特征標(biāo)準(zhǔn)化的情況下收斂缚去,但它使訓(xùn)練更加困難,并且它使得最終模型取決于輸入中使用的單位的選擇琼开。
注意:盡管我們僅從訓(xùn)練數(shù)據(jù)集中有意生成這些統(tǒng)計信息易结,但這些統(tǒng)計信息也將用于標(biāo)準(zhǔn)化測試數(shù)據(jù)集。我們需要這樣做柜候,將測試數(shù)據(jù)集投影到模型已經(jīng)訓(xùn)練過的相同分布中搞动。
def norm(x):
return (x - train_stats['mean']) / train_stats['std']
normed_train_data = norm(train_dataset)
normed_test_data = norm(test_dataset)
這個標(biāo)準(zhǔn)化數(shù)據(jù)是我們用來訓(xùn)練模型的數(shù)據(jù)。
注意:用于標(biāo)準(zhǔn)化輸入的統(tǒng)計數(shù)據(jù)(平均值和標(biāo)準(zhǔn)偏差)需要應(yīng)用于輸入模型的任何其他數(shù)據(jù)渣刷,以及我們之前執(zhí)行的獨熱編碼鹦肿。這包括測試集以及模型在生產(chǎn)中使用時的實時數(shù)據(jù)。
2. 模型
2.1. 構(gòu)建模型
讓我們建立我們的模型辅柴。在這里箩溃,我們將使用具有兩個密集連接隱藏層的Sequential
模型,以及返回單個連續(xù)值的輸出層碌识。模型構(gòu)建步驟包含在函數(shù)build_model
中碾篡,因為我們稍后將創(chuàng)建第二個模型。
def build_model():
model = keras.Sequential([
layers.Dense(64, activation='relu', input_shape=[len(train_dataset.keys())]),
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.2. 檢查模型
使用.summary
方法打印模型的簡單描述
model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense (Dense) (None, 64) 640
_________________________________________________________________
dense_1 (Dense) (None, 64) 4160
_________________________________________________________________
dense_2 (Dense) (None, 1) 65
=================================================================
Total params: 4,865
Trainable params: 4,865
Non-trainable params: 0
_________________________________________________________________
現(xiàn)在試試這個模型筏餐。從訓(xùn)練數(shù)據(jù)中取出一批10個樣本數(shù)據(jù)并在調(diào)用model.predict
函數(shù)。
example_batch = normed_train_data[:10]
example_result = model.predict(example_batch)
example_result
array([[ 0.3297699 ],
[ 0.25655937],
[-0.12460149],
[ 0.32495883],
[ 0.50459725],
[ 0.10887371],
[ 0.57305855],
[ 0.57637435],
[ 0.12094647],
[ 0.6864784 ]], dtype=float32)
這似乎可以工作牡拇,它產(chǎn)生預(yù)期的shape和類型的結(jié)果魁瞪。
2.3. 訓(xùn)練模型
訓(xùn)練模型1000個周期,并在history
對象中記錄訓(xùn)練和驗證準(zhǔn)確性:
# 通過為每個完成的周期打印單個點來顯示訓(xùn)練進(jìn)度
class PrintDot(keras.callbacks.Callback):
def on_epoch_end(self, epoch, logs):
if epoch % 100 == 0: print('')
print('.', end='')
EPOCHS = 1000
history = model.fit(
normed_train_data, train_labels,
epochs=EPOCHS, validation_split = 0.2, verbose=0,
callbacks=[PrintDot()])
使用存儲在history
對象中的統(tǒng)計數(shù)據(jù)可視化模型的訓(xùn)練進(jìn)度惠呼。300
hist = pd.DataFrame(history.history)
hist['epoch'] = history.epoch
hist.tail()
loss | mae | mse | val_loss | val_mae | val_mse | epoch | |
---|---|---|---|---|---|---|---|
995 | 2.556746 | 0.988013 | 2.556746 | 10.210531 | 2.324411 | 10.210530 | 995 |
996 | 2.597973 | 1.039339 | 2.597973 | 11.257273 | 2.469266 | 11.257273 | 996 |
997 | 2.671929 | 1.040886 | 2.671929 | 10.604957 | 2.446257 | 10.604958 | 997 |
998 | 2.634858 | 1.001898 | 2.634858 | 10.906935 | 2.373279 | 10.906935 | 998 |
999 | 2.741717 | 1.035889 | 2.741717 | 10.698320 | 2.342703 | 10.698319 | 999 |
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)
該圖表顯示在約100個周期之后导俘,驗證誤差幾乎沒有改進(jìn),甚至降低剔蹋。讓我們更新model.fit
調(diào)用旅薄,以便在驗證分?jǐn)?shù)沒有提高時自動停止訓(xùn)練。我們將使用EarlyStopping
回調(diào)來測試每個周期的訓(xùn)練狀態(tài)。如果經(jīng)過一定數(shù)量的周期而沒有顯示出改進(jìn)少梁,則自動停止訓(xùn)練洛口。
您可以了解此回調(diào)的更多信息 連接.
model = build_model()
# “patience”參數(shù)是檢查改進(jìn)的周期量
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=0, callbacks=[early_stop, PrintDot()])
plot_history(history)
上圖顯示在驗證集上平均誤差通常約為+/-2MPG,這個好嗎凯沪?我們會把這個決定留給你第焰。
讓我們看一下使用測試集來看一下泛化模型效果,我們在訓(xùn)練模型時沒有使用測試集妨马,這告訴我們挺举,當(dāng)我們在現(xiàn)實世界中使用模型時,我們可以期待模型預(yù)測烘跺。
loss, mae, mse = model.evaluate(normed_test_data, test_labels, verbose=0)
print("Testing set Mean Abs Error: {:5.2f} MPG".format(mae))
Testing set Mean Abs Error: 2.09 MPG
2.4. 預(yù)測
最后湘纵,使用測試集中的數(shù)據(jù)預(yù)測MPG值:
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])
看起來我們的模型預(yù)測得相當(dāng)好,我們來看看錯誤分布:
error = test_predictions - test_labels
plt.hist(error, bins = 25)
plt.xlabel("Prediction Error [MPG]")
_ = plt.ylabel("Count")
上圖看起來不是很高斯(正態(tài)分布)滤淳,很可能是因為樣本數(shù)據(jù)非常少梧喷。
3. 結(jié)論
本章節(jié)介紹了一些處理回歸問題的技巧:
均方誤差(MSE)是用于回歸問題的常見損失函數(shù)(不同的損失函數(shù)用于分類問題)。
同樣娇钱,用于回歸的評估指標(biāo)與分類不同伤柄,常見的回歸度量是平均絕對誤差(MAE)。
當(dāng)數(shù)字輸入數(shù)據(jù)特征具有不同范圍的值時文搂,應(yīng)將每個特征獨立地縮放到相同范圍适刀。
如果沒有太多訓(xùn)練數(shù)據(jù),應(yīng)選擇隱藏層很少的小網(wǎng)絡(luò)煤蹭,以避免過擬合笔喉。
盡早停止是防止過擬合的有效技巧。
最新版本:https://www.mashangxue123.com/tensorflow/tf2-tutorials-keras-basic_regression.html
英文版本:https://tensorflow.google.cn/alpha/tutorials/keras/basic_regression
最全TensorFlow2.0學(xué)習(xí)路線 www.mashangxue123.com