First of all, Keras != tf.keras.
Custom Layers
详见Code
- keras.Sequential
- keras.layers.Layer
- keras.Model
- model.trainable_variables
- model.call()
自定义层需要继承tf.keras.layers.Layer
类,并重写__init__
、build
和call
三个方法
class LinearLayer(tf.keras.layers.Layer):
def __init__(self, units):
super().__init__()
self.units = units
def build(self, input_shape): # 这里 input_shape 是第一次运行call()时参数inputs的形状
self.w = self.add_variable(name='w',
shape=[input_shape[-1], self.units], initializer=tf.zeros_initializer())
self.b = self.add_variable(name='b',
shape=[self.units], initializer=tf.zeros_initializer())
def call(self, inputs):
y_pred = tf.matmul(inputs, self.w) + self.b
return y_pred
# 使用自定义的层构建模型
class LinearModel(tf.keras.Model):
def __init__(self):
super().__init__()
self.layer = LinearLayer(units=1)
def call(self, inputs):
output = self.layer(inputs)
return output
Layer/Model
- inherit from
keras.layers.Layer
,keras.Model
__init__
call()
- Model: compile/fit/evaluate
Sequential API
可以使用Sequential方式建立模型,但是这种层叠结构不能表示任意的神经网络结构
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(100, activation=tf.nn.relu),
tf.keras.layers.Dense(2),
tf.keras.layers.Softmax()
])
Functional API
inputs = tf.keras.Input(shape=(28, 28, 1))
x = tf.keras.layers.Flatten()(inputs)
x = tf.keras.layers.Dense(units=100, activation=tf.nn.relu)(x)
x = tf.keras.layers.Dense(units=10)(x)
outputs = tf.keras.layers.Softmax()(x)
model = tf.keras.Model(inputs=inputs, outputs=outputs)
Compile & Fit
详见Code
- compile
- fit
- evaluate
- predict
可以使用Keras Model
的compile
、fit
和evaluate
方法训练和评估模型,当模型建立完成后,通过tf.keras.Model
的compile
方法配置训练过程:
model.compile(
optimizer=tf.keras.optimizers.Adam(learning_rate=0.001),
loss=tf.keras.losses.sparse_categorical_crossentropy,
metrics=[tf.keras.metrics.sparse_categorical_accuracy]
)
tf.keras.Model.compile 接受 3 个重要的参数:
- optimizer :优化器,可从
tf.keras.optimizers
中选择 - loss :损失函数,可从
tf.keras.losses
中选择 - metrics :评估指标,可从
tf.keras.metrics
中选择
接下来,可以使用tf.keras.Model
的fit
方法训练模型:
model.fit(data_loader.train_data, data_loader.train_label, epochs=num_epochs, batch_size=batch_size)
tf.keras.Model.fit
接受 5 个重要的参数:
- x :训练数据;
- y :目标数据(数据标签);
- epochs :将训练数据迭代多少遍;
- batch_size :批次的大小;
- validation_data :验证数据,可用于在训练过程中监控模型的性能。
最后,使用tf.keras.Model.evaluate
评估训练效果,提供测试数据及标签即可:
print(model.evaluate(data_loader.test_data, data_loader.test_label))
Metrics
详见Code
- metrics
- update_state
- result().numpy()
- reset_states
自定义损失函数和评估指标
自定义损失函数需要继承tf.keras.losses.Loss
类,重写call
方法即可,输入真实值y_true
和模型预测值y_pred
,输出模型预测值和真实值之间通过自定义的损失函数计算出的损失值。下面的示例为均方差损失函数:
class MeanSquaredError(tf.keras.losses.Loss):
def call(self, y_true, y_pred):
return tf.reduce_mean(tf.square(y_pred - y_true))
自定义评估指标需要继承tf.keras.metrics.Metric
类,并重写__init__
、update_state
和result
三个方法。下面的示例对前面用到的SparseCategoricalAccuracy
评估指标类做了一个简单的重实现:
class SparseCategoricalAccuracy(tf.keras.metrics.Metric):
def __init__(self):
super().__init__()
self.total = self.add_weight(name='total', dtype=tf.int32, initializer=tf.zeros_initializer())
self.count = self.add_weight(name='count', dtype=tf.int32, initializer=tf.zeros_initializer())
def update_state(self, y_true, y_pred, sample_weight=None):
values = tf.cast(tf.equal(y_true, tf.argmax(y_pred, axis=-1, output_type=tf.int32)), tf.int32)
self.total.assign_add(tf.shape(y_true)[0])
self.count.assign_add(tf.reduce_sum(values))
def result(self):
return self.count / self.total
Save and Load Models
详见Save and load weights 详见Save and load models
save/load weights:
- 仅仅保存模型的权重参数,不包括整个网络结构,因此load权重之前需要重新compile一样结构的模型
# Save the weights model.save_weights('./checkpoints/my_checkpoint') # Restore the weights model = create_model() model.load_weights('./checkpoints/my_checkpoint') loss, acc = model.evaluate(test_images, test_labels)
save/load entire model:
- 保存整个网络结构和权重,不需要重新定义模型结构
network.save('model.h5) print('saved total model.) del network print('load model from file') network = tf.keras.model.load_model('model.h5') network.evaluate(v_val, y_val)
saved_model
- 主要是用来进行生产环境的部署,ONNX的通用模型格式
# 生产环境部署 print('Save served model') tf.saved_model.save(network, './model/server_model') print('Delete model') del network print('Load served model') imported = tf.saved_model.load('./model/server_model') f = imported.signatures['serving_default'] # 直接inference输出预测结果 # 随机生成一个全是1的张量 pred = f(input_1=tf.ones([1, 784])) print(tf.argmax(pred['output_1'], axis=1)) # 抽取ds_val中第一张图片,扩展为一个张量 pred = f(input_1=tf.expand_dims(sample[0][0], axis=0)) # 需要扩展为[1, 784] print(tf.argmax(pred['output_1'], axis=1)) # 实际label print(tf.argmax([sample[1][0]], axis=1))
Reference
Note: Cover Picture