训练MLM任务NLP模型时出现Unable to create tensor报错求助
trainer.train()抛出张量创建错误 我正在为MLM(掩码语言模型)任务训练NLP模型,但调用trainer.train()函数时抛出以下错误:
Unable to create tensor, you should probably activate truncation
and/or padding with 'padding=True' 'truncation=True' to have batched
tensors with the same length. Perhaps your features (input_idsin
this case) have excessive nesting (inputs typelistwhere typeint
is expected).
我严格遵循Hugging Face教程操作,但仍不清楚问题所在,相关代码如下:
from transformers import AutoTokenizer,AutoModelForMaskedLM cp= "tau/tavbert-he" model=AutoModelForMaskedLM.from_pretrained(cp) tokenizer=AutoTokenizer.from_pretrained(cp) import datasets ds=datasets.load_dataset("csv", data_files='/content/drive/Shareddrives/Embible/data.csv') ds=ds['train'].train_test_split(train_size=0.8, seed=42) def tokenize_function(dataset): return tokenizer(str(dataset["verse"]),truncation=True,padding=True , max_length=512, return_overflowing_tokens=True) tokenized_ds=ds.map(tokenize_function) from transformers import DataCollatorForLanguageModeling data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm_probability=0.15) tokenized_ds=tokenized_ds.remove_columns(ds["train"].column_names) from transformers import TrainingArguments from transformers import Trainer training_args = TrainingArguments("test-trainer") trainer = Trainer( model, training_args, train_dataset=tokenized_ds['train'], eval_dataset=tokenized_ds["test"], data_collator=data_collator, tokenizer=tokenizer, ) trainer.train()
问题原因及修复方案
1. 错误的文本处理导致嵌套结构
你的tokenize_function中使用str(dataset["verse"])会把整个batch的文本列表转换成单个字符串(比如把["文本1", "文本2"]变成"['文本1', '文本2']"),tokenizer处理这个字符串后会生成嵌套多层的input_ids结构,不符合模型要求的二维列表格式(每个样本对应一维token列表)。
修复方法:去掉str(),直接传入dataset["verse"],tokenizer支持直接接收列表类型的批量输入:
def tokenize_function(dataset): return tokenizer(dataset["verse"], truncation=True, padding=True, max_length=512, return_overflowing_tokens=True)
2. 处理溢出样本的映射关系
启用return_overflowing_tokens=True时,tokenizer会生成overflow_to_sample_mapping字段,用于关联新生成的溢出样本和原始样本。需要在映射时处理该字段,避免后续数据集结构混乱:
def tokenize_function(dataset): outputs = tokenizer( dataset["verse"], truncation=True, padding=True, max_length=512, return_overflowing_tokens=True ) # 移除映射字段并调整数据集关联(如果有其他字段需要保留) sample_mapping = outputs.pop("overflow_to_sample_mapping") # 若原始数据集有其他字段(如标签),需同步复制对应数据: # outputs["your_field_name"] = [dataset["your_field_name"][i] for i in sample_mapping] return outputs # 显式指定batched=True确保批量处理(默认已开启,显式更清晰) tokenized_ds = ds.map(tokenize_function, batched=True)
3. 验证数据集结构
修复后可通过tokenized_ds['train'][0]['input_ids']检查结构,确保是整数列表而非嵌套列表,且所有样本的input_ids长度一致(已通过padding=True保证)。
内容的提问来源于stack exchange,提问作者Harel Moshayof

