【Keras】学习笔记8:多层感知器进阶

1、JSON序列化模型

JSON是一种轻量级数据交换格式。
Keras提供了to_json()函数生成模型的JSON描述,并将模型的JSON描述保存到文件中。反序列化时,通过model_from_json()函数加载JSON描述,并编译成模型,从而可以将模型部署到生产环境,并使用模型对新数据进行预测。使用save_weight()函数可以保存模型的权重值,并在加载模型时使用load_weights()函数加载模型的权重信息。
当有新数据需要预测时,从保存的文件加载的模型和权重信息,并创建一个新的模型,通过加载模型的方式建立新的模型后,必须先进行编译模型,然后使用加载后的模型对新数据进行预测。如果使用相同的评估方式来评估从文件加载的模型,可以得到与模型建立时相同结果。
下面的的例子中使用鸢尾花数据集训练一个神经网络模型,使用JSON格式描述模型的结构,并保存到本地目录中的model.json文件中,权重信息保存在本地目录中的model.json.h5文件中。代码如下:

from sklearn import datasets
import numpy as np
from keras.models import Sequential
from keras.layers import Dense
from keras.utils import to_categorical
from keras.models import model_from_json


# 导入数据
dataset = datasets.load_iris()

x = dataset.data
Y = dataset.target

# Convert labels to categorical one-hot encoding  将标签转换成分类编码
Y_labels = to_categorical(Y, num_classes=3)

# 设定随机种子
seed = 7
np.random.seed(seed)
# 构建模型函数
def create_model(optimizer='rmsprop', init='glorot_uniform'):
    # 构建模型
    model = Sequential()
    model.add(Dense(units=4, activation='relu', input_dim=4, kernel_initializer=init))
    model.add(Dense(units=6, activation='relu', kernel_initializer=init))
    model.add(Dense(units=3, activation='softmax', kernel_initializer=init))

    # 编译模型
    model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=['accuracy'])

    return model

# 构建模型
model = create_model()
model.fit(x, Y_labels, epochs=200, batch_size=5, verbose=0)

scores = model.evaluate(x, Y_labels, verbose=0)
print('%s: %.2f%%' % (model.metrics_names[1], scores[1] * 100))

# 模型保存成Json文件
model_json = model.to_json()
with open('model.json', 'w') as file:
    file.write(model_json)

# 保存模型的权重值
model.save_weights('model.json.h5')


# 从Json加载模型
with open('model.json', 'r') as file:
    model_json = file.read()

# 加载模型
new_model = model_from_json(model_json)
new_model.load_weights('model.json.h5')

# 编译模型
new_model.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy'])

# 评估从Json加载的模型
scores = new_model.evaluate(x, Y_labels, verbose=0)
print('%s: %.2f%%' % (model.metrics_names[1], scores[1] * 100))

2、YAML序列化模型

YAML是一种能够被电脑识别的直观的数据序列化格式。
此实例与上述JSON实例大致相同,但是采取YAML格式来描述模型。下面直接使用模型的to_yaml()函数将模型保存在model.yaml文件中,并通过model_from_yaml()函数来加载模型。权重的处理依然采用HDF 5格式,保存为model.yaml.h5文件,代码如下:

from sklearn import datasets
import numpy as np
from keras.models import Sequential
from keras.layers import Dense
from keras.utils import to_categorical
from keras.models import model_from_yaml


# 导入数据
dataset = datasets.load_iris()

x = dataset.data
Y = dataset.target

# Convert labels to categorical one-hot encoding     将标签转换成分类编码
Y_labels = to_categorical(Y, num_classes=3)

# 设定随机种子
seed = 7
np.random.seed(seed)
# 构建模型函数
def create_model(optimizer='rmsprop', init='glorot_uniform'):
    # 构建模型
    model = Sequential()
    model.add(Dense(units=4, activation='relu', input_dim=4, kernel_initializer=init))
    model.add(Dense(units=6, activation='relu', kernel_initializer=init))
    model.add(Dense(units=3, activation='softmax', kernel_initializer=init))

    # 编译模型
    model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=['accuracy'])

    return model

