Tensorflow 2.x–周围单元平均值的张量

2024-06-07 04:27:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图在Tensorflow 2.x中编写一个自定义损失函数,它鼓励在输出空间(2D矩阵)中逐渐增加梯度。所以,作为损失函数的一个组成部分,我想取一个张量并返回一个张量,其中每个单元代表原始张量中对应的相邻单元的平均值

a harmonic matrix transformation

例如,以左上角的单元格为例: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是输出矩阵的维数


Tags: 函数tftensorflow空间代表矩阵单元梯度
1条回答
网友
1楼 · 发布于 2024-06-07 04:27:44

在大多数情况下,可以使用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 ]]]

相关问题 更多 >