我正在为自己构建一些基于Tensorflow和Keras的框架。首先,我只写了框架的核心,并实现了第一个玩具示例。这个玩具示例只是解决XOR的经典前馈网络。
可能不必解释其周围的所有内容,但我实现了损失函数,如下所示:
class MeanSquaredError(Modality):
def loss(self, y_true, y_pred, sample_weight=None):
y_true = tf.cast(y_true, dtype=y_pred.dtype)
loss = tf.keras.losses.MeanSquaredError(reduction=tf.keras.losses.Reduction.NONE)(y_true, y_pred)
return tf.reduce_sum(loss) / self.model_hparams.model.batch_size
这将在实际的模型类中使用,如下所示:
class Model(keras.Model):
def loss(self, y_true, y_pred, weights=None):
target_modality = self.modalities['targets'](self.problem.hparams, self.hparams)
return target_modality.loss(y_true, y_pred)
现在,在训练方面,我可以像这样训练模型:
model.compile(
optimizer=keras.optimizers.Adam(0.001),
loss=model.loss, # Simply setting 'mse' works as well here
metrics=['accuracy']
)
或我可以只设置loss=mse
。两种情况都按预期工作,没有任何问题。
但是,我还有另一个Modality
类,该类用于序列到序列(例如翻译)任务。看起来像这样:
class CategoricalCrossentropy(Modality):
"""Simple SymbolModality with one hot as embeddings."""
def loss(self, y_true, y_pred, sample_weight=None):
labels = tf.reshape(y_true, shape=(tf.shape(y_true)[0], tf.reduce_prod(tf.shape(y_true)[1:])))
y_pred = tf.reshape(y_pred, shape=(tf.shape(y_pred)[0], tf.reduce_prod(tf.shape(y_pred)[1:])))
loss = tf.keras.losses.CategoricalCrossentropy(reduction=tf.keras.losses.Reduction.NONE, from_logits=True)(labels, y_pred)
return tf.reduce_mean(loss) / self.model_hparams.model.batch_size
这只是将y_true
和y_pred
张量[batch_size, seq_len, embedding_size]
改成[seq_len * batch_size, embedding_size]
的形状-有效地堆叠了所有示例。据此,计算出分类交叉熵并对其进行归一化。
现在,我正在使用的模型是一个非常简单的LSTM-但这并不重要。当我训练像这样的模型时:
model.compile(
optimizer=keras.optimizers.Adam(0.001),
loss='categorical_crossentropy', # <-- Setting the loss via string argument (works)
metrics=['accuracy']
)
该模型确实按预期学习了任务。但是,如果我从上方使用CategoricalCrossentropy
-模态,设置loss=model.loss
,则该模型根本不会收敛。损耗随机波动,但不会收敛。
这是我在head头的地方。由于简单的XOR示例可以同时使用,而且设置categorical_crossentropy
也可以使用,因此我不太明白为什么使用上述模态无效。
我做错了什么吗?
很抱歉,我无法在此处提供一个小示例,但是由于框架已经包含一些代码行,因此无法实现。从经验上讲,所有 都应该起作用。
有什么想法可以找出问题的根源或是什么原因造成的?
答案 0 :(得分:1)
您正在创建张量元组以形成形状。那可能行不通。
为什么不仅如此?
labels = tf.keras.backend.batch_flatten(y_true)
y_pred = tf.keras.backend.batch_flatten(y_pred)
标准'categorical_crossentropy'
损失不进行任何平坦化,并且将其视为类最后一个轴。
确定要拼合数据吗?如果展平,则将类数乘以步数,这似乎没有多大意义。
此外,标准'categorical_crossentropy'
损失使用from_logits=False
!
标准损失期望"softmax"
激活的输出,而from_logits=True
期望没有激活的输出。