# 构建模型
model = create_model()
model.fit(x, Y_labels, epochs=200, batch_size=5, verbose=0)

scores = model.evaluate(x, Y_labels, verbose=0)
print('%s: %.2f%%' % (model.metrics_names[1], scores[1] * 100))

# 模型保存成Json文件
model_yaml = model.to_yaml()
with open('model.yaml', 'w') as file:
    file.write(model_yaml)

# 保存模型的权重值
model.save_weights('model.yaml.h5')


# 从Json加载模型
with open('model.yaml', 'r') as file:
    model_json = file.read()

# 加载模型
new_model = model_from_yaml(model_json)
new_model.load_weights('model.yaml.h5')

# 编译模型
new_model.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy'])

# 评估从YAML加载的模型
scores = new_model.evaluate(x, Y_labels, verbose=0)
print('%s: %.2f%%' % (model.metrics_names[1], scores[1] * 100))

3、模型增强更新

在数据量非常大的时,若每次采用全部的数据去重新训练模型,则时间开销非常大,因此可以采用增量更新模型的方式对模型进行训练。对于时间序列的预测,增量更新相当于默认给最新的数据增加了权重,模型的准确度相对会比较好。在实际的应用中,如果采用增量更新模型,需要做与全量更新的对比实验,以确保增量更新的可行性。

在这里使用鸢尾花数据集,将数据集分为基本数据集和增量训练数据集。采用基本数据集训练完模型后,先序列化模型,然后重新导入模型并进行增量训练。完整代码如下:
from sklearn import datasets
import numpy as np
from keras.models import Sequential
from keras.layers import Dense
from keras.utils import to_categorical
from keras.models import model_from_json
from sklearn.model_selection import train_test_split

# 设定随机种子
seed = 7
np.random.seed(seed)

# 导入数据
dataset = datasets.load_iris()

x = dataset.data
Y = dataset.target

x_train, x_increment, Y_train, Y_increment = train_test_split(x, Y, test_size=0.2, random_state=seed)

# Convert labels to categorical one-hot encoding
Y_train_labels = to_categorical(Y_train, num_classes=3)


# 构建模型函数
def create_model(optimizer='rmsprop', init='glorot_uniform'):
    # 构建模型
    model = Sequential()
    model.add(Dense(units=4, activation='relu', input_dim=4, kernel_initializer=init))
    model.add(Dense(units=6, activation='relu', kernel_initializer=init))
    model.add(Dense(units=3, activation='softmax', kernel_initializer=init))

    # 编译模型
    model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=['accuracy'])

    return model

# 构建模型
model = create_model()
model.fit(x_train, Y_train_labels, epochs=10, batch_size=5, verbose=2)

scores = model.evaluate(x_train, Y_train_labels, verbose=0)
print('Base %s: %.2f%%' % (model.metrics_names[1], scores[1] * 100))

# 模型保存成Json文件
model_json = model.to_json()
with open('model.increment.json', 'w') as file:
    file.write(model_json)

# 保存模型的权重值
model.save_weights('model.increment.json.h5')


# 从Json加载模型
with open('model.increment.json', 'r') as file:
    model_json = file.read()

# 加载模型
new_model = model_from_json(model_json)
new_model.load_weights('model.increment.json.h5')

# 编译模型
new_model.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy'])

# 增量训练模型
# Convert labels to categorical one-hot encoding
Y_increment_labels = to_categorical(Y_increment, num_classes=3)
new_model.fit(x_increment, Y_increment_labels, epochs=10, batch_size=5, verbose=2)
scores = new_model.evaluate(x_increment, Y_increment_labels, verbose=0)
print('Increment %s: %.2f%%' % (model.metrics_names[1], scores[1] * 100))

4、神经网络的检查点

