首页 文章

重塑Keras损失函数内的TensorFlow张量?

提问于
浏览
1

有没有办法在自定义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

在实例化TensorFlow图之前,似乎Keras正在调用 custom_loss . 这使 batch_size 无而不是实际值 . 有没有一种正确的方法来重塑损失函数内的张量,避免这种错误?你可以查看完整的代码here .

1 回答

  • 0

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

    如果你使用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问题,在答案中我解释了如何使用带有Tensorflow的Keras作为后端来实现这一点 .

    ...现在关于你的代码 . 基本上,由于您有一些未定义的维度,您可以传递值-1以使其推断形状,无论它的大小如何(在第一个链接的问题中进行了解释,但也可以在docs中看到) . 就像是:

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

    或者使用Keras后端:

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

相关问题