对于常见的神经网络层,可以使用张量方式的底层接口函数来实现,这些接口函数一般在 tf.nn 模块中。更常用地,对于常见的网络层,我们一般直接使用层方式来完成模型的搭建,在 tf.keras.layers 命名空间(下文使用 layers 指代 tf.keras.layers)中提供了大量常见网络层的类接口,如全连接层,激活含水层,池化层,卷积层,循环神经网络层等等。对于这些网络层类,只需要在创建时指定网络层的相关参数,并调用__call__方法即可完成前向计算。在调用__call__方法时,Keras 会自动调用每个层的前向传播逻辑,这些逻辑一般实现在类的 call 函数中。
1、网络容器 Sequential
将多个网络层封装成一个大网络模型,只需要调用网络模型的实例一次即可完成数据从第一层到最末层的顺序运算。
from tensorflow.keras import layers, Sequential
network = Sequential([ # 封装为一个网络
layers.Dense(3, activation=), # 全连接层
layers.ReLU(),#激活函数层
layers.Dense(2, activation=None), # 全连接层
layers.ReLU() #激活函数层
])
x = tf.random.normal([4,3])
1、Sequential 容器也可以通过 add()方法继续追加新的网络层,实现动态创建网络的功能
2、此时通过调用类的build 方法并指定输入大小,即可自动创建所有层的内部张量
3、通过summary()函数可以方便打印出网络结构和参数量
4、Sequential 对象的trainable_variables 和variables 包含了所有层的待优化张量列表和全部张量列表
layers_num = 2 # 堆叠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() #打印参数信息
2、metrics
metrics的建立
acc_meter = metrics.Accuracy()
loss_meter = metrics.Mean()
metrics添加数据
loss_meter.update_state(loss)
acc_meter.update_state(y, pred)
metrics打印和清空
print(step, 'loss:', loss_meter.result().numpy())
loss_meter.reset_states()
print(step, 'Evaluate Acc:', total_correct/total, acc_meter.result().numpy())
acc_meter.update_state(y, pred)
3、complile
在没有compile之前,神经网络的顺序如下:
# 定义model
#for 循环
with tf.GradientTape() as tape: #向前传播
logits = model(x)
loss_mse = tf.reduce_mean(tf.losses.MSE(y, logits)) #计算loss
grads = tape.gradient(loss_mse, model.trainable_variables) #计算梯度
optimizer.apply_gradients(zip(grads, model.trainable_variables)) #优化参数
# test
这一部分逻辑由于非常通用,在keras 中提供了compile()和fit()函数方便实现上述逻辑。首先通过compile 函数指定网络使用的优化器对象,损失函数,评价指标等。
from tensorflow.keras import optimizers,losses
# 采用Adam 优化器,学习率为0.01;采用交叉熵损失函数,包含Softmax
network.compile(optimizer=optimizers.Adam(lr=0.01),
loss=losses.CategoricalCrossentropy(from_logits=True),
metrics=['accuracy'] # 设置测量指标为准确率
)
history = network.fit(train_db, epochs=5, validation_data=val_db, validation_freq=2) #模型训练
# 其中train_db 为tf.data.Dataset 对象,也可以传入Numpy Array 类型的数据;
# epochs 指定训练迭代的epochs 数
# validation_data=val_db 制定测试数据
# validation_freq=2 测试数据的频率
4、模型的保存于加载
save/load weight
save/load entire model
saved_model
network.save_weight('./chechpoint.ckpt')
network.load_weights('./chechpoint.ckpt')
network.save('model.h5')
network = tf.keras.models.load_model('model.h5', compile=False)
network.compile(optimizer=optimizers.Adam(lr=0.01),
loss=tf.losses.CategoricalCrossentropy(from_logits=True),
metrics=['accuracy']
tf.keras.experimental.export_saved_model(network, path)
即可将模型以SavedModel方式保存到path 目录
tf.keras.experimental.export_saved_model(network, 'model-savedmodel')
network = tf.keras.experimental.load_from_saved_model('model-savedmodel')
5、自定义网络层
class MyDense(layers.Layer):
def __init__(self, inp_dim, outp_dim):
super(MyDense, self).__init__()
self.kernel = self.add_weight('w', [inp_dim, outp_dim])
self.bias = self.add_weight('b', [outp_dim])
def call(self, inputs, training=None):
out = inputs @ self.kernel + self.bias
return out
class MyModel(keras.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)
def call(self, inputs, training=None):
x = self.fc1(inputs)
x = tf.nn.relu(x)
x = self.fc2(x)
x = tf.nn.relu(x)
x = self.fc3(x)
x = tf.nn.relu(x)
x = self.fc4(x)
x = tf.nn.relu(x)
x = self.fc5(x)
return x
network = MyModel()
network.compile(optimizer=optimizers.Adam(lr=0.01),
loss=tf.losses.CategoricalCrossentropy(from_logits=True),
metrics=['accuracy']
)
network.fit(db, epochs=5, validation_data=ds_val,
validation_freq=2)
network.evaluate(ds_val)