<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Copyright 2018 The TensorFlow Authors.
Step1:  Basic regression
Step2:  Auto MPG 数据集
该数据集可以从 UCI机器学习库 中获取.
获取数据
首先下载数据集。
Step3:  数据清洗
数据集中包括一些未知值。
Step4:  为了保证这个初始示例的简单性，删除这些行。
Step5:  "Origin" 列实际上是分类的，而不是数字。因此，使用 pd.get_dummies 将其转换为独热码：
注：您可以设置 keras.Model 来为您执行这种转换。这超出了本教程的范围。有关示例，请参阅预处理层或加载 CSV 数据教程。
Step6:  拆分训练数据集和测试数据集
现在需要将数据集拆分为一个训练数据集和一个测试数据集。
在我们模型的最终评估中使用测试集。
Step7:  数据检查
快速查看训练集中几对列的联合分布。
查看顶行，应当清楚燃油效率 (MPG) 是所有其他参数的函数。查看其他行，应当清楚它们是彼此的函数。
Step8:  也可以查看总体的数据统计
Step9:  从标签中分离特征
将特征值从目标值或者"标签"中分离。 这个标签是你使用训练模型进行预测的值。
Step10:  归一化
再次审视下上面的 train_stats 部分，并注意每个特征的范围有什么不同。
Step11:  使用不同的尺度和范围对特征归一化是好的实践。尽管模型可能 在没有特征归一化的情况下收敛，它会使得模型训练更加复杂，并会造成生成的模型依赖输入所使用的单位选择。
注意：尽管我们仅仅从训练集中有意生成这些统计数据，但是这些统计信息也会用于归一化的测试数据集。我们需要这样做，将测试数据集放入到与已经训练过的模型相同的分布中。
尽管模型可能在没有特征归一化的情况下收敛，但归一化会使训练更加稳定。
注：归一化独热特征没有任何好处，这里这样做是为了简单起见。有关如何使用预处理层的更多详细信息，请参阅使用预处理层指南和使用 Keras 预处理层对结构化数据进行分类教程。
归一化层
preprocessing.Normalization 层是一种将预处理构建到模型中的简洁且简单的方法。
第一步是创建层：
Step12:  然后对其执行 .adapt() 以适应数据：
Step13:  这将计算均值和方差，并将它们存储在层中。
Step14:  当层被调用时，它会返回输入数据，每个特征独立归一化：
Step15:  线性回归
在构建 DNN 模型之前，先从线性回归开始。
一个变量
从单变量线性回归开始，根据 Horsepower 预测 MPG。
使用 tf.keras 训练模型通常从定义模型架构开始。
在这种情况下，使用 keras.Sequential 模型。此模型代表了一系列步骤。在这种情况下，有两个步骤：
将输入 horsepower 归一化。
应用线性变换 ($y = mx+b$) 以使用 layers.Dense 产生 1 个输出。
输入的数量可以由 input_shape 参数设置，也可以在模型第一次运行时自动设置。
首先创建马力 Normalization 层：
Step16:  构建序贯模型：
Step17:  此模型将根据 Horsepower 预测 MPG。
在前 10 个马力值上运行未经训练的模型。输出不会很好，但您会看到它具有预期的形状 (10,1)：
Step18:  构建模型后，使用 Model.compile() 方法配置训练过程。要编译的最重要参数是 loss 和 optimizer，因为它们定义了将要优化的内容 (mean_absolute_error) 以及优化的方法（使用 optimizers.Adam）。
Step19:  训练配置完成后，使用 Model.fit() 执行训练：
Step20:  使用 history 对象中存储的统计信息可视化模型的训练进度。
Step21:  收集测试集上的结果，以便稍后使用：
Step22:  由于这是一个单变量回归，因此很容易将模型的预测视为输入的函数：
Step23:  多个输入
您可以使用几乎相同的设置根据多个输入进行预测。此模型仍然执行相同的 $y = mx+b$，只是 $m$ 是一个矩阵而 $b$ 是一个向量。
这次使用适应整个数据集的 Normalization 层。
Step24:  当您对一批输入调用此模型时，它会为每个样本生成 units=1 输出。
Step25:  当您调用模型时，将构建其权重矩阵。现在，您可以看到 kernel（$y=mx+b$ 中的 $m$）的形状为 (9,1)。
Step26:  使用与单输入 horsepower 模型相同的 compile 和 fit 调用：
Step27:  使用所有输入可以实现比 horsepower 模型低得多的训练和验证误差：
Step28:  收集测试集上的结果，以便稍后使用：
Step29:  模型
上一部分为单输入和多输入实现了线性模型。
本部分实现单输入和多输入 DNN 模型。除了将模型扩展为包括一些“隐藏”非线性层之外，代码基本相同。此处的名称“隐藏”仅表示不直接连接到输入或输出。
这些模型包含的层比线性模型多一些：
归一化层。
使用 relu 非线性的两个隐藏非线性 Dense 层。
线性单输出层。
两者都将使用相同的训练过程，因此 compile 方法包含在下面的 build_and_compile_model 函数中。
Step30:  一个变量
从单个输入的 DNN 模型开始：“马力”
Step31:  使用 .summary 方法来打印该模型的简单描述。
Step32:  对模型进行1000个周期的训练，并在 history 对象中记录训练和验证的准确性。
Step33:  此模型略优于线性马力模型。
Step34:  如果您将预测值绘制为 Horsepower 的函数，则将看到此模型如何利用隐藏层提供的非线性：
Step35:  收集测试集上的结果，以便稍后使用：
Step36:  完整模型
如果您使用所有输入重复此过程，则它会略微提高验证数据集的性能。
Step37:  收集测试集上的结果：
Step38:  性能
现在，所有模型都经过训练，检查测试集的性能，看看它们的表现如何：
Step39:  这些结果与训练期间看到的验证误差相匹配。
做预测
最后，使用测试集中的数据预测 MPG 值
Step40:  看起来模型预测得相当出色。
现在，看一下误差分布：
Step41:  如果您对模型感到满意，请将其保存以备以后使用：
Step42:  如果您重新加载模型，它会给出相同的输出：
<ASSISTANT_TASK:>
Python Code:
#@title Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#@title MIT License
#
# Copyright (c) 2017 François Chollet
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
Explanation: Copyright 2018 The TensorFlow Authors.
End of explanation
# Use seaborn for 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.
np.set_printoptions(precision=3, suppress=True)
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.layers.experimental import preprocessing
print(tf.__version__)
Explanation: Basic regression: Predict fuel efficiency
<table class="tfo-notebook-buttons" align="left">
  <td>     <a target="_blank" href="https://tensorflow.google.cn/tutorials/keras/regression"><img src="https://tensorflow.google.cn/images/tf_logo_32px.png"> 在 TensorFlow.org 上查看</a>   </td>
  <td>     <a target="_blank" href="https://colab.research.google.com/github/tensorflow/docs-l10n/blob/master/site/zh-cn/tutorials/keras/regression.ipynb"><img src="https://tensorflow.google.cn/images/colab_logo_32px.png">在 Google Colab 中运行</a>   </td>
  <td> <img><a>在 GitHub 上查看源代码</a> </td>
  <td> <img><a>下载笔记本</a> </td>
