【TensorFlow2.0】keras高层接口之经典数据集加载、网络层、网络容器、模型装配、模型训练、模型测试、模型保存和加载

文章目录

  • 一、常见功能模块
    • 1.1 经典数据集加载函数
    • 1.2 常见网络层类
    • 1.3 网络容器
  • 二、模型装配、训练与测试
    • 2.1 模型装配
    • 2.2 模型训练
    • 2.3 模型测试
  • 三、模型保存与加载
    • 3.1 张量方式--保存权重
    • 3.2 网络方式--保存结构和权重
    • 3.3 SavedModel方式--保存结构和权重

  keras是一个主要由Python语言开发的开源神经网络计算库,被设计为高度模块化和易扩展的高层神经网络接口,使用户不需要过多的专业知识就可以简洁、快速地完成模型的搭建与训练。Keras库分为前端和后端,其中后端是调用现有的神经网络学习框架实现底层运算,如theano、CNTK、tensorflow等,前端接口是Keras抽象过的一组统一接口函数。
  Keras与tensorflow的关系:
  (1)TensorFlow1.0:tensorflow1.0作为Keras的后端支持,Keras的大部分组件被整合到tensorflow1.0框架中。
  (2)TensorFlow2.0: Keras被正式确定为tensorflow2.0的高层唯一接口API,取代了tensorflow中自带的tf.layers等高层接口,现在只能使用Keras的接口来完成tensorflow层方式的模型搭建与训练。在TensorFlow2.0中,Keras被实现在tf.keras模块中。

一、常见功能模块

1.1 经典数据集加载函数

  语法:tf.keras.datasets.xxx.load_data()
  数据集加载模块详细介绍:https://blog.csdn.net/qq_36926037/article/details/105775048

1.2 常见网络层类

  语法:tf.keras.layers.xxx()
  在tf.keras.layers命名空间中提供了大量的常见网络层的类,如全连接层、激活函数层、池化层、卷积层、循环神经网络层等。这些网络层的类,只需要在创建时,指定网络层的相关参数,并调用__call__方法即可完成前向计算。在调用__call__方法时,keras会Keras会自动调用每个层的前项传播逻辑,这些逻辑一般实现在类的call函数中。

import tensorflow as tf
'''
以softmax函数为例,他既可以使用tf.nn.softmas函数在前项传播中完成softmax运算,也可以通过tf.keras.layers.Softmax(axis)
   类搭建Softmax网络层,其中axis参数指定进行softmax运算的维度。
'''
from tensorflow import keras
#导入keras模型,不能使用import keras,它导入的是标准的keras库
from tensorflow.keras import layers#导入常见网络层类
x=tf.constant([2.,1.,0.1])#创建输入张量
layer=layers.Softmax(axis=-1)#创建softmax层,并调用————call__方法完成前项计算
out=layer(x)#调用softmax前向计算,输出为out

print(out)#tf.Tensor([0.6590012  0.24243298 0.09856589], shape=(3,), dtype=float32)

1.3 网络容器

  常见网络层,需要手动调用每一层的类实例完成前向传播运算,当网络层数变得较深时,十分复杂。keras提供的网络容器sequential1将多个网络层封装成一个大网络模型,只需要调用网络模型的实例一次,就可以完成数据从第一层到最末层顺序的传播运算。
  语法:tf.keras.Sequential( [layer1,layer2…] )
     Sequential.add(layer)给sequential容器追加新的网络层

import tensorflow as tf
from tensorflow.keras import layers
#导入sequential容器
from tensorflow.keras import Sequential
network=Sequential([
    layers.Dense(3,activation=None),
    layers.ReLU(),
    layers.Dense(2,activation=None),
    layers.ReLU()
])
x=tf.random.normal([4,3])
out=network(x)#输入从第一层开始,直接传播到输出层,并返回输出层的值

'''sequential容器可以通过add方式追加新的网络层,实现动态创建网络的功能:'''
layers_num=2
network2=Sequential([])#创建新的空网络容器
for _ in range(layers_num):
    network2.add(layers.Dense(3,activation=None))#添加全连接层
    network2.add(layers.ReLU())#添加激活函数
