TensorFlow2.0 (1) wide and deep 模型多输入代码详解

前言、

                TensorFlow 2.0 的重点笔记,对一些细节掌握不牢固,写一下博文来挖掘自己的不足

                因为是纯手打,方便记忆,可能存在一些字节错误,敬请谅解

一、 wide and deep 

          1. 引入资源库

import matplotlib as mpl # python 绘图库
import matplotlib.pyplot as plt # python 2D 绘图库
import numpy as np # 数学库,矩阵数组等
import sklearn
import pandas as pd # 大数据处理模块
import os # 处理文件和目录
import sys # 解释器使用或维护一些变量的访问,以及与解释器强交互的函数
import time # 格式化日期与时间
import tensorflow as tf

from tensorflow import keras

#显示重要库的对应版本
print(tf.__version__)
print(sys.version_info)
for module in mpl,np,pd,sklearn,tf,keras:
    print(module.__name__,module.__version__)

          2. 引入数据集

from sklearn.datasets import fetch_california_housing
# 引入加州房价预测数据
housing = fetch_california_housing()
# 显示数据的说明,数据的矩阵形状,标签的形状
print(housing.DESCR)
print(housing.data.shape)
print(housing.target.shape)

         3. 分割数据集

# 引入机器学习数据集分割库
from sklearn.model_selection import train_test_split
# 引入预测房价的 data,target,并切分数据为 训练集(训练集中又该分为训练集和验证集) 与 测试集,
# x 为训练集,y 为测试集,这里将数据切割为 4 个部分,训练集的特征,验证集的特征,训练集的标签,验证集的标签
# 没有填写训练集与验证的分割比例的话,默认为 0.75
" train_test_split:
    housing.data: 被划分样本的特征集
    housing.target: 被划分样本的标签
    random_state=7: 随机数设定为 7 ,那重复运行时,运行的是同一份数据,改为其他数字,将会导致数据不一致
"
x_train_all,x_test,y_train_all,y_test = train_test_split(
    housing.data,housing.target,random_state=7)

# 将大训练集分割为小训练集与验证集
x_train,x_valid,y_train,y_valid =train_test_split(
    x_train_all,y_train_all,random_state=11)

# 显示训练集,验证集,测试集的形状
print(x_train.shape,y_train.shape)
print(x_valid.shape,y_valid.shape)
print(x_test.shape,y_test.shape)

         4. 归一化

# 引入标准化库 :计算训练集的平均值和标准差,以便测试数据集使用相同的变换
from sklearn.preproccessing import StandardScaler

# 引入标准化函数
scaler = StandarScaler()
# 训练集,验证集,测试集标准化
x_train_scaled = scaler.fit_transform(x_train)
x_valid_scaled = scaler.transform(x_valid)
x_test_scaled = scaler.transform(x_test)

          5. 模型建立

                     经过上面的步骤,我们已经成功导入数据,并对数据完成分割和标准化,下面是建立模型

                     并且因为 wide and deep 模型是分为左右两个部分,不能使用 Sequential 来建立模型,我们就需要

                     使用函数式 API 或者 子类 API 来建立模型

                     在这里我们先演示一下两种模型建立方式:

                  5.1 函数 API 实现 wide and deep 模型

# 函数式 API 功能 API
#输入层,取训练集的第一行以后
# 设定输入格式 这里设定输入矩阵为 行为 None ,列为 8 ,意思是有八分特征值的任意数量的数据
input = keras.layers.Input(shape=x_train.shape[1:])
# 第一层隐藏层,上一层为 input 层,有 30 个节点
hidden1 = keras.layers.Dense(30,activation='relu')(input)
# 第二层隐藏层
hidden2 = keras.layers.Dense(30,activation='relu')(hidden1)
#神经网络不同层级之间就跟复合函数类似: f(x)=h(g(x))

# hidden2 为 deep model 的输出,input 为 wide model 的输入
# wide 模型是将输入直接线性输入给结果,deep 模型则是对输入进行处理后再输出
# 这里就将 wide and deep 模型的两个输出合并再输出
concat =keras.layers.concatenate([input,hidden2])
output =keras.layers.Dense(1)(concat)
#固化模型
model = keras.models.Model(inputs=[input],
                            outputs = [output])

 

                   5.2 子类 API 实现 wide and deep 模型

class WideDeepModel(keras.models.Model):
    def __init__(self):
        super(WideDeepModel,self).__init__()
        """定义模型的层次"""
        self.hidden1_layer = keras.layers.Dense(30,activation='relu')
        self.hidden2_layer = keras.layers.Dense(30,activation='relu')
        self.output_layer = keras.layers.Dense(1)

# 因为没有反向传播部分,就只需要定义正向计算部分
    def call(self,input):
        """完成模型的正向计算"""
        hidden1 = self.hidden1_layer(input)
        hidden2 = self.hidden2_layer(hidden1)
        concat = keras.layers.concatenate([input,hidden2])
        output = self.output_layer(concat)
        return output

