You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何keras.Model.fit()会将布尔张量转换为float32张量?

布尔张量在Keras fit()中自动转为float32的原因与解决方法

问题描述

构建自定义Keras模型时,输入为包含float32特征张量和布尔掩码张量的元组。直接调用模型时布尔张量类型正常,但将输入放入Dataset并使用fit()方法训练后,布尔张量被转换为float32类型,不符合掩码使用需求。

环境版本

  • TensorFlow 2.15.0
  • Keras 2.15.0
  • Python 3.11.5

可复现代码

import tensorflow as tf
from tensorflow import keras

# 定义子类化模型
class TM(keras.Model):
    def __init__(self):
        super(TM, self).__init__()

    def call(self, inputs):
        features = inputs[0]
        input_mask = inputs[1]  # 此处通过fit调用时已被转为float32,预期应为bool
        print("features:")
        print(features)
        print()

        print("input mask:")
        print(input_mask)
        print("-"*100)
        return features

# 实例化模型并编译   
tm = TM()
tm.compile(loss="mean_squared_error")

# 创建测试数据
feature_tensor = tf.random.uniform(shape=[1,8])
boolean_tensor = tf.fill(dims=[1, 8], value=True)

# 构建TensorFlow Dataset
tds = tf.data.Dataset.from_tensor_slices((feature_tensor, boolean_tensor))

# 查看Dataset元素类型(此时类型正确)
print("ds element spec:")
print(tds.element_spec)
print("-"*100)

# 直接调用模型(类型正常)
print("直接调用模型的输入情况:")
print(tm((feature_tensor, boolean_tensor)))
print("-"*100)

# 通过Dataset和fit调用模型(布尔张量被转成float32)
tm.fit(tds)

输出结果

ds element spec:
(TensorSpec(shape=(8,), dtype=tf.float32, name=None), TensorSpec(shape=(8,), dtype=tf.bool, name=None))
----------------------------------------------------------------------------------------------------
直接调用模型的输入情况:
features:
tf.Tensor(
[[0.7957325  0.694777   0.1260978  0.5917362  0.17017555 0.8500334
  0.23767495 0.88851535]], shape=(1, 8), dtype=float32)

input mask:
tf.Tensor([[ True  True  True  True  True  True  True  True]], shape=(1, 8), dtype=bool)
----------------------------------------------------------------------------------------------------
tf.Tensor(
[[0.7957325  0.694777   0.1260978  0.5917362  0.17017555 0.8500334
  0.23767495 0.88851535]], shape=(1, 8), dtype=float32)
----------------------------------------------------------------------------------------------------
features:
Tensor("tm_7/strided_slice:0", shape=(), dtype=float32)

input mask:
Tensor("tm_7/strided_slice_1:0", shape=(), dtype=float32)
----------------------------------------------------------------------------------------------------
1/1 [==============================] - 0s 66ms/step - loss: 0.0417

原因分析

  1. Keras输入自动类型对齐:fit()流程中,Keras会自动对齐输入数据类型以匹配损失函数或模型输出的类型。这里使用的mean_squared_error损失是针对float类型设计的,因此Keras会将所有输入张量统一转为float32。
  2. Dataset预处理管道差异:直接调用模型时,输入数据会直接传入call方法;而通过fit()调用时,Dataset会经过Keras内置的输入预处理管道,该管道默认会将非float类型的张量转换为float类型,以保证训练流程的类型一致性。

解决方案

方案1:在模型call方法中显式转换类型

在call方法里把被转换的mask张量重新转回bool类型:

def call(self, inputs):
    features = inputs[0]
    input_mask = tf.cast(inputs[1], tf.bool)  # 显式转回bool
    # 后续掩码逻辑
    return features

方案2:在Dataset中强制保留bool类型

通过map操作确保mask张量始终保持bool类型,覆盖Keras的自动转换:

tds = tf.data.Dataset.from_tensor_slices((feature_tensor, boolean_tensor))
tds = tds.map(lambda x, y: (x, tf.cast(y, tf.bool)))  # 强制保留bool类型

方案3:用Input层显式定义输入类型

通过Keras的Input层明确指定每个输入的dtype,让模型严格按照定义接收输入:

# 显式定义输入类型
input_features = keras.Input(shape=(8,), dtype=tf.float32)
input_mask = keras.Input(shape=(8,), dtype=tf.bool)

# 构建模型
x = input_features  # 此处可添加自定义逻辑
model = keras.Model(inputs=[input_features, input_mask], outputs=x)

model.compile(loss="mean_squared_error")
model.fit(tds)

内容的提问来源于stack exchange,提问作者triggerp420

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 05:13:09