</table>
Note: 我们的 TensorFlow 社区翻译了这些文档。因为社区翻译是尽力而为， 所以无法保证它们是最准确的，并且反映了最新的 官方英文文档。如果您有改进此翻译的建议， 请提交 pull request 到 tensorflow/docs GitHub 仓库。要志愿地撰写或者审核译文，请加入 docs-zh-cn@tensorflow.org Google Group。
此笔记本使用经典的 Auto MPG 数据集并构建模型来预测 20 世纪 70 年代末和 20 世纪 80 年代初汽车的燃油效率。为此，需要为模型提供该时期的许多汽车的描述。这种描述包括诸如气缸、排量、马力和重量等属性。
本 notebook 使用经典的 Auto MPG 数据集，构建了一个用来预测70年代末到80年代初汽车燃油效率的模型。为了做到这一点，我们将为该模型提供许多那个时期的汽车描述。这个描述包含：气缸数，排量，马力以及重量。
End of explanation
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']
raw_dataset = pd.read_csv(url, names=column_names,
                          na_values='?', comment='\t',
                          sep=' ', skipinitialspace=True)
dataset = raw_dataset.copy()
dataset.tail()
Explanation: Auto MPG 数据集
该数据集可以从 UCI机器学习库 中获取.
获取数据
首先下载数据集。
End of explanation
dataset.isna().sum()
Explanation: 数据清洗
数据集中包括一些未知值。
End of explanation
dataset = dataset.dropna()
Explanation: 为了保证这个初始示例的简单性，删除这些行。
End of explanation
origin = dataset.pop('Origin')
dataset['USA'] = (origin == 1)*1.0
dataset['Europe'] = (origin == 2)*1.0
dataset['Japan'] = (origin == 3)*1.0
dataset.tail()
Explanation: "Origin" 列实际上是分类的，而不是数字。因此，使用 pd.get_dummies 将其转换为独热码：
注：您可以设置 keras.Model 来为您执行这种转换。这超出了本教程的范围。有关示例，请参阅预处理层或加载 CSV 数据教程。
End of explanation
train_dataset = dataset.sample(frac=0.8, random_state=0)
test_dataset = dataset.drop(train_dataset.index)
Explanation: 拆分训练数据集和测试数据集
现在需要将数据集拆分为一个训练数据集和一个测试数据集。
在我们模型的最终评估中使用测试集。
End of explanation
sns.pairplot(train_dataset[["MPG", "Cylinders", "Displacement", "Weight"]], diag_kind="kde")
Explanation: 数据检查
快速查看训练集中几对列的联合分布。
查看顶行，应当清楚燃油效率 (MPG) 是所有其他参数的函数。查看其他行，应当清楚它们是彼此的函数。
End of explanation
train_stats = train_dataset.describe()
train_stats.pop("MPG")
train_stats = train_stats.transpose()
train_stats
Explanation: 也可以查看总体的数据统计:
End of explanation
train_features = train_dataset.copy()
test_features = test_dataset.copy()
train_labels = train_features.pop('MPG')
test_labels = test_features.pop('MPG')
Explanation: 从标签中分离特征
将特征值从目标值或者"标签"中分离。 这个标签是你使用训练模型进行预测的值。
End of explanation
train_dataset.describe().transpose()[['mean', 'std']]
Explanation: 归一化
再次审视下上面的 train_stats 部分，并注意每个特征的范围有什么不同。
End of explanation
normalizer = preprocessing.Normalization(axis=-1)
Explanation: 使用不同的尺度和范围对特征归一化是好的实践。尽管模型可能 在没有特征归一化的情况下收敛，它会使得模型训练更加复杂，并会造成生成的模型依赖输入所使用的单位选择。
注意：尽管我们仅仅从训练集中有意生成这些统计数据，但是这些统计信息也会用于归一化的测试数据集。我们需要这样做，将测试数据集放入到与已经训练过的模型相同的分布中。
尽管模型可能在没有特征归一化的情况下收敛，但归一化会使训练更加稳定。
注：归一化独热特征没有任何好处，这里这样做是为了简单起见。有关如何使用预处理层的更多详细信息，请参阅使用预处理层指南和使用 Keras 预处理层对结构化数据进行分类教程。
归一化层
preprocessing.Normalization 层是一种将预处理构建到模型中的简洁且简单的方法。
第一步是创建层：
End of explanation
normalizer.adapt(np.array(train_features))
Explanation: 然后对其执行 .adapt() 以适应数据：
End of explanation
print(normalizer.mean.numpy())
Explanation: 这将计算均值和方差，并将它们存储在层中。
End of explanation
first = np.array(train_features[:1])
with np.printoptions(precision=2, suppress=True):
  print('First example:', first)
  print()
  print('Normalized:', normalizer(first).numpy())
