如何访问 keras 中单个自定义损失函数的所有输出

2024-01-01

我正在尝试重现中提出的网络架构本出版物 https://www.sciencedirect.com/science/article/pii/S0031320319302031在张量流中。作为一个完全的初学者,我一直在使用本教程 https://www.tensorflow.org/tutorials/images/transfer_learning作为工作的基础,使用tensorflow==2.3.2。

为了训练这个网络,他们使用了一个损失,这意味着同时来自网络的两个分支的输出,这让我开始关注 keras 中的自定义损失函数。我知道您可以定义自己的函数,只要函数的定义如下所示:

def custom_loss(y_true, y_pred):

我还明白你可以给出其他论点,如下所示:

def loss_function(margin=0.3):
    def custom_loss(y_true, y_pred):
        # And now you can use margin

然后您只需在编译模型时调用它们即可。当谈到使用多个输出时,最常见的方法似乎是建议的方法here https://github.com/keras-team/keras/issues/12553#issuecomment-519124729,您将给出几个损失函数,每个输出都会调用一个损失函数。 但是,我找不到为损失函数提供多个输出的解决方案,而这正是我在这里需要的。

为了进一步解释它,这里是一个最小的工作示例,展示了我所尝试的内容,您可以自己尝试这次合作 https://colab.research.google.com/drive/1e_P7gbJGULbfKRjfhYJc3qb7KUbk9goA?usp=sharing.

import os
import tensorflow as tf
import keras.backend as K
from tensorflow.keras import datasets, layers, models, applications, losses
from tensorflow.keras.preprocessing import image_dataset_from_directory

_URL = 'https://storage.googleapis.com/mledu-datasets/cats_and_dogs_filtered.zip'
path_to_zip = tf.keras.utils.get_file('cats_and_dogs.zip', origin=_URL, extract=True)
PATH = os.path.join(os.path.dirname(path_to_zip), 'cats_and_dogs_filtered')

train_dir = os.path.join(PATH, 'train')
validation_dir = os.path.join(PATH, 'validation')

BATCH_SIZE = 32
IMG_SIZE = (160, 160)
IMG_SHAPE = IMG_SIZE + (3,)

train_dataset = image_dataset_from_directory(train_dir,
                                             shuffle=True,
                                             batch_size=BATCH_SIZE,
                                             image_size=IMG_SIZE)

validation_dataset = image_dataset_from_directory(validation_dir,
                                                  shuffle=True,
                                                  batch_size=BATCH_SIZE,
                                                  image_size=IMG_SIZE)

data_augmentation = tf.keras.Sequential([
  layers.experimental.preprocessing.RandomFlip('horizontal'),
  layers.experimental.preprocessing.RandomRotation(0.2),
])
preprocess_input = applications.resnet50.preprocess_input
base_model = applications.ResNet50(input_shape=IMG_SHAPE,
                                               include_top=False,
                                               weights='imagenet')
base_model.trainable = True
conv = layers.Conv2D(filters=128, kernel_size=(1,1))
global_pooling = layers.GlobalAveragePooling2D()
horizontal_pooling = layers.AveragePooling2D(pool_size=(1, 5))
reshape = layers.Reshape((-1, 128))

def custom_loss(y_true, y_pred):
    print(y_pred.shape)
    # Do some stuffs involving both outputs
    # Returning something trivial here for correct behavior
    return K.mean(y_pred)

inputs = tf.keras.Input(shape=IMG_SHAPE)
x = data_augmentation(inputs)
x = preprocess_input(x)
x = base_model(x, training=True)

first_branch = global_pooling(x)

second_branch = conv(x)
second_branch = horizontal_pooling(second_branch)
second_branch = reshape(second_branch)

model = tf.keras.Model(inputs, [first_branch, second_branch])
base_learning_rate = 0.0001
model.compile(optimizer=tf.keras.optimizers.Adam(lr=base_learning_rate),
              loss=custom_loss,
              metrics=['accuracy'])
model.summary()

initial_epochs = 10
history = model.fit(train_dataset,
                    epochs=initial_epochs,
                    validation_data=validation_dataset)

这样做时,我认为赋予损失函数的 y_pred 将是一个列表,包含两个输出。但是,在运行它时,我在标准输出中得到的是:

Epoch 1/10
(None, 2048)
(None, 5, 128)

我从中了解到的是,损失函数是对每个输出一个接一个地调用的,而不是对所有输出调用一次,这意味着我无法定义同时使用两个输出的损失。有什么办法可以实现这一点吗?