network2.build(input_shape=(4,4))#创建网路参数,之前网络并没有创建内部权值等成员变量,通过build方法指定输入大小,即可自动创建所有层的内部张量
network2.summary()
# Model: "sequential_1"
# _________________________________________________________________
# Layer (type)                 Output Shape              Param #
# =================================================================
# dense_2 (Dense)              multiple                  15
# _________________________________________________________________
# re_lu_2 (ReLU)               multiple                  0
# _________________________________________________________________
# dense_3 (Dense)              multiple                  12
# _________________________________________________________________
# re_lu_3 (ReLU)               multiple                  0
# =================================================================
# Total params: 27
# Trainable params: 27
# Non-trainable params: 0
# _________________________________________________________________
'''打印网络待优化参数:sequential对象的trainable_variable和variable包含了所有层的待优化张量和全部张量'''
for p in network2.trainable_variables:
    print(p.name,p.shape)#参数名和形状
# dense_2/kernel:0 (4, 3)
# dense_2/bias:0 (3,)
# dense_3/kernel:0 (3, 3)
# dense_3/bias:0 (3,)

二、模型装配、训练与测试

  在训练网络时,一般的流程是
  (1)通过前向计算获得网络的输出值,
  (2)再通过损失函数计算网络误差
  (3)然后通过自动求导工具计算梯度并更新。

2.1 模型装配

  keras中两个比较特殊的类:
  (1)keras.layer类:是网络层的母类,定义了网络层的一些常见功能,如添加权值、管理权值列表等
  (2)keras.Model类:是网络的母类,除了具有layer类的功能,还添加了保存模型、加载模型、训练与测试模型等便捷功能。sequential也是model的子类,具有model的所有功能。
  语法:Model.compile(optimizer,loss)

import  tensorflow as tf
from    tensorflow.keras import datasets, layers, optimizers, Sequential, metrics,losses
#创建5层的全连接网络
'''创建网络'''
network = Sequential([layers.Dense(256, activation='relu'),
                     layers.Dense(128, activation='relu'),
                     layers.Dense(64, activation='relu'),
                     layers.Dense(32, activation='relu'),
                     layers.Dense(10)])
network.build(input_shape=(None, 28*28))
#network.summary()#可视化网络

'''(1)模型装配:优化器,损失函数'''
network.compile(optimizer=tf.keras.optimizers.Adam(lr=0.01),
                loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),
                metrics=['accuracy'])

2.2 模型训练

  语法:Model.fit(train_data,epoch,validition_data…)
  fit函数返回训练过程的记录信息history,为字典对象,包含了训练过程中的loss、测量指标等记录项。通过history.history可以查看信息

import  tensorflow as tf
from    tensorflow.keras import datasets, layers, optimizers, Sequential, metrics,losses
#创建5层的全连接网络
'''创建网络'''
network = Sequential([layers.Dense(256, activation='relu'),
                     layers.Dense(128, activation='relu'),
                     layers.Dense(64, activation='relu'),
                     layers.Dense(32, activation='relu'),
                     layers.Dense(10)])
network.build(input_shape=(None, 28*28))
#network.summary()#可视化网络

'''(1)模型装配:优化器,损失函数'''
network.compile(optimizer=tf.keras.optimizers.Adam(lr=0.01),
                loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),
                metrics=['accuracy'])
'''(2)模型训练:'''
def preprocess(x, y):
    x = tf.cast(x, dtype=tf.float32) / 255.
    x = tf.reshape(x, [28*28])
    y = tf.cast(y, dtype=tf.int32)
    y = tf.one_hot(y, depth=10)
    return x,y
batchsz = 128
(x, y), (x_val, y_val) = datasets.mnist.load_data()#数据加载
db = tf.data.Dataset.from_tensor_slices((x,y))#变为Dataset对象
db = db.map(preprocess).shuffle(60000).batch(batchsz)#训练集预处理
ds_val = tf.data.Dataset.from_tensor_slices((x_val, y_val))#
ds_val = ds_val.map(preprocess).batch(batchsz)
sample = next(iter(db))

#模型训练:训练集db,验证集ds_val,训练3epoch,每2个epoch验证一次
history=network.fit(db, epochs=3, validation_data=ds_val, validation_freq=2)#返回训练信息,保存在history中
print(history.history)#查看训练数据
#{'loss': [0.28250920921961464, 0.13529823817014694, 0.10918430316845576],
# 'accuracy': [0.91571665, 0.96241665, 0.9697667], 'val_loss': [0.12126635440737245], 'val_accuracy': [0.9676]}

2.3 模型测试

  model基类除了可以快捷的完成网络的装配、训练。验证,还可以非常方便的进行预测和测试。
  语法:Model.predict(data)

import  tensorflow as tf
from    tensorflow.keras import datasets, layers, optimizers, Sequential, metrics,losses
#创建5层的全连接网络
'''创建网络'''
network = Sequential([layers.Dense(256, activation='relu'),
                     layers.Dense(128, activation='relu'),
                     layers.Dense(64, activation='relu'),
                     layers.Dense(32, activation='relu'),
                     layers.Dense(10)])
