KERAS自定义度量函数如何将2个模型输出馈送到单个度量评估功能



i具有一个CNN对象检测模型,该模型具有两个带有张量名的头(输出('classification''regression'

我想定义同时接受两个输出的度量函数,以便它查看回归预测来决定要保留哪些索引并使用的索引这些索引从分类预测中选择张量并计算一些度量。

我当前在此链接的帮助下定义的指标函数:

from tensorflow.python.keras.metrics import MeanMetricWrapper
class Accuracy2(MeanMetricWrapper):
    def __init__(self, name='dummyAccuracy', dtype=None):
        super(Accuracy2, self).__init__(metric_calculator_func, name, dtype=dtype)
        self.true_positives = self.add_weight(name='lol', initializer='zeros')
    @classmethod
    def from_config(cls, config):
        if 'fn' in config:
          config.pop('fn')
        return super(Accuracy2, cls).from_config(config)

    def update_state(self, y_true, y_pred, sample_weight=None):
      print("==@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@===")
      print("Y-True {}".format(y_true))
      print("Y-Pred {}".format(y_pred))
      print("==@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@===")
      update_ops = [self.true_positives.assign_add(1.0)]
      return tf.group(update_ops)
    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.)

我在模型汇编期间称为:

training_model.compile(
    loss={
        'regression'    : regression_loss(),
        'classification': classification_loss()
    },
    optimizer=keras.optimizers.Adam(lr=lr, clipnorm=0.001),
    metrics=[Accuracy2()]
)

tf.estimator.train_and_evaluate is

屏幕日志>:

信息:TensorFlow:损失= 0.0075738616,步骤= 31(11.941 sec(

信息:TensorFlow:global_step/sec:4.51218

信息:TensorFlow:损失= 0.01015341,步骤= 36(1.108 sec(

信息:TensorFlow:将40的检查点保存到/tmp/tmpcla2n3gy/model.ckpt。

信息:TensorFlow:调用model_fn。 == @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ============================================================= 张量(" iteratorGetNext:1",shape =(?,120087,5(,dtype = float32,设备=/设备:cpu:0( 张量("回归/concat:0",shape =(?,??,4(,dtype = float32( == @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ============================================================= == @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ============================================================= 张量(" iteratorGetNext:2",shape =(?,120087,2(,dtype = float32,设备=/设备:cpu:0( 张量("分类/concat:0",shape =(?,??,1(,dtype = float32( == @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ======================================================

信息:TensorFlow:完成拨打Model_fn。

信息:TensorFlow:开始评估2019-06-24T08:20:35Z 信息:TensorFlow:图形已完成。 2019-06-24 13:50:36.457345:i TensorFlow/core/councom_runtime/gpu/gpu_device.cc:1512]添加可见的GPU设备:0 2019-06-24 13:50:36.457398:i TensorFlow/core/councom_runtime/gpu/gpu_device.cc:984]设备互连streamExecutor与强度1 edge矩阵: 2019-06-24 13:50:36.457419:i Tensorflow/core/common_runtime/gpu/gpu_device.cc:990] 0 2019-06-24 13:50:36.457425:i tensorflow/core/common_runtime/gpu/gpu_device.cc:1003] 0:n 2019-06-24 13:50:36.457539:i Tensorflow/core/councom_runtime/gpu/gpu_device.cc:1115]创建了TensorFlow设备(/local-Host/poplica:0/task:0/taskMB内存( ->物理GPU(设备:0,名称:GeForce RTX 2080 TI,PCI总线ID:0000:01:00.0,计算能力:7.5(

信息:TensorFlow:从/TMP/tmpcla2n3gy/model.ckpt-40

还原参数

信息:tensorflow:运行local_init_op。

信息:TensorFlow:运行local_init_op。

信息:TensorFlow:评估[10/100]

信息:TensorFlow:评估[20/100]

信息:TensorFlow:评估[30/100]

信息:TensorFlow:评估[40/100]

信息:TensorFlow:评估[50/100]

信息:TensorFlow:评估[60/100]

信息:TensorFlow:评估[70/100]

信息:TensorFlow:评估[80/100]

信息:TensorFlow:评估[90/100]

信息:TensorFlow:评估[100/100]

信息:TensorFlow:完成的评估2019-06-24-08:20:44

信息:tensorflow:保存全局步骤40:_ focal = 0.0016880237,_smooth_l1 = 0.0,dummyAccuracy = 100.0,global_step = 40,损失= 0.0016880237

这一行:

==@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@===
Tensor("IteratorGetNext:1", shape=(?, 120087, 5), dtype=float32, device=/device:CPU:0)
Tensor("regression/concat:0", shape=(?, ?, 4), dtype=float32)
==@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@===
==@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@===
Tensor("IteratorGetNext:2", shape=(?, 120087, 2), dtype=float32, device=/device:CPU:0)
Tensor("classification/concat:0", shape=(?, ?, 1), dtype=float32)
==@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@===

表明,首先调用Accuracy2()回归,然后分类。但是我希望它通过回归分类一起被调用一次您需要两个 y_true值的度量。

在这种情况下,我们需要将数据弄平,以便我们可以将其限制为单个数组。这将需要固定的尺寸输出。

假设您将regOutclassOut作为张量。如果它们是2D,则只是将它们加入,否则:

regOut = Flatten()(regOut) #only if regOut is 3D or more
classOut = Flatten()(classOut) #only if classOut is 3D or more
out = Concatenate()([regOut,classOut])

将模型带有此单个输出:

model = Model(inputs, out)

对您的数据集进行相同的操作:

y_reg_train = y_reg_train.reshape((y_reg_train.shape[0], -1))
y_class_train = y_clas_trains.reshape((y_class_train.shape[0], -1))
y_train = np.concatenate([y_reg_train, y_class_train], axis=-1)
#same for y_val

然后创建一个分开两者的度量:

def metric(y_true, y_pred):
    reg_true = y_true[:,:flattened_size_of_reg]
    class_true = y_true[:, flattened_size_of_reg:]
    
    reg_pred = y_pred[:,:flattened_size_of_reg]
    class_pred = y_pred[:, flattened_size_of_reg:]
    #calculate the metric
    return value

与组合输出的训练:

model.fit(x_train, y_train, ...)

如果您不需要y_true

这是一个丑陋的答案,但是....

您必须制作一层才能为您计算指标。使用Lambda

鉴于regOutclassOut是您的输出张量,在模型创建中,而不是创建像Model(inputs, [regOut,classOut])这样的模型,您将:

def metricFunc(modelOutputs):
    regressionOutput = modelOutputs[0]
    classOutput = modelOuptuts[1]
    #calculate metric
    return calculatedMetric

metricTensor = Lambda(metricFunc, name='metric_layer')([regOut,classOut])

使公制是模型的输出:

model = Model(inputs, [regOut, classOut, metricTensor])

创建一个虚拟损失和编译的虚拟指标:

def dummyLoss(true,pred):
    return K.zeros(K.shape(true)[:1])
def dummyMetric(true,pred):
    return pred

编译:

model.compile(loss = [regLoss, classLoss, dummyLoss], 
              metrics={'metric_layer':dummyMetric}, 
              optimizer=...)

这也要求您也用 metricTensor的虚拟张量训练:

model.fit(x_train, [y_reg,y_class,np.zeros(y_reg.shape[:1])], ...)

让我向您展示一种实现这一目标的优雅方法。

  • 首先,定义包装您的度量的外部函数,以便您可以通过回归张量reg_out

    def metric_func(reg_out):
        def metric(y_true, class_out):
            return your_metric(reg_out, class_out, y_true)
        return metric
    
  • 接下来,通过设置产生它的图层的参数name来命名分类张量class_out。例如:

    class_out = Dense(1, name='class_out')(something)
    
  • 最后,设置Model.com的参数metrics如下:

    model.compile(...,
                  metrics={'class_out': metric_func(reg_out)})
    

最新更新