Tensorflow 2.x – 具有周围细胞平均值的张量
Tensorflow 2.x – Tensor with Average of Surrounding Cells
我正在尝试在 Tensorflow 2.x 中编写一个自定义损失函数,它鼓励输出 space(二维矩阵)中的渐变。因此,作为损失函数的一个组成部分,我想输入一个 Tensor 和 return 一个 Tensor,其中每个单元格代表原始张量中相应相邻单元格的平均值。
例如,取左上角的单元格: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 是输出矩阵维度。
您可以在大多数情况下使用 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 ]]]
我正在尝试在 Tensorflow 2.x 中编写一个自定义损失函数,它鼓励输出 space(二维矩阵)中的渐变。因此,作为损失函数的一个组成部分,我想输入一个 Tensor 和 return 一个 Tensor,其中每个单元格代表原始张量中相应相邻单元格的平均值。
例如,取左上角的单元格: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 是输出矩阵维度。
您可以在大多数情况下使用 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 ]]]