TF-char8-Keras高层接口

2021-03-02 16:24:02 浏览数 (1)

Char8-Keras高层接口

第八章中讲解的是高层接口Keras的使用。Keras的几个特点

  • Python语言开发
  • 前后端分离
    • 后端基于现有的TF、CNTK等框架
    • 前端有自己的接口API
  • TF的高层唯一API接口
  • Keras被实现在tf.keras子模块中

常见功能模块

Keras提供常见的神经网络类和函数

  • 数据集加载函数
  • 网络层类
  • 模型容器
  • 损失函数
  • 优化器类
  • 经典模型
常见网络层
  1. 张量方式tf.nn模块中
  2. 层方式tf.keras.layers提供大量的接口,需要完成__call__()
    1. 全连接层
    2. 激活含水层
    3. 池化层
    4. 卷积层
代码语言:javascript复制
import tensorflow as tf
from tensorflow import keras # 导入keras模型,不能使用import keras,它导入的是标准的Keras库
from tensorflow.keras import layers  # 导入常见的网络层类
x = tf.constant([1,2,3.0,4.0])
layer = layers.Softmax(axis=-1)  # 创建Softmax层
layer(x)  # 调用softmax前向计算
网络容器

主要使用的Sequential

2层全连接层加上激活函数层通过Sequntial容器构成一个网络

代码语言:javascript复制
import tensorflow as tf
from tensorflow.keras import layers, Sequential

network = Sequential([  # 封装一个网格
  layer.Dense(3, activation=None), # 指定全连接层和激活函数层
  layer.ReLU(),
  layer.Dense(2, activation=None),
  layer.ReLU()
])

x = tf.random.normal([4,3])
network(x)   # 输入从第一层开始,逐层传播至最后一层


# 通过add()方法追加新的网络层
layers_num = 2
network = Sequential([])  # 先创建空的网格
for _ in range(layers_num):
  # 添加两个层:全连接层和激活函数层
  network.add(layers.Dense(3))
  network.add(layers.ReLU())

network.build(input_shape=(None, 4)) # 指定网格参数
network.summary()  # 打印出网络结构和参数量


for p in network.trainable_variables:  # 常看待优化的张量列表
  print(p.name, p.shape)

模型装配、训练和测试

装配

通过两个主要的类实现:

  • keras.Model,网络的母类,Sequentail类是其子类
  • keras.layers.Layer,网络层的母类

通过compile()函数指定优化器、损失函数等

代码语言:javascript复制
# 创建全连接层网络
network = Sequntial([layers.Dense(256, activition='relu'),
                     layers.Dense(128, activition='relu'),
                     layers.Dense(64, activition='relu'),
                     layers.Dense(32, activition='relu'),
                     layers.Dense(10)])

# 指定网格参数和查看网络结构和参数量
network.build(input_shape=None, 28*28)
network.summary()

# 导入优化器和损失模块
from tensorflow.keras import optimisers, losses
# 采用Adam优化器,学习率为0.01,采用交叉熵损失函数
network.compile(optimizer=optimizers.Adam(lr=0.01),
               loss=losses.CategoricalCrossentropy(from_logtis=-True),
               metrics=['accuracy'])# 设置测量指标为准确率
训练

通过fit()函数实现

  • train_dbtf.data_Dataset对象
  • epoch:训练5个epoch,每2个epoch验证一次
代码语言:javascript复制
history = network.fit(train_db, epoch=5, validation=val_db,validation_freq=2)
history.history # 打印训练记录
测试
代码语言:javascript复制
x, y = next(iter(db_test))
out = network.predict(x)  # 模型预测,out为网络输出
print(out)
network.evaluate(db_test)  # 模型测试

模型加载

张量方式

文件中保存的仅仅是参数张量的数值,没有其他的结构参数,需要使用相同的网络结构才能恢复网络数据,一般在拥有源文件的情况下使用。

代码语言:javascript复制
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)])

# 采用Adam优化器,学习率为0.01,采用交叉熵损失函数
network.compile(optimizer=optimizers.Adam(lr=0.01),
               loss=losses.CategoricalCrossentropy(from_logtis=-True),
               metrics=['accuracy'])# 设置测量指标为准确率