Explanation: 当层被调用时，它会返回输入数据，每个特征独立归一化：
End of explanation
horsepower = np.array(train_features['Horsepower'])
horsepower_normalizer = preprocessing.Normalization(input_shape=[1,], axis=None)
horsepower_normalizer.adapt(horsepower)
Explanation: 线性回归
在构建 DNN 模型之前，先从线性回归开始。
一个变量
从单变量线性回归开始，根据 Horsepower 预测 MPG。
使用 tf.keras 训练模型通常从定义模型架构开始。
在这种情况下，使用 keras.Sequential 模型。此模型代表了一系列步骤。在这种情况下，有两个步骤：
将输入 horsepower 归一化。
应用线性变换 ($y = mx+b$) 以使用 layers.Dense 产生 1 个输出。
输入的数量可以由 input_shape 参数设置，也可以在模型第一次运行时自动设置。
首先创建马力 Normalization 层：
End of explanation
horsepower_model = tf.keras.Sequential([
    horsepower_normalizer,
    layers.Dense(units=1)
])
horsepower_model.summary()
Explanation: 构建序贯模型：
End of explanation
horsepower_model.predict(horsepower[:10])
Explanation: 此模型将根据 Horsepower 预测 MPG。
在前 10 个马力值上运行未经训练的模型。输出不会很好，但您会看到它具有预期的形状 (10,1)：
End of explanation
horsepower_model.compile(
    optimizer=tf.optimizers.Adam(learning_rate=0.1),
    loss='mean_absolute_error')
