回归项目实战:预测燃油效率 (tensorflow2.0官方教程翻译)

本教程采用AutoMPG数据集,演示如何使用TensorFlow2.0和Keras API构建模型,预测汽车燃油效率。涵盖数据预处理、特征标准化、模型构建、训练及评估全过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最全TensorFlow2.0学习路线 www.mashangxue123.com

回归问题中,我们的目标是预测连续值的输出,如价格或概率。
将此与分类问题进行对比,分类的目标是从类列表中选择一个类(例如,图片包含苹果或橙色,识别图片中的哪个水果)。

本章节采用了经典的Auto MPG 数据集,并建立了一个模型来预测20世纪70年代末和80年代初汽车的燃油效率。为此,我们将为该模型提供该时段内许多汽车的描述,此描述包括以下属性:气缸,排量,马力和重量。

此实例使用tf.keras API,有关信息信息,请参阅Keras指南

# 使用seaborn进行pairplot数据可视化,安装命令
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数据集

该数据集可从UCI机器学习库获得。

1.1. 获取数据

首先下载数据集:

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导入数据

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()
MPGCylindersDisplacementHorsepowerWeightAccelerationModel YearOrigin
39327.04140.086.02790.015.6821
39444.0497.052.02130.024.6822
39532.04135.084.02295.011.6821
39628.04120.079.02625.018.6821
39731.04119.082.02720.019.4821

1.2. 清理数据

数据集包含一些未知值

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”这一列实际上是分类,而不是数字。 所以把它转换为独热编码:

origin = dataset.pop('Origin')
dataset['USA'] = (origin == 1)*1.0
dataset['Europe'] = (origin == 2)*1.0
dataset['Japan'] = (origin == 3)*1.0
dataset.tail()
MPGCylindersDisplacementHorsepowerWeightAccelerationModel YearUSAEuropeJapan
39327.04140.086.02790.015.6821.00.00.0
39444.0497.052.02130.024.6820.01.00.0
39532.04135.084.02295.011.6821.00.00.0
39628.04120.079.02625.018.6821.00.00.0
39731.04119.082.02720.019.4821.00.00.0

1.3. 将数据分为训练集和测试集

现在将数据集拆分为训练集和测试集,我们将在模型的最终评估中使用测试集。

train_dataset = dataset.sample(frac=0.8,random_state=0)
test_dataset = dataset.drop(train_dataset.index)

1.4. 检查数据

快速浏览训练集中几对列的联合分布:

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

png

另外查看整体统计数据:

train_stats = train_dataset.describe()
train_stats.pop("MPG")
train_stats = train_stats.transpose()
train_stats
countmeanstdmin25%50%75%max
Cylinders314.05.4777071.6997883.04.004.08.008.0
Displacement314.0195.318471104.33158968.0105.50151.0265.75455.0
Horsepower314.0104.86942738.09621446.076.2594.5128.00225.0
Weight314.02990.251592843.8985961649.02256.502822.53608.005140.0
Acceleration314.015.5592362.7892308.013.8015.517.2024.8
Model Year314.075.8980893.67564270.073.0076.079.0082.0
USA314.00.6242040.4851010.00.001.01.001.0
Europe314.00.1783440.3834130.00.000.00.001.0
Japan314.00.1974520.3987120.00.000.00.001.0

1.5. 从标签中分割特征

将目标值或“标签”与特征分开,此标签是您训练的模型进行预测的值:

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

1.6. 标准化数据

再看一下上面的train_stats块,注意每个特征的范围有多么不同。

使用不同的比例和范围对特征进行标准化是一个很好的实践,虽然模型可能在没有特征标准化的情况下收敛,但它使训练更加困难,并且它使得最终模型取决于输入中使用的单位的选择。

注意:尽管我们仅从训练数据集中有意生成这些统计信息,但这些统计信息也将用于标准化测试数据集。我们需要这样做,将测试数据集投影到模型已经训练过的相同分布中。

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

这个标准化数据是我们用来训练模型的数据。

注意:用于标准化输入的统计数据(平均值和标准偏差)需要应用于输入模型的任何其他数据,以及我们之前执行的独热编码。这包括测试集以及模型在生产中使用时的实时数据。

2. 模型

2.1. 构建模型

让我们建立我们的模型。在这里,我们将使用具有两个密集连接隐藏层的Sequential模型,以及返回单个连续值的输出层。模型构建步骤包含在函数build_model中,因为我们稍后将创建第二个模型。

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
_________________________________________________________________

现在试试这个模型。从训练数据中取出一批10个样本数据并在调用model.predict函数。

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)

这似乎可以工作,它产生预期的shape和类型的结果。

2.3. 训练模型

训练模型1000个周期,并在history对象中记录训练和验证准确性:

# 通过为每个完成的周期打印单个点来显示训练进度 
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对象中的统计数据可视化模型的训练进度。300

hist = pd.DataFrame(history.history)
hist['epoch'] = history.epoch
hist.tail()
lossmaemseval_lossval_maeval_mseepoch
9952.5567460.9880132.55674610.2105312.32441110.210530995
9962.5979731.0393392.59797311.2572732.46926611.257273996
9972.6719291.0408862.67192910.6049572.44625710.604958997
9982.6348581.0018982.63485810.9069352.37327910.906935998
9992.7417171.0358892.74171710.6983202.34270310.698319999
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)

png

png

该图表显示在约100个周期之后,验证误差几乎没有改进,甚至降低。让我们更新model.fit调用,以便在验证分数没有提高时自动停止训练。我们将使用EarlyStopping回调来测试每个周期的训练状态。如果经过一定数量的周期而没有显示出改进,则自动停止训练。

您可以了解此回调的更多信息 连接.

model = build_model()

# “patience”参数是检查改进的周期量 
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)

png

png

上图显示在验证集上平均误差通常约为+/-2MPG,这个好吗?我们会把这个决定留给你。

让我们看一下使用测试集来看一下泛化模型效果,我们在训练模型时没有使用测试集,这告诉我们,当我们在现实世界中使用模型时,我们可以期待模型预测。

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. 预测

最后,使用测试集中的数据预测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])

png

看起来我们的模型预测得相当好,我们来看看错误分布:

error = test_predictions - test_labels
plt.hist(error, bins = 25)
plt.xlabel("Prediction Error [MPG]")
_ = plt.ylabel("Count")

png

上图看起来不是很高斯(正态分布),很可能是因为样本数据非常少。

3. 结论

本章节介绍了一些处理回归问题的技巧:

  • 均方误差(MSE)是用于回归问题的常见损失函数(不同的损失函数用于分类问题)。

  • 同样,用于回归的评估指标与分类不同,常见的回归度量是平均绝对误差(MAE)。

  • 当数字输入数据特征具有不同范围的值时,应将每个特征独立地缩放到相同范围。

  • 如果没有太多训练数据,应选择隐藏层很少的小网络,以避免过拟合。

  • 尽早停止是防止过拟合的有效技巧。

最新版本:https://www.mashangxue123.com/tensorflow/tf2-tutorials-keras-basic_regression.html
英文版本:https://tensorflow.google.cn/alpha/tutorials/keras/basic_regression
最全TensorFlow2.0学习路线 www.mashangxue123.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值