如何防止 Keras 在训练期间计算指标

Loa*_*Gio 8 python machine-learning deep-learning keras tensorflow

我正在使用 Tensorflow/Keras 2.4.1,并且有一个(无监督的)自定义指标,它将我的几个模型输入作为参数,例如:

model = build_model() # returns a tf.keras.Model object
my_metric = custom_metric(model.output, model.input[0], model.input[1])
model.add_metric(my_metric)
[...]
model.fit([...]) # training with fit
Run Code Online (Sandbox Code Playgroud)

然而,它恰好custom_metric非常昂贵,所以我希望仅在验证期间计算它。我找到了这个答案,但我几乎不明白如何使解决方案适应我的指标,该指标使用多个模型输入作为参数,因为该update_state方法似乎并不灵活。

在我的上下文中,除了编写我自己的训练循环之外,是否有办法避免在训练期间计算我的指标?另外,我很惊讶我们无法本机指定 Tensorflow 某些指标只能在验证时计算,这有什么原因吗?

此外,由于模型经过训练来优化损失,并且训练数据集不应用于评估模型,我什至不明白为什么默认情况下 Tensorflow 在训练期间计算指标。

Mar*_*ani 3

我认为仅在验证时计算指标的最简单解决方案是使用自定义回调。

在这里我们定义我们的虚拟回调:

class MyCustomMetricCallback(tf.keras.callbacks.Callback):

    def __init__(self, train=None, validation=None):
        super(MyCustomMetricCallback, self).__init__()
        self.train = train
        self.validation = validation

    def on_epoch_end(self, epoch, logs={}):

        mse = tf.keras.losses.mean_squared_error

        if self.train:
            logs['my_metric_train'] = float('inf')
            X_train, y_train = self.train[0], self.train[1]
            y_pred = self.model.predict(X_train)
            score = mse(y_train, y_pred)
            logs['my_metric_train'] = np.round(score, 5)

        if self.validation:
            logs['my_metric_val'] = float('inf')
            X_valid, y_valid = self.validation[0], self.validation[1]
            y_pred = self.model.predict(X_valid)
            val_score = mse(y_pred, y_valid)
            logs['my_metric_val'] = np.round(val_score, 5)
Run Code Online (Sandbox Code Playgroud)

给定这个虚拟模型:

def build_model():

  inp1 = Input((5,))
  inp2 = Input((5,))
  out = Concatenate()([inp1, inp2])
  out = Dense(1)(out)

  model = Model([inp1, inp2], out)
  model.compile(loss='mse', optimizer='adam')

  return model
Run Code Online (Sandbox Code Playgroud)

和这个数据:

X_train1 = np.random.uniform(0,1, (100,5))
X_train2 = np.random.uniform(0,1, (100,5))
y_train = np.random.uniform(0,1, (100,1))

X_val1 = np.random.uniform(0,1, (100,5))
X_val2 = np.random.uniform(0,1, (100,5))
y_val = np.random.uniform(0,1, (100,1))
Run Code Online (Sandbox Code Playgroud)

您可以使用自定义回调来计算训练和验证上的指标:

model = build_model()

model.fit([X_train1, X_train2], y_train, epochs=10, 
          callbacks=[MyCustomMetricCallback(train=([X_train1, X_train2],y_train), validation=([X_val1, X_val2],y_val))])
Run Code Online (Sandbox Code Playgroud)

仅在验证时:

model = build_model()

model.fit([X_train1, X_train2], y_train, epochs=10, 
          callbacks=[MyCustomMetricCallback(validation=([X_val1, X_val2],y_val))])
Run Code Online (Sandbox Code Playgroud)

仅限火车上:

model = build_model()

model.fit([X_train1, X_train2], y_train, epochs=10, 
          callbacks=[MyCustomMetricCallback(train=([X_train1, X_train2],y_train))])
Run Code Online (Sandbox Code Playgroud)

请记住,回调会一次性评估数据上的指标,就像 keras 在validation_data.

是运行代码。