【问题标题】:Tensorflow 2.x – Tensor with Average of Surrounding CellsTensorflow 2.x – 具有周围细胞平均值的张量
【发布时间】:2020-12-06 23:33:57
【问题描述】:

我正在尝试在 Tensorflow 2.x 中编写一个自定义损失函数,以鼓励输出空间(二维矩阵)中的渐变。所以,作为损失函数的一个组成部分,我想接受一个张量并返回一个张量,其中每个单元格代表原始张量中相应相邻单元格的平均值。

例如,取左上角的单元格:6.3 = (7 + 9 + 3)/3。或者取中间单元格:4.5 = (1 + 3 + 5 + 7 + 8 + 6 + 4 + 2)/8。

考虑以下代码:

def gradient_encouraging_loss(y_true: Tensor, y_pred: Tensor) -> Tensor:
    gradient_loss: Tensor = tf.divide(tf.reduce_sum(tf.abs(tf.subtract(
        y_pred, tensor_harmonic(y_pred)
    ))), tf.cast(tf.size(y_pred), tf.float32))

    return gradient_loss

我将如何实现tensor_harmonic()y_pred 的形状为 (None, X, Y),其中 X 和 Y 是输出矩阵的维度。

【问题讨论】:

    标签: python arrays tensorflow tensorflow2.0 loss-function


    【解决方案1】:

    大多数情况下,您可以使用 2D 卷积操作来做到这一点,但您需要特别注意外部值。你可以这样做:

    import tensorflow as tf
    
    def surround_average(x):
        x = tf.convert_to_tensor(x)
        dt = x.dtype
        # Compute surround sum
        filter = tf.constant([[1, 1, 1], [1, 0, 1], [1, 1, 1]], dtype=dt)
        x2 = x[tf.newaxis, :, :, tf.newaxis]
        filter2 = filter[:, :, tf.newaxis, tf.newaxis]
        y2 = tf.nn.conv2d(x2, filter2, strides=1, padding='SAME')
        y = y2[0, :, :, 0]
        # Make matrix of number of surrounding elements
        s = tf.shape(x)
        d = tf.fill(s - 2, tf.constant(8, dtype=dt))
        d = tf.pad(d, [[0, 0], [1, 1]], constant_values=5)
        top_row = tf.concat([[3], tf.fill([s[1] - 2], tf.constant(5, dtype=dt)), [3]], axis=0)
        d = tf.concat([[top_row], d, [top_row]], axis=0)
        # Return average
        return y / d
    
    # Test
    x = tf.reshape(tf.range(24.), (4, 6))
    print(x.numpy())
    # [[ 0.  1.  2.  3.  4.  5.]
    #  [ 6.  7.  8.  9. 10. 11.]
    #  [12. 13. 14. 15. 16. 17.]
    #  [18. 19. 20. 21. 22. 23.]]
    print(surround_average(x).numpy())
    # [[ 4.6666665  4.6        5.6        6.6        7.6        8.333333 ]
    #  [ 6.6        7.         8.         9.        10.        10.4      ]
    #  [12.6       13.        14.        15.        16.        16.4      ]
    #  [14.666667  15.4       16.4       17.4       18.4       18.333334 ]]
    

    编辑:上面的代码可以通过一些小的改动来适应成批的矩阵:

    import tensorflow as tf
    
    def surround_average_batch(x):
        x = tf.convert_to_tensor(x)
        dt = x.dtype
        # Compute surround sum
        filter = tf.constant([[1, 1, 1], [1, 0, 1], [1, 1, 1]], dtype=dt)
        x2 = tf.expand_dims(x, axis=-1)
        filter2 = filter[:, :, tf.newaxis, tf.newaxis]
        y2 = tf.nn.conv2d(x2, filter2, strides=1, padding='SAME')
        y = tf.squeeze(y2, axis=-1)
        # Make matrix of number of surrounding elements
        s = tf.shape(x)
        d = tf.fill(s[1:] - 2, tf.constant(8, dtype=dt))
        d = tf.pad(d, [[0, 0], [1, 1]], constant_values=5)
        top_row = tf.concat([[3], tf.fill([s[2] - 2], tf.constant(5, dtype=dt)), [3]], axis=0)
        d = tf.concat([[top_row], d, [top_row]], axis=0)
        # Return average
        return y / d
    
    # Test
    x = tf.reshape(tf.range(24.), (2, 4, 3))
    print(x.numpy())
    # [[[ 0.  1.  2.]
    #   [ 3.  4.  5.]
    #   [ 6.  7.  8.]
    #   [ 9. 10. 11.]]
    # 
    #  [[12. 13. 14.]
    #   [15. 16. 17.]
    #   [18. 19. 20.]
    #   [21. 22. 23.]]]
    print(surround_average_batch(x).numpy())
    # [[[ 2.6666667  2.8        3.3333333]
    #   [ 3.6        4.         4.4      ]
    #   [ 6.6        7.         7.4      ]
    #   [ 7.6666665  8.2        8.333333 ]]
    # 
    #  [[14.666667  14.8       15.333333 ]
    #   [15.6       16.        16.4      ]
    #   [18.6       19.        19.4      ]
    #   [19.666666  20.2       20.333334 ]]]
    

    【讨论】:

    • 这可以解决二维张量的问题!为了使它与一批形状为(None, X, Y) 的二维张量一起工作,我使用了tf.map_fn(fn=surround_average, elems=y_pred),其中y_pred 的形状为(None, X, Y)。谢谢!
    • @B.Freeman 我添加了一个批处理版本的功能,应该比使用tf.map_fn快很多。
    猜你喜欢
    • 1970-01-01
    • 2020-03-19
    • 2019-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多