如果我不清楚,或者您需要更多详细信息,请告诉我。


我在尝试实施时遇到了同样的问题Triplet_Loss功能。

我参考了 Keras 的实现具有三重态损失函数的连体网络 https://keras.io/examples/vision/siamese_network/但有些事情没有成功,我不得不自己实现网络。

def get_siamese_model(input_shape, conv2d_filters):
    # Define the tensors for the input images
    anchor_input = Input(input_shape, name="Anchor_Input")
    positive_input = Input(input_shape, name="Positive_Input")
    negative_input = Input(input_shape, name="Negative_Input")

    body = build_body(input_shape, conv2d_filters)
    # Generate the feature vectors for the images
    encoded_a = body(anchor_input)
    encoded_p = body(positive_input)
    encoded_n = body(negative_input)

    distance = DistanceLayer()(encoded_a, encoded_p, encoded_n)
    # Connect the inputs with the outputs
    siamese_net = Model(inputs=[anchor_input, positive_input, negative_input],
                        outputs=distance)
    return siamese_net

而“错误”是在DistanceLayerKeras 发布的实现(也在上面的同一链接中)。

class DistanceLayer(tf.keras.layers.Layer):
    """
    This layer is responsible for computing the distance between the anchor
    embedding and the positive embedding, and the anchor embedding and the
    negative embedding.
    """

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    def call(self, anchor, positive, negative):
        ap_distance = tf.math.reduce_sum(tf.math.square(anchor - positive), axis=1, keepdims=True, name='ap_distance')
        an_distance = tf.math.reduce_sum(tf.math.square(anchor - negative), axis=1, keepdims=True, name='an_distance')
        return (ap_distance, an_distance)

当我训练模型时,损失函数只取其中一个向量ap_distance or an_distance.

最后,修复是将向量连接在一起(沿着axis=1在这种情况下),在损失函数上,将它们分开:

    def call(self, anchor, positive, negative):
        ap_distance = tf.math.reduce_sum(tf.math.square(anchor - positive), axis=1, keepdims=True, name='ap_distance')
        an_distance = tf.math.reduce_sum(tf.math.square(anchor - negative), axis=1, keepdims=True, name='an_distance')
        return tf.concat([ap_distance, an_distance], axis=1)

关于我的自定义损失:

def get_loss(margin=1.0):
    def triplet_loss(y_true, y_pred):
        # The output of the network is NOT A tuple, but a matrix shape (batch_size, 2),
        # containing the distances between the anchor and the positive example,
        # and the anchor and the negative example.
        ap_distance = y_pred[:, 0]
        an_distance = y_pred[:, 1]

        # Computing the Triplet Loss by subtracting both distances and
        # making sure we don't get a negative value.
        loss = tf.math.maximum(ap_distance - an_distance + margin, 0.0)
        # tf.print("\n", ap_distance, an_distance)
        # tf.print(f"\n{loss}\n")
        return loss

    return triplet_loss
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何访问 keras 中单个自定义损失函数的所有输出 的相关文章