Explanation: 构建模型后，使用 Model.compile() 方法配置训练过程。要编译的最重要参数是 loss 和 optimizer，因为它们定义了将要优化的内容 (mean_absolute_error) 以及优化的方法（使用 optimizers.Adam）。
End of explanation
%%time
history = horsepower_model.fit(
    train_features['Horsepower'], train_labels,
    epochs=100,
    # suppress logging
    verbose=0,
    # Calculate validation results on 20% of the training data
    validation_split = 0.2)
Explanation: 训练配置完成后，使用 Model.fit() 执行训练：
End of explanation
hist = pd.DataFrame(history.history)
hist['epoch'] = history.epoch
hist.tail()
def plot_loss(history):
  plt.plot(history.history['loss'], label='loss')
  plt.plot(history.history['val_loss'], label='val_loss')
  plt.ylim([0, 10])
  plt.xlabel('Epoch')
  plt.ylabel('Error [MPG]')
  plt.legend()
  plt.grid(True)
plot_loss(history)
Explanation: 使用 history 对象中存储的统计信息可视化模型的训练进度。
End of explanation
test_results = {}
test_results['horsepower_model'] = horsepower_model.evaluate(
    test_features['Horsepower'],
    test_labels, verbose=0)
Explanation: 收集测试集上的结果，以便稍后使用：
End of explanation
x = tf.linspace(0.0, 250, 251)
y = horsepower_model.predict(x)
def plot_horsepower(x, y):
  plt.scatter(train_features['Horsepower'], train_labels, label='Data')
  plt.plot(x, y, color='k', label='Predictions')
  plt.xlabel('Horsepower')
  plt.ylabel('MPG')
  plt.legend()
plot_horsepower(x,y)
Explanation: 由于这是一个单变量回归，因此很容易将模型的预测视为输入的函数：
End of explanation
linear_model = tf.keras.Sequential([
    normalizer,
    layers.Dense(units=1)
])
Explanation: 多个输入
您可以使用几乎相同的设置根据多个输入进行预测。此模型仍然执行相同的 $y = mx+b$，只是 $m$ 是一个矩阵而 $b$ 是一个向量。
这次使用适应整个数据集的 Normalization 层。
End of explanation
linear_model.predict(train_features[:10])
Explanation: 当您对一批输入调用此模型时，它会为每个样本生成 units=1 输出。
End of explanation
linear_model.layers[1].kernel
Explanation: 当您调用模型时，将构建其权重矩阵。现在，您可以看到 kernel（$y=mx+b$ 中的 $m$）的形状为 (9,1)。
End of explanation
linear_model.compile(
    optimizer=tf.optimizers.Adam(learning_rate=0.1),
    loss='mean_absolute_error')
%%time
history = linear_model.fit(
    train_features, train_labels, 
    epochs=100,
    # suppress logging
    verbose=0,
    # Calculate validation results on 20% of the training data
    validation_split = 0.2)