network.build(input_shape=(None, 28*28))
#network.summary()#可视化网络

'''(1)模型装配:优化器,损失函数'''
network.compile(optimizer=tf.keras.optimizers.Adam(lr=0.01),
                loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),
                metrics=['accuracy'])
'''(2)模型训练:'''
def preprocess(x, y):
    x = tf.cast(x, dtype=tf.float32) / 255.
    x = tf.reshape(x, [28*28])
    y = tf.cast(y, dtype=tf.int32)
    y = tf.one_hot(y, depth=10)
    return x,y
batchsz = 128
(x, y), (x_val, y_val) = datasets.mnist.load_data()#数据加载
db = tf.data.Dataset.from_tensor_slices((x,y))#变为Dataset对象
db = db.map(preprocess).shuffle(60000).batch(batchsz)#训练集预处理
ds_val = tf.data.Dataset.from_tensor_slices((x_val, y_val))#
ds_val = ds_val.map(preprocess).batch(batchsz)
sample = next(iter(db))

#模型训练:训练集db,验证集ds_val,训练3epoch,每2个epoch验证一次
history=network.fit(db, epochs=3, validation_data=ds_val, validation_freq=2)#返回训练信息,保存在history中
print(history.history)#查看训练数据
#{'loss': [0.28250920921961464, 0.13529823817014694, 0.10918430316845576],
# 'accuracy': [0.91571665, 0.96241665, 0.9697667], 'val_loss': [0.12126635440737245], 'val_accuracy': [0.9676]}

'''(3)模型预测:'''
#加载一个batch的测试数据
x,y= next(iter(db))
out=network.predict(x)#模型预测,out为网络的输出

'''(4)模型验证:'''
network.evaluate(ds_val)

三、模型保存与加载

  训练时间隔性地保存模型状态是非常好的习惯。
  三种模型保存与加载的方法:

3.1 张量方式–保存权重

  网络的状态主要体现在网络的结构以及网络层内部张量(模型参数)上,因此在拥有网络结构源文件的条件下,直接保存网络张量参数到文件系统上,是轻量级的一种方式。
  语法:
  (1)保存模型参数:Model.save_weights(path),文件名为xxx.ckpt
  (2)加载模型参数:将模型参数写入模型结构Model.load_weights(path)

  这种保存加载网络的方式最为轻量级,文件中仅仅保存的是张量参数的数值,并没有其他额外的结构参数,因此需要相同的网络结构才能够正确恢复网络状态,因此在拥有网络源文件的情况下使用

import  os
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'

import  tensorflow as tf
from    tensorflow.keras import datasets, layers, optimizers, Sequential, metrics

'''(1)获取数据集'''
def preprocess(x, y):
    x = tf.cast(x, dtype=tf.float32) / 255.
    x = tf.reshape(x, [28*28])
    y = tf.cast(y, dtype=tf.int32)
    y = tf.one_hot(y, depth=10)
    return x,y
batchsz = 128
(x, y), (x_val, y_val) = datasets.mnist.load_data()
db = tf.data.Dataset.from_tensor_slices((x,y))
db = db.map(preprocess).shuffle(60000).batch(batchsz)
ds_val = tf.data.Dataset.from_tensor_slices((x_val, y_val))
ds_val = ds_val.map(preprocess).batch(batchsz)
sample = next(iter(db))


'''(2)网络模型构建:'''
network = Sequential([layers.Dense(256, activation='relu'),
                     layers.Dense(128, activation='relu'),
                     layers.Dense(64, activation='relu'),
                     layers.Dense(32, activation='relu'),
                     layers.Dense(10)])
network.build(input_shape=(None, 28*28))

'''(3)模型装配:'''
network.compile(optimizer=optimizers.Adam(lr=0.01),
		loss=tf.losses.CategoricalCrossentropy(from_logits=True),
		metrics=['accuracy']
	)
'''(4)模型训练'''
network.fit(db, epochs=3, validation_data=ds_val, validation_freq=2)
'''(5)模型评估'''
network.evaluate(ds_val)


'''模型参数张量保存'''
network.save_weights('weights.ckpt')

'''网络模型删除'''
del network
'''从新定义网络模型'''
network = Sequential([layers.Dense(256, activation='relu'),
                     layers.Dense(128, activation='relu'),
                     layers.Dense(64, activation='relu'),
                     layers.Dense(32, activation='relu'),
                     layers.Dense(10)])