# 从参数文件总读取并且保存到当前网络中
network.load_weights('weigts.ckpt')
网络方式
  • 不需要网络源文件
  • 仅仅是需要模型参数文件就可以恢复网络模型
  • 通过Model.save()
代码语言:javascript复制
network.save('model.h5')
del network

network = tf.keras.models.load_model('model.h5')
SaveModel方式

通过 tf.keras.experimental.export_saved_model(network, path)即可将模型以 SavedModel 方式保存到 path 目录中:

代码语言:javascript复制
tf.keras.experimental.export_saved_model(network, 'model-savedmodel')  # 保存模型结构与参数
del network

# 从文件中恢复网络
network = tf.keras.experimental.load_from_saved_model('model-savedmodel')

自定义类

自定义网络类

需要实现call()__init__()方法

代码语言:javascript复制
# 初始化工作
class MyDense(layers.Layer): # 继承关系
  def __init__(self, inp_dim, outp_dim):
    super(MyDense, self).__init__()
    self.kernel = self.add__variable('w', [inp_dim, outp_dim], trainable=True)   # True表示张量需要被优化

net = MyDense(4,3)
print(net.variables)

# 实现前项运算逻辑
	def call(self, inputs, training=None):  # training为T执行训练模式,F为测试模式默认是None
  	out = inputs @ self.kernel
  	out = tf.nn.relu(out)
自定义网络
代码语言:javascript复制
network = Squential([MyDense(784, 256),  #  使用自定义的网络类MyDense
                    MyDense(256, 128),
                    MyDense(128, 64),
                    MyDense(64, 32),
                    MyDense(32, 10)])
network.build(input_shape(None, 28*28))
  • 通过堆叠使用自定义的网络类
  • 5层全连接没有偏置张量,同时使用激活啊函数ReLU
使用基类实现

​ 可以继承基类来实现任意逻辑的自定义网络类

代码语言:javascript复制
class MyModel(keras.Model):
  # 自定义网络类,继承自Model基类
  def __init__(self):
    super(MyModel, self).__init__():
      self.fc1 = MyDense(28*28, 256)
			self.fc2 = MyDense(256, 128)
			self.fc3 = MyDense(128, 64)
			self.fc4 = MyDense(64, 32)
			self.fc5 = MyDense(32, 10)

  # 实现自定义网络的前向运算逻辑
  # 经过5层网络
  x = self.fc1(inputs)
  x = self.fc2(x)
  x = self.fc3(x)
  x = self.fc4(x)
  x = self.fc5(x)

  return x

测量工具

  • 新建测量器loss_meter = metrics.Mean()
  • 写入数据loss_meter.update_state(float(loss))
  • 读取统计信息loss_meter.result()
  • 清除历史状态的信息loss_meter.reset_states()

可视化

  • TensorBoard
  • Visdom
模型端

需要写入监控数据、图片数据、查看数据的直方分布图、文本信息。

代码语言:javascript复制
# 监控标量数据
summary_writter= tf.summary.create_file_writer(log_dir)
with summary_writer.as_default():
  tf.summary.scalar('train-loss', float(loss), step=step)

# 监控图片数据
with summary_writer.as_default():
  tf.summmary.scalar('test-acc', float(total_correct/total), step=step)
  tf.summary.image('val-onebyone-images:', val_images, max_outputs=9, step=step)
浏览器端

通过tensorboard --logdir path来指定web后端监控的文件目录,浏览器端口默认是6006

代码语言:javascript复制
# 查看张量的数据脂肪分布图和打印文本信息
with summary_writer.as_defualt():
  # 当前时间戳 step 上的数据为 loss,写入到 ID 位 train-loss 对象中
  tf.summary.scalar('train-loss', float(loss), step=step) # 可视化真实标签的直方图分布
  tf.summary.histogram('y-hist',y, step=step)
  tf.summary.text('loss-text',str(float(loss)))  # 查看文本信息

0 人点赞