# 第一种子类 API 使用方法,定义一个模型的对象 
# model = WideDeepModel()
# 再调用模型的 build 函数定义输入 ,8 对于 feature 数量
# model.build(input_shape+(None,8))



model = keras.models.Sequential([
    WideDeepModel(),
])

model.build(input_shape=(None,8))

                   5.3 wide and deep 多输入

# 实现多输入 这里使用函数式的方法
# 我们假设我们将前 5 个 feature 输入 wide 模型,后 6 个 feature 输入 deep 模型,一共 8 个 feature ,也就是说, wide and deep 有交集部分
input_wide = keras.layers.Input(shape=[5])
input_deep = keras.layers.Input(shape=[6])
# deep model 有两个隐藏层
hidden1 = keras.layers.Dense(30,activation='relu')(input_deep)
hidden2 = keras.layers.Dense(30,activation='relu')(hidden1)
# 合并两个模型的输出
concat = keras.layers.concatenate([input_wide,hidden2])
# 模型的输入为两个模型的输入,输出只有一个
model = keras.models.Model(inputs = [input_wide,input_deep],
                            outputs = [output])

           6. 配置模型学习流程

                 6.1 非多输入的模型配置

# 先用 summary 看一下模型结构,概况
model.summary()
# 配置模型
# loss: 损失函数,这里设定为 mean_squared_error(均方误差)*sparse_categorical_crossentropy 交叉熵
# optimizer: 优化器,这里设定为 sgd(随机梯度下降)
# metrics :指标,可选 metrics=["accuracy"]
model.compile(loss="mean_squared_error",optimizer="sgd")

# 定义回调函数:在训练模型时,中间需要进行的一些操作
# keras.callbacks.EarlyStopping :提前结束训练,loss 不再下降时
#                 ModelCheckpoint : 每个一段时间显示一下各个参数的中间状态
# EarlyStopping 的参数介绍:
#                         patience : 进过 5 步没有进步,模型训练将被停止
#                         min_delta : 变化小于该值,则认为没有进步
callbacks = [keras.callbacks.EarlyStopping(
                patience= 5,min_delta=1e-2)]

                 6.2 多输入的训练集配置

                                在多输入的情况下,训练集不但需要拆分,还有重复训练部分,所以我们需要根据多输入的情况,对数据做

                                拆分处理,所以需要多加上这一部分的代码

# wide 模型的输入,前 5 个特征的数据集 ,deep 模型输入后 6 个
x_train_scaled_wide = x_train_scaled[:,:5]
x_train_scaled_deep = x_train_scled[:,2:]
# 验证集和测试集同上
x_valid_scaled_wide = x_valid_scaled[:,:5]
x_valid_scaled_deep = x_valid_scaled[:,2:]
x_test_scaled_wide = x_test_scaled[:,:5]
x_test_scaled_deep = x_test_scaled[:.2:]

           7. 开启训练

                 7.1 非多输入的训练

                       构建好图以后,我们就可以开启训练了

                       这里调用 model.fit 函数来进行训练

# 调用训练函数 fit ,
# 输入归一化后的训练集,以及训练集的标签
# 输入验证集,设定好后,每隔一段时间,就会对验证集做一次验证
# 设定遍历训练集的次数,100 次
# 获取 callbacks 函数
history = model.fit(x_train_scaled,y_train,
                    validation_data = (x_valid_scaled,y_valid),
                    epochs = 100,
                    callbacks = callbacks)

                  7.2 多输入的模型训练

               

history = model.fit([x_train_scaled_wide,x_train_scaled_deep],
                    y_train,
                    validation_data=(
                                    [x_valid_scaled_wide,x_valid_scaled_deep],
                                    y_valid),
                    epochs = 100,
                    callbacks = callbacks)

           8. 训练过程的图表展示

                       以上我们的模型构建和训练已经完成了,但我们还想了解一下训练过程中参数的变化

# 设定图表展示函数,将模型训练的接受对象 history 输入到该函数中
def plot_learning_curves(history):
# 将 history 获取到的训练过程的参数变化的字典变为矩阵形状,并设定图的尺寸大小为 8 和 5
    pd.DataFrame(history.history).plot(figsize=(8,5))
# 显示网格
    plt.grid(True)
# 设置坐标范围 ,设定 y 为 0~1 之间
    plt.gca().set_ylim(0,1)
# 显示这张图
    plt.show()
plot_learning_curves(history)

 

           9. 评估模型

                       最后我们可以使用测试集评估一下模型

# 输入测试集的特征与标签
model.evaluate(x_test_scaled,y_test)

 

参考资料、

                           Google老师亲授 TensorFlow2.0 

你可能感兴趣的:(TensorFlow,2.0,tensorflow)