'''模型装配'''
network.compile(optimizer=optimizers.Adam(lr=0.01),
		loss=tf.losses.CategoricalCrossentropy(from_logits=True),
		metrics=['accuracy']
	)

'''加载模型参数,将模型参数应用在网络结构中'''
network.load_weights('weights.ckpt')#通过重新定义网络结构和加载网络参数张量,将模型复原到训练时的状态
network.evaluate(ds_val)

3.2 网络方式–保存结构和权重

  语法:
  (1)保存模型:Model.save(path),文件名为xxx.h5
  (2)加载模型:恢复整个网络keras.model.load_model(path)

  不需要网络源文件就可以直接恢复模型,包括网络结构和参数张量

import  os
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'

import  tensorflow as tf
from    tensorflow.keras import datasets, layers, optimizers, Sequential, metrics

'''(1)获取数据集'''
def preprocess(x, y):
    x = tf.cast(x, dtype=tf.float32) / 255.
    x = tf.reshape(x, [28*28])
    y = tf.cast(y, dtype=tf.int32)
    y = tf.one_hot(y, depth=10)
    return x,y
batchsz = 128
(x, y), (x_val, y_val) = datasets.mnist.load_data()
db = tf.data.Dataset.from_tensor_slices((x,y))
db = db.map(preprocess).shuffle(60000).batch(batchsz)
ds_val = tf.data.Dataset.from_tensor_slices((x_val, y_val))
ds_val = ds_val.map(preprocess).batch(batchsz)
sample = next(iter(db))


'''(2)网络模型构建:'''
network = Sequential([layers.Dense(256, activation='relu'),
                     layers.Dense(128, activation='relu'),
                     layers.Dense(64, activation='relu'),
                     layers.Dense(32, activation='relu'),
                     layers.Dense(10)])
network.build(input_shape=(None, 28*28))

'''(3)模型装配:'''
network.compile(optimizer=optimizers.Adam(lr=0.01),
		loss=tf.losses.CategoricalCrossentropy(from_logits=True),
		metrics=['accuracy']
	)
'''(4)模型训练'''
network.fit(db, epochs=3, validation_data=ds_val, validation_freq=2)
'''(5)模型评估'''
network.evaluate(ds_val)

'''模型保存:保存了网络结构和张量参数'''
network.save('model2.h5')

'''网络删除'''
del network

'''恢复模型:包括网络结构和网络参数'''
network=tf.keras.models.load_model('model2.h5')

3.3 SavedModel方式–保存结构和权重

  语法:
  (1)保存模型:tf.saved_modle.save(network,path),文件名为xxx,不需要加后缀,但是生成pb格式文件
  (2)加载模型:tf.saved_modle.load(path)

  这种方法保存的模型具有平台无关性,不需要网络源文件就可以直接恢复模型,包括网络结构和参数张量

import  os
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
import  tensorflow as tf
from    tensorflow.keras import datasets, layers, optimizers, Sequential, metrics
'''(1)获取数据集'''
def preprocess(x, y):
    x = tf.cast(x, dtype=tf.float32) / 255.
    x = tf.reshape(x, [28*28])
    y = tf.cast(y, dtype=tf.int32)
    y = tf.one_hot(y, depth=10)
    return x,y
batchsz = 128
(x, y), (x_val, y_val) = datasets.mnist.load_data()
db = tf.data.Dataset.from_tensor_slices((x,y))
db = db.map(preprocess).shuffle(60000).batch(batchsz)
ds_val = tf.data.Dataset.from_tensor_slices((x_val, y_val))
ds_val = ds_val.map(preprocess).batch(batchsz)
sample = next(iter(db))

'''(2)网络模型构建:'''
network = Sequential([layers.Dense(256, activation='relu'),
                     layers.Dense(128, activation='relu'),
                     layers.Dense(64, activation='relu'),
                     layers.Dense(32, activation='relu'),
                     layers.Dense(10)])
network.build(input_shape=(None, 28*28))

'''(3)模型装配:'''
network.compile(optimizer=optimizers.Adam(lr=0.01),
		loss=tf.losses.CategoricalCrossentropy(from_logits=True),
		metrics=['accuracy']
	)
'''(4)模型训练'''
network.fit(db, epochs=3, validation_data=ds_val, validation_freq=2)
'''(5)模型评估'''
network.evaluate(ds_val)

'''模型保存:平台无关'''
tf.saved_model.save(network,'saved_model_pb')

'''网络删除'''
del network

'''恢复模型'''
network=tf.saved_model.load('saved_model_pb')

你可能感兴趣的:(TensorFlow)