每个输出节点与全部的输入节点相连接,这种网络层称为全连接层,本质上是矩阵的相乘和相加运算;

由神经元相互连接而成的网络叫做神经网络,每一层为全连接层的网络叫做全连接网络;

6.5解释了为什么预处理数据到0-1才合适的原因。

影响汽车的每加仑燃油英里数的有气缸数,排量,马力,重量,加速度,生产低和年份

其中有如下关系

tensorflow 2.0 学习 (五)MPG全连接网络训练与测试

与书上图6.16对应,但第四个图找不到是什么!

预测的神经网络如下:

# encoding: utf-8

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers, Sequential
import pandas as pd
import matplotlib.pyplot as plt

# input data
dataset_path = keras.utils.get_file("auto-mpg.data", "http://archive.ics.uci.edu/ml/"
                                                     "machine-learning-databases/auto-mpg/auto-mpg.data",
                                    cache_dir='G:2019pythonauto-mpg.data')
colum_names = ['MPG', 'Cylinder', 'Displacement', 'Horsepower', 'Weight',
               'Acceleration', 'Model Year', 'Origin']                  # 398行数据,8列
raw_dataset = pd.read_csv(dataset_path, names=colum_names, na_values="?", comment='t',
                          sep=" ", skipinitialspace=True)

# data process
dataset = raw_dataset.copy()
dataset.head()
dataset.isna().sum()
dataset = dataset.dropna()
dataset.isna().sum()                    # dataset.shape = (392, 8)

# 拓展dataset到10列
origin = dataset.pop('Origin')          # (392, 1)得到产地
dataset['USA'] = (origin == 1) * 1.0
dataset['Europe'] = (origin == 2) * 1.0
dataset['Japan'] = (origin == 3) * 1.0
dataset.tail()                          # dataset.shape = (392, 10) 后三列换成三个产地,每列用0,1表示是否

# 获取训练集和测试集
train_dataset = dataset.sample(frac=0.8, random_state=0)            # (314, 10)
test_dataset = dataset.drop(train_dataset.index)                    # (78, 10)

train_labels = train_dataset.pop('MPG')                             # (314, 1) 取出带标签“MPG”的第一列
test_labels = test_dataset.pop('MPG')                               # (78, 1)

# 做统计
train_stats = train_dataset.describe()                          # (8, 9)获取一列数据的均值、标准差、最大值、最小值等
train_stats = train_stats.transpose()                           # (9, 8) 转置功能

# 标准化函数
def norm(x):
    return (x - train_stats['mean']) / train_stats['std']

# 训练集、测试集标准化
normed_train_data = norm(train_dataset)                         # (314, 9)数据-1:1之间
normed_test_data = norm(test_dataset)                           # (78, 9)

print(normed_train_data.shape, train_labels.shape)              # 展示最终输入的模型
print(normed_test_data.shape, test_labels.shape)

#切分训练集、测试集
train_db = tf.data.Dataset.from_tensor_slices((normed_train_data.values,  train_labels.values))
train_db = train_db.shuffle(314).batch(32)

test_db = tf.data.Dataset.from_tensor_slices((normed_test_data.values, test_labels.values))
test_db = test_db.shuffle(78).batch(13)

# 观察原始数据之间的关系
def Draw():
    MPG = dataset.pop('MPG')
    Cylinder = dataset.pop('Cylinder')
    Displacement = dataset.pop('Displacement')
    Weight = dataset.pop('Weight')
    Horsepower = dataset.pop('Horsepower')
    Acceleration = dataset.pop('Acceleration')
    ModelYear = dataset.pop('Model Year')
    plt.figure()
    plt.subplot(131)
    plt.plot(Cylinder, MPG, 'bo')
    plt.xlabel('Cylinders')
    plt.ylabel('MPG')
    plt.subplot(132)
    plt.plot(Displacement, MPG, 'bo')
    plt.xlabel('Displacement')
    plt.ylabel('MPG')
    plt.subplot(133)
    plt.plot(Weight, MPG, 'bo')
    plt.xlabel('Weight')
    plt.ylabel('MPG')
    plt.savefig('three_fig_auto-MPG.png')
    plt.show()

# 特征之间两两分布
Draw()

# 创建网络
class Network(keras.Model):
    def __init__(self):                                     # 回归网络模型
        super(Network, self).__init__()
        self.fc1 = layers.Dense(64, activation='relu')      # 输出64个节点
        self.fc2 = layers.Dense(64, activation='relu')
        self.fc3 = layers.Dense(1)

    def call(self, inputs, training=None, mask=None):       # 创建3个全连接层
        x = self.fc1(inputs)
        x = self.fc2(x)
        x = self.fc3(x)
        return x

model = Network()                                           # 创建网络实例
model.build(input_shape = (4, 9))                           # 完成内部张量的创建,4为任意设置的batch数,9为输入特征长度
model.summary()                                             # 打印网络信息
optimizer = tf.keras.optimizers.RMSprop(0.001)              # 创建优化器,指定学习率

# 保存训练和测试过程中的误差情况
train_tot_loss = []
train_tot_mae = []
test_tot_loss = []
test_tot_mae = []

for epoch in range(200):
    for step, (x, y) in enumerate(train_db):
        with tf.GradientTape() as tape:                         # 梯度记录器
            out = model(x)                                      # 通过网络获取输入
            loss = tf.reduce_mean(tf.losses.MSE(y, out))        # 计算MSE
            mae_loss= tf.reduce_mean(tf.losses.MAE(y, out))     # 计算MAE

        if step % 10 == 0:
            print(epoch, step, float(loss))
            train_tot_loss.append(float(loss))
            train_tot_mae.append(float(mae_loss))
        # 更新梯度
        grads = tape.gradient(loss, model.trainable_variables)
        optimizer.apply_gradients(zip(grads, model.trainable_variables))

        # 测试
        if step % 10 == 0:
            test_loss, test_mae_loss = 0, 0
            for x, y in test_db:
                test_out = model(x)
                test_loss = tf.reduce_mean(tf.losses.MSE(y, test_out))
                test_mae_loss = tf.reduce_mean(tf.losses.MAE(y, test_out))

            print(epoch, step, float(test_loss))
            test_tot_loss.append(float(test_loss))
            test_tot_mae.append(float(test_mae_loss))

plt.figure()
plt.plot(train_tot_mae, 'b', label = 'train')
plt.plot(test_tot_mae, 'r', label = 'test')
plt.xlabel('Step')
plt.ylabel('MAE')
plt.legend()
plt.savefig('train_test_auto-MPG.png')
plt.show()

训练和测试误差如下:

tensorflow 2.0 学习 (五)MPG全连接网络训练与测试

有波动与书上很光滑不太一致,总体趋势是一致的!

注意:(1)警告:tensorflow:Layer network正在将输入张量从dtype float64转换为该层的dtype float32,这是tensorflow 2中的新行为。

未解决这个警告!

下次更新反向传播算法,Himmelbla函数优化与二分类全连接网络