1.如何保存 Keras 模型?
不建议使用 pickle 或 cPickle 来保存 Keras 模型。
保存/加载整个模型(结构 + 权重 + 优化器状态)
from keras.models import load_model
model.save('my_model.h5') # 创建 HDF5 文件 'my_model.h5'
del model # 删除现有模型
# 返回一个编译好的模型
# 与之前那个相同
model = load_model('my_model.h5')
只保存/加载 模型的结构
如果您只需要保存模型的结构,而非其权重或训练配置项,则可以执行以下操作:
# 保存为 JSON
json_string = model.to_json()
# 保存为 YAML
yaml_string = model.to_yaml()
# 从 JSON 重建模型:
from keras.models import model_from_json
model = model_from_json(json_string)
# 从 YAML 重建模型:
from keras.models import model_from_yaml
model = model_from_yaml(yaml_string)
只保存/加载 模型的权重
请注意,我们首先需要安装 HDF5 和 Python 库 h5py,它们不包含在 Keras 中。
model.save_weights('my_model_weights.h5')
假设你有用于实例化模型的代码,则可以将保存的权重加载到具有相同结构的模型中:
model.load_weights('my_model_weights.h5')
当然了,如果你需要将权重加载到不同的结构(有一些共同层)的模型中,例如微调或迁移学习,则可以按层的名字来加载权重:
model.load_weights('my_model_weights.h5', by_name=True)
如:微调或迁移学习
"""
假设原始模型如下所示:
model = Sequential()
model.add(Dense(2, input_dim=3, name='dense_1'))
model.add(Dense(3, name='dense_2'))
...
model.save_weights(fname)
"""
# 新模型
model = Sequential()
model.add(Dense(2, input_dim=3, name='dense_1')) # 将被加载
model.add(Dense(10, name='new_dense')) # 将不被加载
# 从第一个模型加载权重;只会影响第一层,dense_1
model.load_weights(fname, by_name=True)
处理已保存模型中的自定义层(或其他自定义对象)
custom_objects ~~
如果要加载的模型包含自定义层或其他自定义类或函数,则可以通过 custom_objects 参数将它们传递给加载机制:
from keras.models import load_model
# 假设你的模型包含一个 AttentionLayer 类的实例
model = load_model('my_model.h5', custom_objects={'AttentionLayer': AttentionLayer})
或者:
from keras.utils import CustomObjectScope
with CustomObjectScope({'AttentionLayer': AttentionLayer}):
model = load_model('my_model.h5')
再如:
from keras.models import model_from_json
model = model_from_json(json_string, custom_objects={'AttentionLayer': AttentionLayer})
如何获取中间层的输出?
方法一:创建一个新的模型来输出你所感兴趣的层:
取网络中间的某个部分作为中间层模型。之后,对数据进行预测。
from keras.models import Model
model = ... # 创建原始模型
layer_name = 'my_layer'
intermediate_layer_model = Model(inputs=model.input,
# 创建模型的时候,需要说明input 和 output是什么 outputs=model.get_layer(layer_name).output)
intermediate_output = intermediate_layer_model.predict(data)
方法二:
构建一个 Keras 函数,该函数将在给定输入的情况下返回某个层的输出。
from keras import backend as K
# 获取中间层的输出
# 以 Sequential 模型为例
get_3rd_layer_output = K.function([model.layers[0].input],
[model.layers[3].output])
layer_output = get_3rd_layer_output([x])[0]
注意,如果你的模型在训练和测试阶段有不同的行为(例如,使用 Dropout, BatchNormalization 等),则需要将学习阶段标志传递给你的函数:
get_3rd_layer_output = K.function([model.layers[0].input, K.learning_phase()],
[model.layers[3].output])
# 在不同的阶段有不同的行为 ,需要标明处于哪个阶段
# 测试模式 = 0 时的输出
layer_output = get_3rd_layer_output([x, 0])[0]
# 测试模式 = 1 时的输出
layer_output = get_3rd_layer_output([x, 1])[0]
如何用 Keras 处理超过内存的数据集?
方法一:
# 批量训练与测试
model.train_on_batch(x,y)
model.test_on_batch(x,y)
方法二:
可以编写一个生成批处理训练数据的生成器,Then
model.fit_generator(data_generator,steps_per_epoch,epochs)
在验证集的误差不再下降时,如何中断训练?
使用 EarlyStopping 回调函数。
from keras.callbacks import EarlyStopping
early_stopping = EarlyStopping(monitor='val_loss', patience=2)
model.fit(x, y, validation_split=0.2, callbacks=[early_stopping])
验证集划分是如何计算的?
model.fit 中的 validation_split 参数设置为 0.1,那么使用的验证数据将是最后 10% 的数据。注意,在提取分割验证集之前,数据不会被混洗,因此验证集仅仅是传递的输入中最后一个 x% 的样本。
在同一个 fit 中调用,所有epoch都使用相同的验证集。
在训练过程中数据是否会混洗?
是的,如果 model.fit中的 shuffle参数设置为 True(默认值),则训练数据将在每个 epoch 混洗。
哦哦~~,训练数据默认是进行混洗的。But,
验证集永远不会混洗。
如何在每个 epoch 后记录训练集和验证集的误差和准确率?
hist = model.fit(x, y, validation_split=0.2)
print(hist.history)
如何「冻结」网络层?
「冻结」一个层意味着将其排除在训练之外,即其权重将永远不会更新。这在微调模型时很有用。
可以将 trainable 参数(布尔值)传递给一个层的构造器,以将该层设置为不可训练的:
冻结意味着该层不可以训练。
frozen_layer = Dense(32, trainable=False)
冻结一个层
x = Input(shape=(32,))
layer = Dense(32)
layer.trainable = False
y = layer(x)
frozen_model = Model(x, y)
# 在下面的模型中,训练期间不会更新层的权重
frozen_model.compile(optimizer='rmsprop', loss='mse')
layer.trainable = True
trainable_model = Model(x, y)
# 使用这个模型,训练期间 `layer` 的权重将被更新
trainable_model.compile(optimizer='rmsprop', loss='mse')
frozen_model.fit(data, labels) # 这不会更新 `layer` 的权重
trainable_model.fit(data, labels) # 这会更新 `layer` 的权重
如何使用有状态 RNN (stateful RNNs)?
使 RNN 具有状态意味着每批样品的状态将被重新用作下一批样品的初始状态。
# 输入数据,尺寸为 (32, 21, 16)
# 将步长为 10 的序列输送到模型中
model = Sequential()
model.add(LSTM(32, input_shape=(10, 16), batch_size=32, stateful=True))
model.add(Dense(16, activation='softmax'))
model.compile(optimizer='rmsprop', loss='categorical_crossentropy')
# 训练网络,根据给定的前 10 个时间步,来预测第 11 个时间步:
model.train_on_batch(x[:, :10, :], np.reshape(x[:, 10, :], (32, 16)))
# 网络的状态已经改变。我们可以提供后续序列:
model.train_on_batch(x[:, 10:20, :], np.reshape(x[:, 20, :], (32, 16)))
# 重置 LSTM 层的状态:
model.reset_states()
# 另一种重置方法:
model.layers[0].reset_states()
如何从 Sequential 模型中移除一个层?
可以通过调用 .pop() 来删除 Sequential 模型中最后添加的层:
model = Sequential()
model.add(Dense(32, activation='relu', input_dim=784))
model.add(Dense(32, activation='relu'))
print(len(model.layers)) # "2"
model.pop()
print(len(model.layers)) # "1"
如何在 Keras 中使用预训练的模型?
预训练的模型包括有:
Xception
VGG16
VGG19
ResNet50
Inception v3
Inception-ResNet v2
MobileNet v1
它们可以使用 keras.applications 模块进行导入:
from keras.applications.xception import Xception
from keras.applications.vgg16 import VGG16
from keras.applications.vgg19 import VGG19
from keras.applications.resnet50 import ResNet50
from keras.applications.inception_v3 import InceptionV3
from keras.applications.inception_resnet_v2 import InceptionResNetV2
from keras.applications.mobilenet import MobileNet
model = VGG16(weights='imagenet', include_top=True)
如何在 Keras 中使用 HDF5 输入?
方法一:用的是keras.utils.io_utils 中的 HDF5Matrix 类。
方法二:直接使用HDF5数据集。
import h5py
with h5py.File('input/file.hdf5', 'r') as f:
x_data = f['x_data']
model.predict(x_data)
Keras 配置文件保存在哪里?
默认目录是:
$HOME/.keras/
Keras配置文件是存储在 $HOME/.keras/keras.json 中的 JSON 文件。
{
"image_data_format": "channels_last",
# 用于防止在某些操作中被零除的 epsilon 模糊因子
"epsilon": 1e-07,
"floatx": "float32",
"backend": "tensorflow"
}
用get_file()下载的文件,默认存储在$HOME/.keras/datasets/ 中。这时缓存的数据集文件。
如何在 Keras 开发过程中获取可复现的结果?
设定随机种子
import numpy as np
import tensorflow as tf
import random as rn
import os
os.environ['PYTHONHASHSEED'] = '0'
np.random.seed(42) # numpy
rn.seed(12345) # python
# 强制 TensorFlow 使用单线程。
session_conf = tf.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1)
from keras import backend as K
# 在一个明确的初始状态下生成固定随机数字。
# 将会以 TensorFlow 为后端
tf.set_random_seed(1234)
sess = tf.Session(graph=tf.get_default_graph(), config=session_conf)
K.set_session(sess)