TensorFlow 混合精度下自定义损失函数为何出现 dtype 不匹配?
数据小陈
在 TensorFlow 的 mixed_float16 策略下,自定义损失函数接收的 y_true 和 y_pred 可能分别是 float32 和 float16。示例中的 y_true - y_pred 会因两者类型不同而触发 Sub 操作错误。
为什么会出现类型不匹配
混合精度策略通常让模型层使用 float16 计算,同时让变量保持为 float32。训练标签通常仍为 float32,模型输出则可能是 float16。因此,损失函数需要处理输入类型不同的情况。
在损失函数中统一使用 float32
对数值敏感的损失计算,可以先将预测值和标签都转换为 float32,再计算差值和均值:
import tensorflow as tf
from tensorflow.keras import mixed_precision
mixed_precision.set_global_policy("mixed_float16")
def custom_mse(y_true, y_pred):
y_true = tf.cast(y_true, tf.float32)
y_pred = tf.cast(y_pred, tf.float32)
diff = y_true - y_pred
return tf.reduce_mean(tf.square(diff))
这样,减法两侧的 dtype 就一致了,损失计算也会在 float32 中进行。将这个损失函数用于原来的 model.compile(optimizer=tf.keras.optimizers.Adam(), loss=custom_mse),可以避免示例中的减法类型冲突。
可选做法:让输出层返回 float32
如果需要模型最后一层输出 float32,可以显式指定该层的 dtype:
model = tf.keras.Sequential([
tf.keras.layers.Dense(64, activation="relu"),
tf.keras.layers.Dense(1, dtype="float32"),
])
这样最后一层会输出 float32。自定义损失函数仍可显式转换输入类型,以免依赖输出层的配置。
注意事项
原问题片段中的 diff = y_true - y_pred 和错误信息都指向 Sub 运算。应检查损失函数中参与运算的张量类型,并将它们统一。具体 dtype 行为可能因 TensorFlow 和 Keras 版本以及模型配置而异。遇到类似问题时,可以查看损失函数中的 y_true.dtype 和 y_pred.dtype,再选择统一的计算类型。
备注:内容仅供参考。
