Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Keras多输出模型中每个输出的自定义精度/损失_Python_Tensorflow_Keras - Fatal编程技术网

Python Keras多输出模型中每个输出的自定义精度/损失

Python Keras多输出模型中每个输出的自定义精度/损失,python,tensorflow,keras,Python,Tensorflow,Keras,我试图使用Keras为双输出神经网络模型中的每个输出定义自定义损失和精度函数。让我们调用两个输出:A和B 我的目标是: 给出其中一个输出名称的精度/损失函数,以便可以在tensorboard中的相同图表上报告它们,与我提供的旧/现有模型的相同对应输出。例如,两个输出网络中输出A的精度和损耗应该可以在tensorboard中的同一个图形中看到,就像我所拥有的一些旧模型的输出A一样。更具体地说,这些旧型号的所有输出都是A_输出acc,val_输出acc,A_输出损耗和val_输出损耗。因此,我希望在

我试图使用Keras为双输出神经网络模型中的每个输出定义自定义损失和精度函数。让我们调用两个输出:A和B

我的目标是:

  • 给出其中一个输出名称的精度/损失函数,以便可以在tensorboard中的相同图表上报告它们,与我提供的旧/现有模型的相同对应输出。例如,两个输出网络中输出A的精度和损耗应该可以在tensorboard中的同一个图形中看到,就像我所拥有的一些旧模型的输出A一样。更具体地说,这些旧型号的所有输出都是
    A_输出acc
    val_输出acc
    A_输出损耗
    val_输出损耗
    。因此,我希望在这个新模型中,
    A
    输出的相应度量读数也具有这些名称,以便它们在tensorboard中的同一图形上可以查看/比较
  • 允许轻松配置精度/损失函数,以便我可以随心所欲地交换每个输出的不同损失/精度,而无需硬编码 我有一个构建和编译网络的
    Modeler
    类。有关守则如下

    class Modeler(BaseModeler):
      def __init__(self, loss=None,accuracy=None, ...):
        """
        Returns compiled keras model.  
    
        """
        self.loss = loss
        self.accuracy = accuracy
        model = self.build()
    
        ...
    
        model.compile(
            loss={ # we are explicit here and name the outputs even though in this case it's not necessary
                "A_output": self.A_output_loss(),#loss,
                "B_output": self.B_output_loss()#loss
            },
            optimizer=optimus,
            metrics= { # we need to tie each output to a specific list of metrics
                "A_output": [self.A_output_acc()],
                                # self.A_output_loss()], # redundant since it's already reported via `loss` param,
                                                            # ends up showing up as `A_output_loss_1` since keras
                                                            # already reports `A_output_loss` via loss param
                "B_output": [self.B_output_acc()]
                                # self.B_output_loss()]  # redundant since it's already reported via `loss` param
                                                            # ends up showing up as `B_output_loss_1` since keras
                                                            # already reports `B_output_loss` via loss param
            })
    
        self._model = model
    
    
      def A_output_acc(self):
        """
        Allows us to output custom train/test accuracy/loss metrics to desired names e.g. 'A_output_acc' and
        'val_A_output_acc' respectively so that they may be plotted on same tensorboard graph as the accuracies from
        other models that same outputs.
    
        :return:    accuracy metric
        """
    
        acc = None
        if self.accuracy == TypedAccuracies.BINARY:
            def acc(y_true, y_pred):
                return self.binary_accuracy(y_true, y_pred)
        elif self.accuracy == TypedAccuracies.DICE:
            def acc(y_true, y_pred):
                return self.dice_coef(y_true, y_pred)
        elif self.accuracy == TypedAccuracies.JACARD:
            def acc(y_true, y_pred):
                return self.jacard_coef(y_true, y_pred)
        else:
            logger.debug('ERROR: undefined accuracy specified: {}'.format(self.accuracy))
    
        return acc
    
    
      def A_output_loss(self):
        """
        Allows us to output custom train/test accuracy/loss metrics to desired names e.g. 'A_output_acc' and
        'val_A_output_acc' respectively so that they may be plotted on same tensorboard graph as the accuracies from
        other models that same outputs.
    
        :return:    loss metric
        """
    
        loss = None
        if self.loss == TypedLosses.BINARY_CROSSENTROPY:
            def loss(y_true, y_pred):
                return self.binary_crossentropy(y_true, y_pred)
        elif self.loss == TypedLosses.DICE:
            def loss(y_true, y_pred):
                return self.dice_coef_loss(y_true, y_pred)
        elif self.loss == TypedLosses.JACARD:
            def loss(y_true, y_pred):
                return self.jacard_coef_loss(y_true, y_pred)
        else:
            logger.debug('ERROR: undefined loss specified: {}'.format(self.accuracy))
    
        return loss
    
    
      def B_output_acc(self):
        """
        Allows us to output custom train/test accuracy/loss metrics to desired names e.g. 'A_output_acc' and
        'val_A_output_acc' respectively so that they may be plotted on same tensorboard graph as the accuracies from
        other models that same outputs.
    
        :return:    accuracy metric
        """
    
        acc = None
        if self.accuracy == TypedAccuracies.BINARY:
            def acc(y_true, y_pred):
                return self.binary_accuracy(y_true, y_pred)
        elif self.accuracy == TypedAccuracies.DICE:
            def acc(y_true, y_pred):
                return self.dice_coef(y_true, y_pred)
        elif self.accuracy == TypedAccuracies.JACARD:
            def acc(y_true, y_pred):
                return self.jacard_coef(y_true, y_pred)
        else:
            logger.debug('ERROR: undefined accuracy specified: {}'.format(self.accuracy))
    
        return acc
    
    
      def B_output_loss(self):
        """
        Allows us to output custom train/test accuracy/loss metrics to desired names e.g. 'A_output_acc' and
        'val_A_output_acc' respectively so that they may be plotted on same tensorboard graph as the accuracies from
        other models that same outputs.
    
        :return:    loss metric
        """
    
        loss = None
        if self.loss == TypedLosses.BINARY_CROSSENTROPY:
            def loss(y_true, y_pred):
                return self.binary_crossentropy(y_true, y_pred)
        elif self.loss == TypedLosses.DICE:
            def loss(y_true, y_pred):
                return self.dice_coef_loss(y_true, y_pred)
        elif self.loss == TypedLosses.JACARD:
            def loss(y_true, y_pred):
                return self.jacard_coef_loss(y_true, y_pred)
        else:
            logger.debug('ERROR: undefined loss specified: {}'.format(self.accuracy))
    
        return loss
    
    
      def load_model(self, model_path=None):
        """
        Returns built model from model_path assuming using the default architecture.
    
        :param model_path:   str, path to model file
        :return:             defined model with weights loaded
        """
    
        custom_objects = {'A_output_acc': self.A_output_acc(),
                          'A_output_loss': self.A_output_loss(),
                          'B_output_acc': self.B_output_acc(),
                          'B_output_loss': self.B_output_loss()}
        self.model = load_model(filepath=model_path, custom_objects=custom_objects)
        return self
    
    
      def build(self, stuff...):
        """
        Returns model architecture.  Instead of just one task, it performs two: A and B.
    
        :return:            model
        """
    
        ...
    
        A_conv_final = Conv2D(1, (1, 1), activation="sigmoid", name="A_output")(up_conv_224)
    
        B_conv_final = Conv2D(1, (1, 1), activation="sigmoid", name="B_output")(up_conv_224)
    
        model = Model(inputs=[input], outputs=[A_conv_final, B_conv_final], name="my_model")
        return model
    
    培训效果很好。但是,当我稍后使用上面的
    load\u model()
    函数加载模型进行推断时,Keras抱怨它不知道我给它的自定义度量:

    ValueError: Unknown loss function:loss
    
    似乎正在发生的是,Keras将在上述每个自定义度量函数(
    def loss(…)
    def acc(…)
    )中创建的返回函数附加到
    model.compile()调用的
    metrics
    参数中给定的字典键。 例如,键是
    A\u output
    ,我们为它调用自定义精度函数,
    A\u output\u acc()
    ,它返回一个名为
    acc
    的函数。因此,结果是
    A_输出
    +
    acc
    =
    A_输出\u acc
    。这意味着我无法命名那些返回的函数:
    acc
    /
    loss
    其他一些函数,因为这将打乱报告/图表。 这一切都很好,但我不知道如何使用正确定义的
    custom_objects
    参数编写我的
    load
    函数(或者定义/命名我的自定义度量函数),以便Keras知道每个输出头将加载哪些自定义精度/损失函数

    更重要的是,在
    load\u model()
    中,它似乎需要一个如下形式的
    自定义\u对象
    字典(由于明显的原因,它不起作用):

    而不是:

    custom_objects = {'A_output_acc': self.A_output_acc(),
                      'A_output_loss': self.A_output_loss(),
                      'B_output_acc': self.B_output_acc(),
                      'B_output_loss': self.B_output_loss()}
    
    有什么见解或解决办法吗

    谢谢

    编辑:

    我已经确认上面关于键/函数名连接的推理对于Keras的
    model.compile()
    调用的
    metrics
    参数是正确的。但是,对于
    model.compile()
    中的
    loss
    参数,Keras只是将键与单词
    loss
    连接起来,但在
    model.load\u model()
    custom\u objects
    参数中需要自定义loss函数的名称。请参见图。

    删除()在你的损失和指标结束时,应该是这样。它将看起来像这样

    loss={ 
           "A_output": self.A_output_loss,
           "B_output": self.B_output_loss
          }
    

    你也可以看看这个问题吗?
    loss={ 
           "A_output": self.A_output_loss,
           "B_output": self.B_output_loss
          }