随机推荐

  • 将对象数组转换为对象值数组

    我正在尝试转换这个数组 let orders amount 100 user admin date March 6 2019 amount 120 user admin date March 6 2019 amount 80 user ad
  • 我可以通过编程方式控制 .NET Core 程序集重定向吗?

    问题 NET Core 2 0 netstandard 2 0 中是否有任何方法可以应用给定中未定义的程序集重定向application exe config运行可执行文件时的文件 也许某种编程方式 或者甚至通过使用一些特殊设置 标志运行可
  • 你可以同时运行 Coldfusion 和 PHP [重复]

    这个问题在这里已经有答案了 可能的重复 是否可以在同一服务器和网站上运行 Coldfusion 和 PHP https stackoverflow com questions 2444598 is is possible to run co
  • iOS 上的 Firebase Crashlytics 设置?

    我正在尝试集成 Firebase崩溃解决方案进入 iOS 我的应用程序 该应用程序启用了 Firebase 崩溃报告 我已按照文档进行操作here https firebase google com docs crashlytics upg
  • 老问题,如何确定不规则形状中的点?

    我学习 Html5 Canvas 有几个星期了 但是上面的问题困扰了我很长时间 不规则的形状 可能是圆形 矩形 椭圆形 多边形 或者由一些直线和贝塞尔曲线构造的路径 我找到了一些针对某些形状的算法 例如圆形 矩形和多边形 但是 如果我在画布
  • 带有打字稿的 nextjs API,将 NextApiRequest 查询参数限制为字符串类型[重复]

    这个问题在这里已经有答案了 在这个端点处理程序中 有没有办法限制req query在 NextJS 中NextApiRequest只是string类型而不是string string 例如 someQueryParam这里是string s
  • 内核模块如何卸载自身而不在内核日志中生成错误?

    我制作了一个简单的模块 可以在加载时打印 GDT 和 IDT 当它完成工作后 就不再需要它并且可以卸载 但如果它返回负数以停止加载 insmod会抱怨 并且错误消息将记录在内核日志中 内核模块如何优雅地卸载自身 据我所知 使用库存内核是不可
  • 如何设计系统以允许加密迁移?

    我想建立一个系统 允许我将加密密码 哈希密码 从一个系统迁移到另一个系统 我该怎么做 比如说 2 个月后 我发现了一种加密方法 其性能提高了 10 倍 并且当前的哈希函数已被毫无疑问地证明是完全脆弱的 我将如何将用户密码从一种哈希类型迁移到
  • 如何注释 EJS 代码(JS 节点)而不出现错误

    我在 EJS 文件中有以下代码 table tr td td td td tr table 当我这样评论的时候
  • 获取数字的 CastError NaN

    我收到这个错误 CastError Cast to Number failed for value NaN at path area message Cast to Number failed for value NaN at path a
  • 带有 CSS 的纹理文本?

    我目前正在开发一个简单的页面 有谁知道有什么方法可以将纹理图像覆盖在文本上吗 目前的规格似乎不可能 但请告诉我这是否可能 谢谢并保重 不知道为什么没有人回答这个问题 这可以使用background clip https codepen io
  • 指定 Tkinter 文本框的尺寸(以像素为单位)

    如何使用像素指定 Tkinter 文本框的尺寸 我不想改变字体大小 我用它来帮助我将其缩放到窗口的大小 您可以通过将其放入框架内 通过停用尺寸传播并配置条目以粘贴到框架边框来强制框架为固定尺寸来实现此目的 pack 也应该以类似的方式工作
  • 屏幕上和变量中的调用表达式输出

    我正在尝试存储来自的输出Invoke expression到变量以及屏幕上 我有 PS 日志记录 它会自动将所有内容记录为Write Host在一个文件中 现在我正在使用Invoke Expression这似乎要么在屏幕上打印输出 要么打印
  • 对 pandas MultiIndex 数据帧进行重新采样

    我有一个类似于以下内容的 pandas MultiIndex 数据框 import pandas as pd rows One One One 20120105 1 Text1 One One One 20120107 2 Text2 On
  • swift ios 键盘扩展 - 长按/按住

    我需要知道如何向 ios 自定义键盘扩展添加长按 按住 功能 以便我可以显示多个键以从中选择一个 expected design 我的项目结构 按键操作的当前代码 代码可以将按下的按钮的标题作为新文本添加到任何代理文本字段中 IBActio
  • Xcode PhoneGap 本地化

    这两天我一直在努力尝试向我的应用程序添加特定于语言的本地化 该应用程序正在使用 PhoneGap 1 1 我正在尝试使用 XCode 4 1 构建它 两天以来我一直在寻找信息 教程 其他内容 但找不到任何详细信息 所以 要么这是一个微不足道
  • XStream解析没有根节点的JSON

    我目前正在使用 XStream 反序列化 JSON 并且效果很好 但是 当我有如下所示的 JSON 字符串时 key1 an object something foobar key2 another object data hi 最值得注意
  • 在哪里放置模型数据和行为? [tl;博士;使用服务]

    我正在使用 AngularJS 来完成我的最新项目 在文档和教程中 所有模型数据都放入控制器范围内 我知道它必须可供控制器使用 因此必须在相应的视图中 但我认为该模型实际上不应该在那里实施 例如 它可能很复杂并且具有私有属性 此外 人们可能
  • 将文本框绑定到comboBox.SelectedItem 的属性

    我正在使用 winforms 并且有一个代表 IQueryable 的组合框 组合框下方是一系列文本框 我希望将它们绑定到组合框中当前选择的文本框 这是我的代码 public partial class TestForm Form publ
  • 如何访问 keras 中单个自定义损失函数的所有输出

    我正在尝试重现中提出的网络架构本出版物 https www sciencedirect com science article pii S0031320319302031在张量流中 作为一个完全的初学者 我一直在使用本教程 https ww