在 Keras 中将特定条目设置为某个值

Setting specific entries to some value in Keras

我有以下 Keras 模型代码:

def create_model():
    inputs = layers.Input((32, 32, 20))

    x = layers.Conv2D(filters, 3, padding='same')(inputs)
    x = layers.BatchNormalization()(x)
    x = layers.ReLU()(x)
    
    outputs = layers.Conv2D(6, 1, padding='same')(x)
    outputs = outputs * inputs[..., :1]
    
    model = Model(inputs, outputs)
    return model

我想根据 inputs 使用以下代码将某些 outputs 条目设置为新值:

outputs[..., 0] = tf.ones_like(inputs[..., 0]) - inputs[..., 0]

但是,它抛出一个错误:TypeError: 'KerasTensor' object does not support item assignment。我也试过使用

outputs = outputs[..., 0].assign(tf.ones_like(inputs[..., 0]) - inputs[..., 0])

但它会抛出一个不同的错误:'KerasTensor' object has no attribute 'assign'(但是,它适用于普通的 tensorflow 张量)。 那么,有没有办法将 outputs 的某些值设置为我想要的值?

我想做的事情的例子(使用数组):

inputs:
[[[0 1 0 0]
  [1 1 1 0]
  [1 0 0 0]]

 [[1 1 0 1]
  [0 1 0 1]
  [1 1 1 0]]]

outputs:
[[[ 0.538 -1.141 -0.483  0.2  ]
  [-0.418  0.087 -0.915  0.433]
  [ 0.434  1.298  1.202  1.13 ]]

 [[ 0.175  1.672  0.769  0.226]
  [ 1.203  0.019  0.107  0.09 ]
  [-0.108  0.145 -0.537  0.213]]]

outputs = outputs * inputs[..., :1]之后我得到

[[[ 0.    -0.    -0.     0.   ]
  [-0.418  0.087 -0.915  0.433]
  [ 0.434  1.298  1.202  1.13 ]]

 [[ 0.175  1.672  0.769  0.226]
  [ 0.     0.     0.     0.   ]
  [-0.108  0.145 -0.537  0.213]]]

并且 outputs[..., 0] = tf.ones_like(inputs[..., 0]) - inputs[..., 0] 我想得到

[[[ 1.    -0.    -0.     0.   ]
  [ 0.     0.087 -0.915  0.433]
  [ 0.     1.298  1.202  1.13 ]]

 [[ 0.     1.672  0.769  0.226]
  [ 1.     0.     0.     0.   ]
  [ 0.     0.145 -0.537  0.213]]]

这是一个基于 tensor_scatter_nd_update and meshgrid. For more information, check out this 的简单可行的解决方案。我还在您的模型中引入了一个 Lambda 层来计算输出。

import tensorflow as tf

def compute_output(tensor):
    outputs, inputs = tensor 
    outputs = outputs * inputs[..., :1]

    index_1, index_2, index_3 = tf.meshgrid(tf.range(tf.shape(outputs)[0]), tf.range(tf.shape(outputs)[1]), tf.range(tf.shape(outputs)[2]), indexing='ij')
    index_4 = 0 * tf.cast(tf.ones_like(outputs[..., 0]), dtype=tf.int32)
    indices = tf.stack([index_1, index_2, index_3, index_4], axis=-1)
    return tf.tensor_scatter_nd_update(outputs, indices,  tf.ones_like(inputs[..., 0]) - inputs[..., 0])

def create_model():
    inputs = tf.keras.layers.Input((32, 32, 20))

    x = tf.keras.layers.Conv2D(12, 3, padding='same')(inputs)
    x = tf.keras.layers.BatchNormalization()(x)
    x = tf.keras.layers.ReLU()(x)
    
    outputs = tf.keras.layers.Conv2D(6, 1, padding='same')(x)
    outputs = tf.keras.layers.Lambda(compute_output)((outputs, inputs)) 

    model = tf.keras.Model(inputs, outputs)
    return model

dummy_data = tf.random.normal((1, 32, 32, 20))
model = create_model()
print(model(dummy_data))