编译具有不同维度输出和标签的模型(在 Tensorflow 中)
Compile model which has different dimensions of output and labels (in Tensorflow)
复制错误的最简单示例:
import tensorflow as tf
def loss(y, logits):
loss = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits))
return loss
Input = tf.keras.layers.Input(dtype=tf.float32, shape=(20,), name="X")
hidden = tf.keras.layers.Dense(40, activation=tf.keras.activations.relu, name="hidden1")(Input)
logits = tf.keras.layers.Dense(10, name="outputs")(hidden)
optimizer = tf.keras.optimizers.Adam()
model = tf.keras.Model(inputs=Input, outputs=logits)
model.summary()
model.compile(optimizer=optimizer, loss=loss)
我明白,在这种情况下,模型的输出是 (batch_size, 10) 而我的标签有 (batch_size,) 维度。这就是我使用 tf.nn.sparse_softmax_cross_entropy_with_logits
.
的原因
在我可以为该模型提供任何类型的标签之前,编译失败并出现以下错误:
C:\Stas\Development\Anaconda3\lib\site-packages\tensorflow_core\python\ops\nn_ops.py in sparse_softmax_cross_entropy_with_logits(_sentinel, labels, logits, name)
3445 raise ValueError("Rank mismatch: Rank of labels (received %s) should "
3446 "equal rank of logits minus 1 (received %s)." %
-> 3447 (labels_static_shape.ndims, logits.get_shape().ndims))
3448 if (static_shapes_fully_defined and
3449 labels_static_shape != logits.get_shape()[:-1]):
ValueError: Rank mismatch: Rank of labels (received 2) should equal rank of logits minus 1 (received 2).
经过一些调查,我发现编译失败是因为 tensorflow 以某种方式认为我的“target_output”的形状为 (None, None),而我的输出形状为(None, 10), 所以因为维数相等,不能应用稀疏交叉熵。
我了解到在TF 2.1中,可以直接将target_output作为参数进行编译,而现在是不可能的。
我继续这个的正确方法是什么?
根据 docs,您只需确保标签的形状为 [batch_size]
。这是 tf.squeeze
:
的工作示例
import tensorflow as tf
def loss(y, logits):
y = tf.squeeze(y, axis=-1)
loss = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits))
return loss
Input = tf.keras.layers.Input(dtype=tf.float32, shape=(20,), name="X")
hidden = tf.keras.layers.Dense(40, activation=tf.keras.activations.relu, name="hidden1")(Input)
logits = tf.keras.layers.Dense(10, name="outputs")(hidden)
optimizer = tf.keras.optimizers.Adam()
model = tf.keras.Model(inputs=Input, outputs=logits)
model.summary()
model.compile(optimizer=optimizer, loss=loss)
x = tf.random.normal((50, 20))
y = tf.random.uniform((50, 1), maxval=10, dtype=tf.int32)
model.fit(x, y, epochs=2)
复制错误的最简单示例:
import tensorflow as tf
def loss(y, logits):
loss = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits))
return loss
Input = tf.keras.layers.Input(dtype=tf.float32, shape=(20,), name="X")
hidden = tf.keras.layers.Dense(40, activation=tf.keras.activations.relu, name="hidden1")(Input)
logits = tf.keras.layers.Dense(10, name="outputs")(hidden)
optimizer = tf.keras.optimizers.Adam()
model = tf.keras.Model(inputs=Input, outputs=logits)
model.summary()
model.compile(optimizer=optimizer, loss=loss)
我明白,在这种情况下,模型的输出是 (batch_size, 10) 而我的标签有 (batch_size,) 维度。这就是我使用 tf.nn.sparse_softmax_cross_entropy_with_logits
.
在我可以为该模型提供任何类型的标签之前,编译失败并出现以下错误:
C:\Stas\Development\Anaconda3\lib\site-packages\tensorflow_core\python\ops\nn_ops.py in sparse_softmax_cross_entropy_with_logits(_sentinel, labels, logits, name)
3445 raise ValueError("Rank mismatch: Rank of labels (received %s) should "
3446 "equal rank of logits minus 1 (received %s)." %
-> 3447 (labels_static_shape.ndims, logits.get_shape().ndims))
3448 if (static_shapes_fully_defined and
3449 labels_static_shape != logits.get_shape()[:-1]):
ValueError: Rank mismatch: Rank of labels (received 2) should equal rank of logits minus 1 (received 2).
经过一些调查,我发现编译失败是因为 tensorflow 以某种方式认为我的“target_output”的形状为 (None, None),而我的输出形状为(None, 10), 所以因为维数相等,不能应用稀疏交叉熵。
我了解到在TF 2.1中,可以直接将target_output作为参数进行编译,而现在是不可能的。
我继续这个的正确方法是什么?
根据 docs,您只需确保标签的形状为 [batch_size]
。这是 tf.squeeze
:
import tensorflow as tf
def loss(y, logits):
y = tf.squeeze(y, axis=-1)
loss = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits))
return loss
Input = tf.keras.layers.Input(dtype=tf.float32, shape=(20,), name="X")
hidden = tf.keras.layers.Dense(40, activation=tf.keras.activations.relu, name="hidden1")(Input)
logits = tf.keras.layers.Dense(10, name="outputs")(hidden)
optimizer = tf.keras.optimizers.Adam()
model = tf.keras.Model(inputs=Input, outputs=logits)
model.summary()
model.compile(optimizer=optimizer, loss=loss)
x = tf.random.normal((50, 20))
y = tf.random.uniform((50, 1), maxval=10, dtype=tf.int32)
model.fit(x, y, epochs=2)