【问题标题】:Reshape TensorFlow tensor inside Keras loss function?在 Keras 损失函数中重塑 TensorFlow 张量?
【发布时间】:2017-08-20 18:10:19
【问题描述】:

有没有办法在自定义 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 与 1d 数组一起工作得更好,我必须将图像重新整形为 1d 数组。当我尝试训练这个网络时,我得到了错误

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 在实例化 TensorFlow 图之前调用了custom_loss。这使得 batch_size None 代替了实际值。是否有适当的方法来重塑损失函数内部的张量以避免该错误?可以查看完整代码here

【问题讨论】:

  • 您是否尝试过在第一层或Input 层中定义batch_input_shape 而不是input_shape
  • 在使用get_shape().as_list()之后,你能检查shape的值吗?我想 xx_hat 是正确的张量,但如果你能检查它们是否正确,将极大地帮助解决问题

标签: python tensorflow keras


【解决方案1】:

有没有合适的方法来重塑张量...

如果您使用 Keras,您应该使用 K.reshape(x,shape) 方法,它是 tf.reshape(x,shape) 的包装器,正如我们在 docs 中看到的那样。

我还注意到您正在使用 get_shape() 来获取张量形状,在 Keras 上您可以使用 K.int_shape(x) 来执行此操作,正如 docs 中也提到的那样,如下所示:

shape = K.int_shape(x_hat)

除了您直接调用 Tensorflow 导入而不是 Keras 后端(如 tf.abs()tf.reduce_mean()tf.transpose() 等)之外,还有其他一些操作。您应该考虑在 keras 后端使用其相应的包装器以具有统一的符号并保证更常规的行为。此外,通过使用 Keras 后端,您的程序与 Theano 和 Tensorflow 兼容,因此您应该考虑这一点。

此外,当使用未定义维度的张量时,可能会出现一些 TypeError。请查看this question,他们在其中解释了如何重塑具有未定义维度的张量。此外,对于 Keras 中的等价物,请查看this other 问题,在答案中我解释了如何使用 Keras 和 Tensorflow 作为后端来实现这一目标。

...现在关于您的代码。基本上,由于您有一些未定义的尺寸,您可以传递值 -1 以使其推断形状,无论它可能是什么尺寸(在第一个链接问题中进行了解释,但也可以在 docs 中看到) .比如:

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

或者使用 Keras 后端:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-18
    • 2019-01-20
    • 2021-04-26
    • 2016-02-15
    • 2020-08-17
    • 2018-10-28
    • 2017-12-29
    相关资源
    最近更新 更多