编译具有不同维度输出和标签的模型(在 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)