1、构建模型
1.1、Sequential model
model = keras.Sequential()
# Adds a densely-connected layer with 64 units to the model:
model.add(keras.layers.Dense(64, activation='relu'))
# Add another:
model.add(keras.layers.Dense(64, activation='relu'))
# Add a softmax layer with 10 output units:
model.add(keras.layers.Dense(10, activation='softmax'))
1.2、使用 Keras functional API 可以构建有复杂拓扑结构的模型
tf.keras.Sequential 模型只适用于多层简单堆叠网络,通过使用 Keras functional API 可以构建有复杂拓扑结构的模型,
层实例可调用并返回张量。输入 tensors 和输出 tensors 被用来定义一个 tf.keras.Model 实例
inputs = keras.Input(shape=(32,)) # Returns a placeholder tensor
# A layer instance is callable on a tensor, and returns a tensor.
x = keras.layers.Dense(64, activation='relu')(inputs)
x = keras.layers.Dense(64, activation='relu')(x)
predictions = keras.layers.Dense(10, activation='softmax')(x)
# 输入tensor和输出tensor被用来定义一个tf.keras.Model的实例
model = keras.Model(inputs=inputs, outputs=predictions)
# The compile step specifies the training configuration.
model.compile(optimizer=tf.train.RMSPropOptimizer(0.001),
loss='categorical_crossentropy',
metrics=['accuracy'])
# Trains for 5 epochs
model.fit(data, labels, batch_size=32, epochs=5)
1.3、Model subclassing
通过继承tf.keras.Model并定义自己的前向传递来构建完全可自定义的模型。 在init方法中创建图层并将它们设置为类实例的属性。 在call方法中定义正向传递。例如下面的代码定义ResNet,其中,我们适应Layer类来定义内部就散块,并使用Model类来定义外部模型,即要训练的对象。
class BasicBlock(layers.Layer):
def __init__(self,filter_num,stride=1):
super(BasicBlock,self).__init__()
self.conv1=layers.Conv2D(filter_num,(3,3),strides=stride,padding="same")
self.bn1 = layers.BatchNormalization()
self.relu = layers.Activation("relu")
self.conv2 = layers.Conv2D(filter_num, (3, 3), strides=1, padding="same")
self.bn2 = layers.BatchNormalization()
if stride !=1:
self.downsample = Sequential()
self.downsample.add(layers.Conv2D(filter_num,(1,1),strides=stride))
else:
self.downsample =lambda x:x
def call(self,inputs,training=None):
out = self.conv1(inputs)
out = self.bn1(out)
out =self.relu(out)
out = self.conv2(out)
out = self.bn2(out)
identity = self.downsample(inputs)
output = layers.add([out,identity])
output = tf.nn.relu(output)
return output
class ResNet(keras.Model):
def __init__(self,layer_dims,num_classe=100):
super(ResNet,self).__init__()
#预处理层
self.stem = Sequential([layers.Conv2D(64,(3,3),strides=(1,1)),
layers.BatchNormalization(),
layers.Activation("relu"),
layers.MaxPool2D(pool_size=(2,2),strides=(1,1),padding="same")])
self.layer1 = self.build_resblock(64,layer_dims[0])
self.layer2 = self.build_resblock(128, layer_dims[1],stride=2)
self.layer3 = self.build_resblock(256, layer_dims[2], stride=2)
self.layer4 = self.build_resblock(512, layer_dims[3], stride=2)
self.avgpool = layers.GlobalAveragePooling2D()
self.fc = layers.Dense(num_classe)
self.num_classes=num_classe
def call(self, inputs, training=None):
x = self.stem(inputs)
x = self.layer1(x)
x = self.layer2(x)
x = self.layer3(x)
x = self.layer4(x)
x = self.avgpool(x)
x = self.fc(x)
return x
def build_resblock(self,filter_num,blocks,stride=1):
#filter_num是卷积核的数量,blocks是basic_block的数量
res_blocks=Sequential()
res_blocks.add(BasicBlock(filter_num,stride))
for _ in range(1,blocks):
res_blocks.add(BasicBlock(filter_num,stride=1))
return res_blocks
2、训练:
2.1、构建模型后,通过调用compile方法配置其训练过程
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
- optimizer:训练过程的优化方法。此参数通过 tf.train 模块的优化方法的实例来指定,比如:AdamOptimizer, RMSPropOptimizer, GradientDescentOptimizer
- loss:训练过程中使用的损失函数(通过最小化损失函数来训练模型)。 常见的选择包括:均方误差(mse),categorical_crossentropy和binary_crossentropy。 损失函数由名称或通过从tf.keras.losses模块传递可调用对象来指定。
- metrics:训练过程中,监测的指标(Used to monitor training)。指定方法:名称 或 可调用对象 from the tf.keras.metrics 模块。
2.2、模型使用 fit 方法训练数据:
model_train=model.fit(train_images,train_labels,batch_size=2,epochs=5,validation_split=0.1)
- epochs:训练多少轮。(小批量)
- batch_size:当传递NumPy数据时,模型将数据分成较小的批次,并在训练期间迭代这些批次。 此整数指定每个批次的大小。 请注意,如果样本总数不能被批量大小整除,则最后一批可能会更小。
- validation_data:在对模型进行原型设计时,您希望轻松监控其在某些验证数据上的性能。 传递这个参数 - 输入和标签的元组 - 允许模型在每个epoch的末尾以传递数据的推理模式显示损失和度量
2.3、model.fit_generator()
利用Python的生成器,逐个生成数据的batch并进行训练。生成器与模型将并行执行以提高效率。例如,该函数允许我们在CPU上进行实时的数据提升,同时在GPU上进行模型训练。各个参数参考Keras中文文档
3、回调
Keras中的回调是在训练期间在不同点(在epoch开始时,batch结束时,epoch结束时等)调用的对象,
可使用的内置回调有:
- ModelCheckpoint:定期保存模型
- EarlyStopping:当训练不再改进验证指标时停止训练
- TensorBoard:定期编写可在TensorBoard中显示的模型日志
- CSVLogger:将丢失和指标数据流式传输到CSV文件
- ……
回调使用示例
model = XXX()
callbacks = [
keras.callbacks.EarlyStopping( # 当训练不再改变停止目标的时候停止训练
monitor='val_loss', # 当val_loss不再改善的时候停止训练
min_delta=1e-2, # 不再改善定义为下降小于1e-2
patience=2, # 不再改善进一步定义为两个epochs
verbose=1)
]
model.fit(x_train, y_train,
epochs=20,
batch_size=64,
callbacks=callbacks,
validation_split=0.2)
4、保存模型
4.1、保存整个模型
# Create a trivial model
model = keras.Sequential([
keras.layers.Dense(10, activation='softmax', input_shape=(32,)),
keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
model.fit(data, targets, batch_size=32, epochs=5)
# Save entire model to a HDF5 file
model.save('my_model.h5')
# Recreate the exact same model, including weights and optimizer.
model = keras.models.load_model('my_model.h5')
注意:如果是通过继承 tf.keras.Model来定义自己的前向传递来构建完全可自定义的模型,则不能通过model.save(‘my_model.h5’)来保存模型。将一个模型保存为HDF5格式的时候,需要模型是Functional模型或者是Sequential模型。他不能工作在subclassed 模型上,可以保存为Tensorflow SavedModel format(通过设置save_format=“tf”)或者使用save_weights来保存模型。 会发生以下错误:
4.2、保存权重
使用 tf.keras.Model.save_weights 来保存和加载模型的 weights
默认情况下保存的是TensorFlow checkpoint格式的文件
# Save weights to a TensorFlow Checkpoint file
model.save_weights('./my_model')
# Restore the model's state,
# this requires a model with the same architecture.
model.load_weights('my_model')
也可以保存为HDF5格式的文件
# Save weights to a HDF5 file
model.save_weights('my_model.h5', save_format='h5')
# Restore the model's state
model.load_weights('my_model.h5')
4.3、保存配置
一个模型的 configuration 可以被保存,序列化过程中不包含任何 weights。保存的 configuration 可以用来重新创建、初始化出相同的模型,即使没有模型原始的定义代码。Keras 支持 JSON,YAML 序列化格式:
# Serialize a model to JSON format
json_string = model.to_json()
# Recreate the model (freshly initialized)
fresh_model = keras.models.model_from_json(json_string)
# Serializes a model to YAML format
yaml_string = model.to_yaml()
# Recreate the model
fresh_model = keras.models.model_from_yaml(yaml_string)