Keras 自定义损失函数:形状为 batch_size (y_true) 的变量
Keras custom loss function: variable with shape of batch_size (y_true)
在 Keras 中实现自定义损失函数时,我需要 tf.Variable
形状与输入数据的批量大小 (y_true, y_pred)
。
def custom_loss(y_true, y_pred):
counter = tf.Variable(tf.zeros(K.shape(y_true)[0], dtype=tf.float32))
...
但是,这会产生错误:
You must feed a value for placeholder tensor 'dense_17_target' with dtype float and shape [?,?]
如果我将 batch_size 固定为一个值:
def custom_loss(y_true, y_pred):
counter = tf.Variable(tf.zeros(batch_size, dtype=tf.float32))
...
这样 |training_set| % batch_size
和 |val_set| % batch_size
等于零,一切正常。
有什么建议吗,为什么根据输入的形状(y_true
和 y_pred
)分配批量大小的变量不起作用?
解决方案
我找到了一个令人满意的有效解决方案。
我使用最大 batch_size 可能(在模型构建时指定)初始化变量,并仅使用 K.shape(y_true)[0]
来切片变量。这样它就可以完美地工作。这里的代码:
def custom_loss(y_true, y_pred):
counter = tf.Variable(tf.zeros(batch_size, dtype=tf.float32))
...
true_counter = counter[:K.shape(y_true)[0]]
...
它不起作用,因为 K.shape
returns 你是一个符号形状,它本身是一个张量,而不是一个 int 值的元组。要从张量中获取值,您必须在会话下对其进行评估。参见 documentation for this. To get a real value prior to evaluation time, use K.int_shape
: https://keras.io/backend/#int_shape
但是,K.int_shape
也不会在这里工作,因为它只是一些静态元数据,通常不会反映当前的批量大小,但有一个占位符值 None
.
您找到的解决方案(控制批量大小并在损失内使用它)确实是一个很好的解决方案。
我认为问题是因为您需要在定义时知道批处理大小来构建变量,但只有在会话 运行 时间才能知道。
如果您像使用张量一样使用它,应该没问题,请参阅此 example。
另一种解决方案是创建一个变量并使用 tf.assign
和 validate_shape=False
:
动态更改其形状
counter = tf.Variable(0.0)
...
val = tf.zeros(tf.shape(y_true)[:1], 0.0)
counter = tf.assign(counter, val, validate_shape=False)
在 Keras 中实现自定义损失函数时,我需要 tf.Variable
形状与输入数据的批量大小 (y_true, y_pred)
。
def custom_loss(y_true, y_pred):
counter = tf.Variable(tf.zeros(K.shape(y_true)[0], dtype=tf.float32))
...
但是,这会产生错误:
You must feed a value for placeholder tensor 'dense_17_target' with dtype float and shape [?,?]
如果我将 batch_size 固定为一个值:
def custom_loss(y_true, y_pred):
counter = tf.Variable(tf.zeros(batch_size, dtype=tf.float32))
...
这样 |training_set| % batch_size
和 |val_set| % batch_size
等于零,一切正常。
有什么建议吗,为什么根据输入的形状(y_true
和 y_pred
)分配批量大小的变量不起作用?
解决方案
我找到了一个令人满意的有效解决方案。
我使用最大 batch_size 可能(在模型构建时指定)初始化变量,并仅使用 K.shape(y_true)[0]
来切片变量。这样它就可以完美地工作。这里的代码:
def custom_loss(y_true, y_pred):
counter = tf.Variable(tf.zeros(batch_size, dtype=tf.float32))
...
true_counter = counter[:K.shape(y_true)[0]]
...
它不起作用,因为 K.shape
returns 你是一个符号形状,它本身是一个张量,而不是一个 int 值的元组。要从张量中获取值,您必须在会话下对其进行评估。参见 documentation for this. To get a real value prior to evaluation time, use K.int_shape
: https://keras.io/backend/#int_shape
但是,K.int_shape
也不会在这里工作,因为它只是一些静态元数据,通常不会反映当前的批量大小,但有一个占位符值 None
.
您找到的解决方案(控制批量大小并在损失内使用它)确实是一个很好的解决方案。
我认为问题是因为您需要在定义时知道批处理大小来构建变量,但只有在会话 运行 时间才能知道。
如果您像使用张量一样使用它,应该没问题,请参阅此 example。
另一种解决方案是创建一个变量并使用 tf.assign
和 validate_shape=False
:
counter = tf.Variable(0.0)
...
val = tf.zeros(tf.shape(y_true)[:1], 0.0)
counter = tf.assign(counter, val, validate_shape=False)