应用程序检查点(Checkpoint)是长时间运行进程的容错技术,是在系统故障的情况下,对系统状态快照保存的一种方法。如果产生问题,不是丢失全部数据,而是可以在检查点检查,或者从检查点开始新的运行。当训练深度学习模型时,可以利用检查点来捕获模型的权重,可以基于当前的权重进行预测,也可以用检测点保存的权重值来继续训练模型。

	回调函数 Callbacks 是一组在训练的特定阶段被调用的函数集,可以使用回调函数来观察训练过程中网络内部的状态和统计信息。然后,在模型上调用 fit() 函数时,可以将ModelCheckpoint传递给训练过程。训练深度学习模型时,Checkpoint是模型的权重。ModelCheckpoint回调类允许你定义检查模型权重的位置,文件应如何命名,以及在什么情况下创建模型的Checkpoint。函数如下:
checkpoint = ModelCheckpoint(filepath, monitor='val_acc', verbose=0, save_best_only=True, mode='max', period=1)

在这里插入图片描述

4.1 检查点跟踪神经网络模型

每当检测到模型性能提高时,使用检查点保存输出模型的权重值是一个很好的方法。
接下来将会通过一个简单的实例来演示在Keras中如何使用检查点。这个实例使用鸢尾花数据集,创建一个多分类的神经网络。该实例使用20%的数据自动评估模型的性能。只是在评估数据集(monitor = 'val acc’和mode = ‘max’)上的分类准确度有所提高时,才会设置检查点来保存网络权重。权重存储在文件weight-improvement-epoch-val_acc=.2f.h5中,代码如下:

from sklearn import datasets
import numpy as np
from keras.models import Sequential
from keras.layers import Dense
from keras.utils import to_categorical
from keras.callbacks import ModelCheckpoint

# 导入数据
dataset = datasets.load_iris()

x = dataset.data
Y = dataset.target

# Convert labels to categorical one-hot encoding
Y_labels = to_categorical(Y, num_classes=3)

# 设定随机种子
seed = 7
np.random.seed(seed)
# 构建模型函数
def create_model(optimizer='rmsprop', init='glorot_uniform'):
    # 构建模型
    model = Sequential()
    model.add(Dense(units=4, activation='relu', input_dim=4, kernel_initializer=init))
    model.add(Dense(units=6, activation='relu', kernel_initializer=init))
    model.add(Dense(units=3, activation='softmax', kernel_initializer=init))

    # 编译模型
    model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=['accuracy'])

    return model

# 构建模型
model = create_model()

# 设置检查点
filepath = 'weights-improvement-{epoch:02d}-{val_acc:.2f}.h5'
checkpoint = ModelCheckpoint(filepath=filepath, monitor='val_acc', verbose=1, save_best_only=True, mode='max')
callback_list = [checkpoint]
model.fit(x, Y_labels, validation_split=0.2, epochs=200, batch_size=5, verbose=0, callbacks=callback_list)



4.2 自动保存最优模型

更简单的检查点策略是将模型权重保存到同一个文件中,当且仅当模型的准确度提高时,才会将权重更新保存在文件中,只需要将文件名更改为固定文件名即可。
使用上述代码就可以完全。只需要将filepath = 'weights-improvement-{epoch:02d}-{val_acc:.2f}.h5’改成filepath = 'weights.best.h5’固定文件名(不包括分数或epoch信息)就行。

4.3 从检查点导入模型

使用ModelCheckpoint训练模型的过程中,通过检查点保存了模型的权重值。当训练模型意外终止,就可以从自动保存的检查点加载和使用检查点时保存的模型。使用检查点保存模型时,假定神经网络的拓扑结构是已知的,因此仅保存了模型的权重值。神经网络的拓扑结构可以在训练模型前,序列化JSON格式或YAML格式,以确保可以方便恢复网络的拓扑结构。
在下面的实例中,模型的拓扑结构是已知的,使用先前的实例生成的最佳权重(文件名为weight.best.h5),先从检查点恢复模型,然后使用该模型对整个数据集进行预测,代码如下:

from sklearn import datasets
import numpy as np
from keras.models import Sequential
from keras.layers import Dense
from keras.utils import to_categorical

# 导入数据
dataset = datasets.load_iris()

x = dataset.data
Y = dataset.target

# Convert labels to categorical one-hot encoding
Y_labels = to_categorical(Y, num_classes=3)

# 设定随机种子
seed = 7
np.random.seed(seed)
# 构建模型函数
def load_model(optimizer='rmsprop', init='glorot_uniform'):
    # 构建模型
    model = Sequential()
    model.add(Dense(units=4, activation='relu', input_dim=4, kernel_initializer=init))
    model.add(Dense(units=6, activation='relu', kernel_initializer=init))
    model.add(Dense(units=3, activation='softmax', kernel_initializer=init))

    # 加载权重
    filepath = 'weights.best.h5'
    model.load_weights(filepath=filepath)

    # 编译模型
    model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=['accuracy'])

    return model

# 构建模型
model = load_model()

# 评估模型
scores = model.evaluate(x, Y_labels, verbose=0)
print('%s: %.2f%%' % (model.metrics_names[1], scores[1] * 100))

5、模型训练过程可视化

在训练深度学习模型时,Keras提供了对训练历史的默认回调方法。在深度学习的模型的训练过程中,默认回调方法之一是History回调,它记录每个epoch的训练指标,包括损失和准确度(分类问题),以及评估数据集的损失和准确度(如果已设置)。
模型训练过程中的信息可以从训练模型的fit()函数的返回值获取。度量标准存储在返回对象的历史成员的字典里。可以使用历史对象中收集的数据来创建图表,可以很方便看出模型训练的情况,如:
(1)模型在epoch上的收敛速度(斜率);
(2)模型是否已经收敛(该线是否平滑收敛);
(3)模型是否过度学习训练数据(验证线的拐点)。
在下面的例子中,使用鸢尾花数据集构建神经网络,并使用对该神经网络训练时返回的历史信息,构建图表展示以下信息:
(1)训练数据集和评估数据集在各epoch的准确度;
(2)训练数据集和评估数据集在各epoch的损失情况。
代码如下:

from sklearn import datasets
import numpy as np
from keras.models import Sequential
from keras.layers import Dense
from keras.utils import to_categorical
from matplotlib import pyplot as plt


# 导入数据
dataset = datasets.load_iris()

x = dataset.data
Y = dataset.target

# Convert labels to categorical one-hot encoding
Y_labels = to_categorical(Y, num_classes=3)

# 设定随机种子
seed = 7
np.random.seed(seed)
# 构建模型函数
def create_model(optimizer='rmsprop', init='glorot_uniform'):
    # 构建模型
    model = Sequential()
    model.add(Dense(units=4, activation='relu', input_dim=4, kernel_initializer=init))
    model.add(Dense(units=6, activation='relu', kernel_initializer=init))
    model.add(Dense(units=3, activation='softmax', kernel_initializer=init))

    # 编译模型
    model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=['accuracy'])

    return model

# 构建模型
model = create_model()

history = model.fit(x, Y_labels, validation_split=0.2, epochs=200, batch_size=5, verbose=0)

# 评估模型
scores = model.evaluate(x, Y_labels, verbose=0)
print('%s: %.2f%%' % (model.metrics_names[1], scores[1] * 100))

# Hisotry列表
print(history.history.keys())

# accuracy的历史
plt.plot(history.history['acc'])
plt.plot(history.history['val_acc'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'validation'], loc='upper left')
plt.show()

# loss的历史
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'validation'], loc='upper left')
plt.show()

结果如下:
(1)训练数据集和评估数据集在各epoch的准确度。
在这里插入图片描述
(2)训练数据集和评估数据集在各epoch的损失情况。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zking~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值