在 Keras 损失函数中重塑 TensorFlow 张量?

2024-03-10

有没有办法在自定义 Keras 损失函数内重塑 TF 张量?我正在为卷积神经网络定义这个自定义损失函数?

def custom_loss(x, x_hat):
    """
    Custom loss function for training background extraction networks (autoencoders)
    """

    #flatten x, x_hat before computing mean, median
    shape = x_hat.get_shape().as_list()
    batch_size = shape[0]
    image_size = np.prod(shape[1:])

    x = tf.reshape(x, [batch_size, image_size])
    x_hat = tf.reshape(x_hat, [batch_size, image_size]) 

    B0 = reduce_median(tf.transpose(x_hat))
    # I divide by sigma in the next step. So I add a small float32 to F0
    # so as to prevent sigma from becoming 0 or Nan.

    F0 = tf.abs(x_hat - B0) + 1e-10

    sigma = tf.reduce_mean(tf.sqrt(F0 / 0.5), axis=0)

    background_term = tf.reduce_mean(F0 / sigma, axis=-1)

    bce = binary_crossentropy(x, x_hat)

    loss = bce + background_term 

    return loss

除了计算标准binary_crossentropy额外的background_term被添加到损失中。该术语激励网络预测接近批次中值的图像。由于 CNN 的输出是 2d 并且reduce_median对于一维数组效果更好我必须将图像重塑为一维数组。当我尝试训练该网络时出现错误

Traceback (most recent call last):
  File "stackoverflow.py", line 162, in <module>
    autoencoder = build_conv_autoencoder(lambda_W, input_shape, num_filters, optimizer, custom_loss)
  File "stackoverflow.py", line 136, in build_conv_autoencoder
    autoencoder.compile(optimizer, loss, metrics=[mean_squared_error])
  File "/usr/local/lib/python3.5/dist-packages/keras/models.py", line 594, in compile
    **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/keras/engine/training.py", line 667, in compile
    sample_weight, mask)
  File "/usr/local/lib/python3.5/dist-packages/keras/engine/training.py", line 318, in weighted
    score_array = fn(y_true, y_pred)
  File "stackoverflow.py", line 26, in custom_loss
    x = tf.reshape(x, [batch_size, image_size])
  File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/ops/gen_array_ops.py", line 2448, in reshape
    name=name)
  File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/framework/op_def_library.py", line 494, in apply_op
    raise err
  File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/framework/op_def_library.py", line 491, in apply_op
    preferred_dtype=default_dtype)
  File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/framework/ops.py", line 710, in internal_convert_to_tensor
    ret = conversion_func(value, dtype=dtype, name=name, as_ref=as_ref)
  File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/framework/constant_op.py", line 176, in _constant_tensor_conversion_function
    return constant(v, dtype=dtype, name=name)
  File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/framework/constant_op.py", line 165, in constant
    tensor_util.make_tensor_proto(value, dtype=dtype, shape=shape, verify_shape=verify_shape))
  File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/framework/tensor_util.py", line 441, in make_tensor_proto
    tensor_proto.string_val.extend([compat.as_bytes(x) for x in proto_values])
  File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/framework/tensor_util.py", line 441, in <listcomp>
    tensor_proto.string_val.extend([compat.as_bytes(x) for x in proto_values])
  File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/util/compat.py", line 65, in as_bytes
    (bytes_or_text,))
TypeError: Expected binary or unicode string, got None

好像 Keras 正在打电话custom_loss在实例化 TensorFlow 图之前。这使得batch_size无而不是实际值。是否有适当的方法来重塑损失函数内的张量以避免此错误?你可以看一下完整的代码here https://gitlab.com/mdornfe1/dolphin_tagger/blob/master/stackoverflow.py .


有没有正确的方法来重塑张量......

如果您使用 Keras,您应该使用K.reshape(x,shape)方法,它是一个包装器tf.reshape(x,shape)正如我们所看到的docs https://github.com/fchollet/keras/blob/master/keras/backend/tensorflow_backend.py#L1726-L1736.

我还注意到你正在使用get_shape()为了获得你的张量形状,在 Keras 上你可以这样做K.int_shape(x)正如在docs https://github.com/fchollet/keras/blob/master/keras/backend/tensorflow_backend.py#L469-L496, 像这样:

shape = K.int_shape(x_hat)

除此之外,还有其他几个操作可以直接调用 Tensorflow 导入,而不是 Keras 后端(例如tf.abs(), tf.reduce_mean(), tf.transpose(), ETC。)。您应该考虑在 keras 后端使用其相应的包装器,以具有统一的表示法并保证更规则的行为。此外,通过使用 Keras 后端,您的程序可以与 Theano 和 Tensorflow 兼容,因此这是您应该考虑的一大优势。

此外,一些TypeError当使用未定义维度的张量时可能会出现。请看一下这个问题 https://stackoverflow.com/questions/36668542/flatten-batch-in-tensorflow他们解释了如何重塑具有未定义维度的张量。另外,对于 Keras 中的等效项,请检查这个其他 https://stackoverflow.com/questions/45171247/reshape-tensor-in-custom-loss-function/45173396#45173396问题,在答案中我解释了如何使用 Keras 和 Tensorflow 作为后端来实现这一目标。

...现在关于您的代码。基本上,由于您有一些未定义的尺寸,您可以传递值 -1 来让它推断形状,无论它的大小是什么(在第一个链接的问题中对此进行了解释,但也可以在docs https://www.tensorflow.org/api_docs/python/tf/reshape)。就像是:

x = tf.reshape(x, [-1, image_size])

或者使用 Keras 后端:

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

在 Keras 损失函数中重塑 TensorFlow 张量? 的相关文章

随机推荐