使用BERT文本分类遇数据适配器错误,请求技术支持
BERT文本分类训练数据适配器错误解决
问题背景
使用BERT进行文本分类时,执行训练代码触发数据适配器错误,无法正常启动训练流程。
数据集示例
| content | catalogPath_level_1 |
|---|---|
| mobility academy rolling stock technical and p... | TM |
| trackguard sicas ecc ... | TM |
| zuverlässigkeit von verteiltem juridical recor... | TMR |
| wbt simis d hardware projektierung innenraum... | TMR |
现有代码
分词器代码
def tokenize_function(text): return tokenizer(text.numpy(), padding=True, truncation=True, return_tensors='tf') def tf_tokenize(text): result = tf.py_function(tokenize_function, [text], Tout=tf.int32) result.set_shape([None, None]) return result
网络层定义
text_input = tf.keras.layers.Input(shape=(), dtype=tf.float32, name='input_ids') tokenized_input = tf.keras.layers.Lambda(tf_tokenize)(text_input) outputs = bert_encoder(tokenized_input) pooled_output = outputs[0][:, 0] # Neural network layers l = tf.keras.layers.Dropout(0.1, name="dropout")(pooled_output) l = tf.keras.layers.Dense(4, activation='sigmoid', name="output")(l) # Use inputs and outputs to construct a final model model = tf.keras.Model(inputs=[text_input], outputs = [l])
优化器与编译
optimizer = tf.keras.optimizers.Adam() loss = tf.keras.losses.CategoricalCrossentropy() model.compile(optimizer=optimizer, loss=loss, metrics='accuracy')
训练代码
model.fit(X_train, Y_train, epochs=10)
错误信息
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) Cell In[23], line 1 ----> 1 model.fit(X_train, Y_train, epochs=10) File ~\AppData\Roaming\Python\Python310\site-packages\keras\utils\traceback_utils.py:70, in filter_traceback..error_handler(*args, **kwargs) 67 filtered_tb = _process_traceback_frames(e.__traceback__) 68 # To get the full stack trace, call: 69 # `tf.debugging.disable_traceback_filtering()` ---> 70 raise e.with_traceback(filtered_tb) from None 71 finally: 72 del filtered_tb File ~\AppData\Roaming\Python\Python310\site-packages\keras\engine\data_adapter.py:1082, in select_data_adapter(x, y) 1079 adapter_cls = [cls for cls in ALL_ADAPTER_CLS if cls.can_handle(x, y)] 1080 if not adapter_cls: 1081 # TODO(scottzhu): This should be a less implementation-specific error. ---> 1082 raise ValueError( 1083 "Failed to find data adapter that can handle input: {}, {}".format( 1084 _type_name(x), _type_name(y) 1085 ) 1086 ) 1087 elif len(adapter_cls) > 1: 1088 raise RuntimeError( 1089 "Data adapters should be mutually exclusive for " 1090 "handling inputs. Found multiple adapters {} to handle " 1091 "input: {}, {}".format(adapter_cls, _type_name(x), _type_name(y)) 1092 ) ValueError: Failed to find data adapter that can handle input: , ( containing values of types {""})
解决方案
1. 修正输入层数据类型错误
输入层定义时将dtype=tf.float32改为tf.string,因为输入是文本字符串:
text_input = tf.keras.layers.Input(shape=(), dtype=tf.string, name='input_text')
2. 标准化数据集格式
- X_train:必须转换为TensorFlow可识别的张量或
tf.data.Dataset对象,不能直接传入原始Pandas DataFrame。转换方式:X_train_tensor = tf.convert_to_tensor(X_train.values, dtype=tf.string) - Y_train:使用
CategoricalCrossentropy损失要求标签为独热编码格式,需先完成标签编码与独热转换:from sklearn.preprocessing import LabelEncoder, OneHotEncoder import numpy as np # 标签编码:将字符串标签转为整数 le = LabelEncoder() y_train_encoded = le.fit_transform(Y_train) # 独热编码:转为模型可接受的格式 ohe = OneHotEncoder(sparse_output=False) Y_train = ohe.fit_transform(y_train_encoded.reshape(-1, 1))
3. 匹配激活函数与损失函数
CategoricalCrossentropy损失对应softmax激活函数,而非sigmoid,修改输出层:
l = tf.keras.layers.Dense(4, activation='softmax', name="output")(l)
4. 优化分词流程(推荐)
将分词逻辑提前到数据集处理阶段,避免在模型内部使用tf.py_function(性能差且易出问题):
def tokenize_text(text, label): # 解码字符串并分词 tokens = tokenizer(text.numpy().decode('utf-8'), padding='max_length', truncation=True, max_length=128) return (tokens['input_ids'], tokens['attention_mask']), label def tf_tokenize_text(text, label): return tf.py_function(tokenize_text, [text, label], Tout=((tf.int32, tf.int32), tf.float32)) # 构建训练数据集 train_dataset = tf.data.Dataset.from_tensor_slices((X_train_tensor, Y_train)) train_dataset = train_dataset.map(tf_tokenize_text).batch(32) # 调整模型输入为BERT所需的input_ids和attention_mask input_ids = tf.keras.layers.Input(shape=(128,), dtype=tf.int32, name='input_ids') attention_mask = tf.keras.layers.Input(shape=(128,), dtype=tf.int32, name='attention_mask') outputs = bert_encoder({'input_ids': input_ids, 'attention_mask': attention_mask}) pooled_output = outputs[1] # BERT的pooled_output通常对应outputs[1] l = tf.keras.layers.Dropout(0.1)(pooled_output) l = tf.keras.layers.Dense(4, activation='softmax')(l) model = tf.keras.Model(inputs=[input_ids, attention_mask], outputs=l)
5. 执行训练
如果使用优化后的数据集,训练代码改为:
model.fit(train_dataset, epochs=10)
核心问题总结
- 输入层数据类型错误,将文本输入设为float32导致TensorFlow无法识别数据格式。
- 标签格式不匹配,未将字符串标签转为独热编码,无法适配
CategoricalCrossentropy损失。 - 激活函数与损失函数不匹配,
sigmoid不适用于多分类场景的CategoricalCrossentropy。
内容的提问来源于stack exchange,提问作者Ashok Kumar Reddy Kummetha
相关产品推荐
相关产品推荐

