训练与评估

08 Jun 2020

使用内建的训练与评估

假定已经建立了如下模型:

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:

Losses:

Metrics:

自定义 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)
  1. 多输入多输出模型中:

比如我的模型有两个输出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=[])
  1. 多输出,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()方法的主要参数:

自定义训练