Explanation: 使用与单输入 horsepower 模型相同的 compile 和 fit 调用：
End of explanation
plot_loss(history)
Explanation: 使用所有输入可以实现比 horsepower 模型低得多的训练和验证误差：
End of explanation
test_results['linear_model'] = linear_model.evaluate(
    test_features, test_labels, verbose=0)
Explanation: 收集测试集上的结果，以便稍后使用：
End of explanation
def build_and_compile_model(norm):
  model = keras.Sequential([
      norm,
      layers.Dense(64, activation='relu'),
      layers.Dense(64, activation='relu'),
      layers.Dense(1)
  ])
  model.compile(loss='mean_absolute_error',
                optimizer=tf.keras.optimizers.Adam(0.001))
  return model
Explanation: 模型
上一部分为单输入和多输入实现了线性模型。
本部分实现单输入和多输入 DNN 模型。除了将模型扩展为包括一些“隐藏”非线性层之外，代码基本相同。此处的名称“隐藏”仅表示不直接连接到输入或输出。
这些模型包含的层比线性模型多一些：
归一化层。
使用 relu 非线性的两个隐藏非线性 Dense 层。
线性单输出层。
两者都将使用相同的训练过程，因此 compile 方法包含在下面的 build_and_compile_model 函数中。
End of explanation
model = build_model()
Explanation: 一个变量
从单个输入的 DNN 模型开始：“马力”
End of explanation
model.summary()
Explanation: 使用 .summary 方法来打印该模型的简单描述。
End of explanation
%%time
history = dnn_horsepower_model.fit(
    train_features['Horsepower'], train_labels,
    validation_split=0.2,
    verbose=0, epochs=100)
Explanation: 对模型进行1000个周期的训练，并在 history 对象中记录训练和验证的准确性。
End of explanation
plot_loss(history)
Explanation: 此模型略优于线性马力模型。
End of explanation
x = tf.linspace(0.0, 250, 251)
y = dnn_horsepower_model.predict(x)
plot_horsepower(x, y)
Explanation: 如果您将预测值绘制为 Horsepower 的函数，则将看到此模型如何利用隐藏层提供的非线性：
End of explanation
test_results['dnn_horsepower_model'] = dnn_horsepower_model.evaluate(
    test_features['Horsepower'], test_labels,
    verbose=0)
Explanation: 收集测试集上的结果，以便稍后使用：
End of explanation
dnn_model = build_and_compile_model(normalizer)
dnn_model.summary()
%%time
history = dnn_model.fit(
    train_features, train_labels,
    validation_split=0.2,
    verbose=0, epochs=100)
plot_loss(history)
Explanation: 完整模型
如果您使用所有输入重复此过程，则它会略微提高验证数据集的性能。
End of explanation
test_results['dnn_model'] = dnn_model.evaluate(test_features, test_labels, verbose=0)
Explanation: 收集测试集上的结果：
End of explanation
pd.DataFrame(test_results, index=['Mean absolute error [MPG]']).T
Explanation: 性能
现在，所有模型都经过训练，检查测试集的性能，看看它们的表现如何：
End of explanation
test_predictions = dnn_model.predict(test_features).flatten()
a = plt.axes(aspect='equal')
plt.scatter(test_labels, test_predictions)
plt.xlabel('True Values [MPG]')
plt.ylabel('Predictions [MPG]')
lims = [0, 50]
plt.xlim(lims)
plt.ylim(lims)
_ = plt.plot(lims, lims)
Explanation: 这些结果与训练期间看到的验证误差相匹配。
做预测
最后，使用测试集中的数据预测 MPG 值:
End of explanation
error = test_predictions - test_labels
plt.hist(error, bins=25)
plt.xlabel('Prediction Error [MPG]')
_ = plt.ylabel('Count')
Explanation: 看起来模型预测得相当出色。
现在，看一下误差分布：
End of explanation
dnn_model.save('dnn_model')
Explanation: 如果您对模型感到满意，请将其保存以备以后使用：
End of explanation
reloaded = tf.keras.models.load_model('dnn_model')
test_results['reloaded'] = reloaded.evaluate(
    test_features, test_labels, verbose=0)
pd.DataFrame(test_results, index=['Mean absolute error [MPG]']).T
Explanation: 如果您重新加载模型，它会给出相同的输出：
End of explanation
<END_TASK>