训练与评估
使用内建的训练与评估
假定已经建立了如下模型:
from tensorflow import keras
from tensorflow.keras import layers
inputs = keras.Input(shape=(784,), name='digits')
x = layers.Dense(64, activation='relu', name='dense_1')(inputs)
x = layers.Dense(64, activation='relu', name='dense_2')(x)
outputs = layers.Dense(10, name='predictions')(x)
model = keras.Model(inputs=inputs, outputs=outputs)
训练
指定训练的参数
model.compile(optimizer=keras.optimizers.RMSprop(), # Optimizer
# Loss function to minimize
loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
# List of metrics to monitor
metrics=['sparse_categorical_accuracy'])
训练参数的配置
Optimizers:
SGD()
(with or without momentum)RMSprop()
Adam()
- etc.
Losses:
MeanSquaredError()
KLDivergence()
CosineSimilarity()
- etc.
Metrics:
AUC()
Precision()
Recall()
- etc.
自定义 loss函数(可以类继承)
def basic_loss_function(y_true, y_pred):
return tf.math.reduce_mean(tf.abs(y_true - y_pred))
model.compile(optimizer=keras.optimizers.Adam(),
loss=basic_loss_function)
model.fit(x_train, y_train, batch_size=64, epochs=3)
- 多输入多输出模型中:
比如我的模型有两个输出output1和output2,需要对这两个输出都计算一个MSE,并以平均值作为loss,那么model初始化和model.compile函数可以改为如下形式:
model = tf.keras.Model(inputs=x, outputs=[output1, output2])
model.compile(optimizer='adam', loss=['mean_squared_error', 'mean_squared_error'], loss_weights=[0.5, 0.5], metrics=[])
history = model.fit(x, [y1, y2], epochs=10, batch_size=32, verbose=1, validation_data=(vx, [vy1, vy2])
如果需要自定义loss函数:
def lossFunc(y_true, y_pred):
return tf.reduce_mean(tf.abs(y_true - y_pred))
model.compile(optimizer='adam', loss=[lossFunc, 'mean_squared_error'], loss_weights=[0.5, 0.5], metrics=[])
-
多输出,loss不独立
参考:https://mikito.mythsman.com/post/5da44e775ed28235d7573581/
自定义metrics(可以类继承)
class CategoricalTruePositives(keras.metrics.Metric):
def __init__(self, name='categorical_true_positives', **kwargs):
super(CategoricalTruePositives, self).__init__(name=name, **kwargs)
self.true_positives = self.add_weight(name='tp', initializer='zeros')
def update_state(self, y_true, y_pred, sample_weight=None):
y_pred = tf.reshape(tf.argmax(y_pred, axis=1), shape=(-1, 1))
values = tf.cast(y_true, 'int32') == tf.cast(y_pred, 'int32')
values = tf.cast(values, 'float32')
if sample_weight is not None:
sample_weight = tf.cast(sample_weight, 'float32')
values = tf.multiply(values, sample_weight)
self.true_positives.assign_add(tf.reduce_sum(values))
def result(self):
return self.true_positives
def reset_states(self):
# The state of the metric will be reset at the start of each epoch.
self.true_positives.assign(0.)
model.compile(optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=[CategoricalTruePositives()])
model.fit(x_train, y_train,
batch_size=64,
epochs=3)
把输入数据切成多个“batches”,每个大小为“batch_size”,以给定的“epochs“在整个数据集上重复迭代。
print('# Fit model on training data')
history = model.fit(x_train, y_train,
batch_size=64,
epochs=3,
# We pass some validation for
# monitoring validation loss and metrics
# at the end of each epoch
validation_data=(x_val, y_val))
print('\nhistory dict:', history.history)
”history“有训练过程中loss的记录和metric的值
参数的意义
1. epoch
训练过程中当一个完整的数据集通过了神经网络一次并且返回了一次,这个过程称为一个epoch,网络会在每个epoch结束时报告关于模型学习进度的调试信息。
在神经网络中传递完整的数据集一次是不够的,对于有限的数据集(是在批梯度下降情况下),使用一个迭代过程,更新权重一次或者说使用一个epoch是不够的,需要将完整的数据集在同样的神经网络中传递多次,随着epoch次数增加,神经网络中的权重的更新次数也增加,模型从欠拟合变得过拟合。
2. batch
batch_size: 一批数据中包含的样本数量称为batch_size;
3. iteration
将数据分为几个batch而不是一次性通过神经网络时,iteration是batch需要完成一个epoch的次数,也就是number of batches (区别于 batch size) , 在一次epoch中 number of batches = iteration = 训练样本总数 / batch size
比如,对于一个有2000个训练样本的数据集,将2000个样本分成大小为500的batch,那么完成一个epoch需要4个iteration
4. 如何选取这些参数
对于固定的epoch:
(a)在合理范围内,随着batch size增大,跑完一次epoch所需的迭代数减少,对于相同数据量的处理速度进一步加快,确定的下降方向越准,引起的训练震荡越小。
(b)batch size 过大时,跑完一次epoch所需的迭代数减少,想要达到相同的精度,所花费的时间大大增加了,从而对参数的修正也变得缓慢,batch size增大到一定程度,其确定的下降方向已经基本不再变化
对于固定的batch size:
(a)在合理范围内随着epoch的增加,训练集和测试集的误差呈下降趋势,模型的训练有了效果
(b)随着epoch的继续增加,训练集的误差呈下降而测试集的误差呈上升趋势,模型过拟合训练集对测试集性能不好
(2)实验实验,通过实验+经验选取合适的batch size 和 epoch
5. 其他
tf.keras中提供了fit()方法对模型进行训练,先来看看fit()方法的主要参数:
- x和y:训练数据和目标数据
- epochs:训练周期数,每一个周期都是对训练数据集的一次完整迭代
- batch_size:簇的大小,一般在数据集是numpy数组类型时使用
- validation_data:验证数据集,模型训练时,如果你想通过一个额外的验证数据集来监测模型的性能变换,就可以通过这个参数传入验证数据集
- verbose:日志显示方式,verbose=0为不在标准输出流输出日志信息,verbose=1为输出进度条记录,verbose=2为每个epoch输出一行记录
- callbacks:回调方法组成的列表,一般是定义在tf.keras.callbacks中的方法
- validation_split:从训练数据集抽取部分数据作为验证数据集的比例,是一个0到1之间的浮点数。这一参数在输入数据为dataset对象、生成器、keras.utils.Sequence对象是无效。
- shuffle:是否在每一个周期开始前打乱数据