目录
Basic regression: Predict fuel efficiency
我们将会使用这个已经归一化的数据来训练模型。
警告: 用于归一化输入的数据统计(均值和标准差)需要反馈给模型从而应用于任何其他数据,以及我们之前所获得独热码。这些数据包含测试数据集以及生产环境中所使用的实时数据。
Basic regression: Predict fuel efficiency
基本回归:预测燃油效率
# Use seaborn for pairplot.使用 seaborn 绘制矩阵图 (pairplot)
!pip install -q seaborn
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
# Make NumPy printouts easier to read.使NumPy打印输出更易于阅读。
np.set_printoptions(precision=3, suppress=True)
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
print(tf.__version__)
#2.9.2
Auto MPG 数据集
获取数据
url = 'http://archive.ics.uci.edu/ml/machine-learning-databases/auto-mpg/auto-mpg.data'
column_names = ['MPG', 'Cylinders', 'Displacement', 'Horsepower', 'Weight',
'Acceleration', 'Model Year', 'Origin']
#列名:“MPG”、“气缸”、“排量”、“马力”、“重量”、“加速”、“车型年份”、“原产地”。
#使用 pandas 导入数据集。
raw_dataset = pd.read_csv(url,
names=column_names,
na_values='?',
comment='\t',
sep=' ',
skipinitialspace=True)
dataset = raw_dataset.copy()
dataset.tail()#显示数据集部分数据集。tail()的意思是显示数据后5行的内容。
使用 pandas 导入数据集。
#pandas用来读入数据.url是导入的地址,names指定列的名称以列表表示。
#原数据中有数据缺失为?,na_values='?'可以将?标明为NAN(未知值)。
#comment='\t'的意思是忽略以\t(一个制表符)开头后的行内容,这部分内容不读入。
#sep=' '的意思是将数据中有空白的部分当作分隔符,用来分割不同列的数据。(指定分隔符,默认为逗号’,’)
#skipinitialspace=True的意思则是忽略分隔符后的空白。
![](https://img-blog.csdnimg.cn/dff345e72430475e9c8ca2ddd53edc09.png)
数据清洗
数据集包含一些未知值:
dataset.isna().sum()
#显示为空值(NAN)的特征类别和数目。
#为了保证此初始教程简单,请删除这些行:
dataset = dataset.dropna()
#处理这些缺省值,处理缺省值的方式有很多种,比如去掉,取中位数,平均值等等。这里选取的是去掉。
#因为空值数据不多,因此我们直接用dropna()函数删除这些数据。
"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()
将数据拆分为训练集和测试集
现在,将数据集拆分为训练集和测试集。您将在模型的最终评估中使用测试集。
#采用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测试集
数据检查
检查训练集中几对列的联合分布。第一行表明燃油效率 (MPG) 是所有其他参数的函数。其他行表示它们是彼此的函数
sns.pairplot(train_dataset[['MPG', 'Cylinders', 'Displacement', 'Weight']], diag_kind='kde')
#diag_kind='kde'为图的设定,若是单变量图(自己和自己比较)则是线性图,若是不同变量比较则为散点图。
也可以查看总体的数据统计:
train_stats = train_dataset.describe()#.describe()查看数据统计的参数值
train_stats.pop("MPG")
train_stats = train_stats.transpose()#.transpose()行列转置显示
train_stats
从标签中分离特征
将特征值从目标值或者"标签"中分离。 这个标签是你使用训练模型进行预测的值。
train_labels = train_dataset.pop('MPG')
test_labels = test_dataset.pop('MPG')
数据规范化
再次审视下上面的 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)
我们将会使用这个已经归一化的数据来训练模型。
警告: 用于归一化输入的数据统计(均值和标准差)需要反馈给模型从而应用于任何其他数据,以及我们之前所获得独热码。这些数据包含测试数据集以及生产环境中所使用的实时数据。
模型
构建模型
让我们来构建我们自己的模型。这里,我们将会使用一个“顺序”模型,其中包含两个紧密相连的隐藏层,以及返回单个、连续值得输出层。模型的构建步骤包含于一个名叫 'build_model' 的函数中,稍后我们将会创建第二个模型。 两个密集连接的隐藏层。
- 均方误差(MSE)是用于回归问题的常见损失函数(分类问题中使用不同的损失函数)。
- 类似的,用于回归的评估指标与分类不同。 常见的回归指标是平均绝对误差(MAE)。
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)
])
#优化器使用RMSprop,学习率选择为0.001,
optimizer = tf.keras.optimizers.RMSprop(0.001)
#模型设置
model.compile(loss='mse', #损失函数选择为mse(mean-square error均方误差)
optimizer=optimizer,
metrics=['mae', 'mse']) #度量的参数为mae(绝对值误差)和mse(均方误差)的loss
return model
model = build_model()
#检查模型 打印模型概要
model.summary()
现在试用下这个模型。从训练数据中批量获取‘10’条例子并对这些例子调用 model.predict
。
example_batch = normed_train_data[:10]#取前10个数据
example_result = model.predict(example_batch)#预测
example_result
训练模型
对模型进行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 = model.fit(
normed_train_data, train_labels,
epochs=1000, validation_split = 0.2, verbose=2)
参考于Tensorflow2.0学习(六) — 线性回归模型(燃油效率预测)_Yohann、的博客-CSDN博客
使用
history
对象中存储的统计信息可视化模型的训练进度。
该图表显示在约100个 epochs 之后误差非但没有改进,反而出现恶化。 让我们更新 model.fit
调用,当验证值没有提高上是自动停止训练。 我们将使用一个 EarlyStopping callback 来测试每个 epoch 的训练条件。如果经过一定数量的 epochs 后没有改进,则自动停止训练。
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个 epochs 之后误差非但没有改进,反而出现恶化。 让我们更新 model.fit
调用,当验证值没有提高上是自动停止训练。 我们将使用一个 EarlyStopping callback 来测试每个 epoch 的训练条件。如果经过一定数量的 epochs 后没有改进,则自动停止训练。
model = build_model()
# 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=0, callbacks=[early_stop, PrintDot()])
plot_history(history)
如图所示,验证集中的平均的误差通常在 +/- 2 MPG左右。 这个结果好么? 我们将决定权留给你。
让我们看看通过使用 测试集 来泛化模型的效果如何,我们在训练模型时没有使用测试集。这告诉我们,当我们在现实世界中使用这个模型时,我们可以期望它预测得有多好。
loss, mae, mse = model.evaluate(normed_test_data, test_labels, verbose=2)
print("Testing set Mean Abs Error: {:5.2f} MPG".format(mae))
做预测
最后,使用测试集中的数据预测 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])
这看起来我们的模型预测得相当好。我们来看下误差分布。
error = test_predictions - test_labels
plt.hist(error, bins = 25)
plt.xlabel("Prediction Error [MPG]")
_ = plt.ylabel("Count")
结论
本笔记本 (notebook) 介绍了一些处理回归问题的技术。
- 均方误差(MSE)是用于回归问题的常见损失函数(分类问题中使用不同的损失函数)。
- 类似的,用于回归的评估指标与分类不同。 常见的回归指标是平均绝对误差(MAE)。
- 当数字输入数据特征的值存在不同范围时,每个特征应独立缩放到相同范围。
- 如果训练数据不多,一种方法是选择隐藏层较少的小网络,以避免过度拟合。
- 早期停止是一种防止过度拟合的有效技术。