使用Hugging Face Trainer API微调TimeSformer遇NoneType len()错误
TimeSformer微调时Trainer触发
TypeError: object of type 'NoneType' has no len()的解决办法 问题背景
- 使用Hugging Face Trainer API微调TimeSformer模型做视频分类
- 环境版本:
transformers==4.31.0、torch==2.0.1、accelerate==0.27.0 - 自定义
VideoFrameDataset加载视频帧数据,直接测试模型时数据可正常运行,但调用trainer.train()时触发错误:TypeError: object of type 'NoneType' has no len()
错误原因分析
Trainer会自动对数据集执行预处理、长度校验等操作,触发该错误的核心原因是数据链路中存在None值,且Trainer无法处理这种无效数据,常见场景包括:
- 自定义Dataset的
__getitem__方法在部分样本加载失败时返回了None,直接测试未覆盖到这类坏样本 - Dataset未正确实现
__len__方法,导致Trainer调用len(dataset)时得到None - 数据预处理管道中某一步返回了None,Trainer遍历数据时触发长度校验错误
解决办法
1. 修复Dataset的__getitem__方法,确保无None返回
添加异常捕获逻辑,避免样本加载失败时返回None,同时记录错误样本:
def __getitem__(self, idx): try: frames = self.load_frames(self.video_paths[idx]) label = self.labels[idx] # 确保返回格式符合模型输入要求 return {"pixel_values": frames, "labels": label} except Exception as e: print(f"加载样本{idx}失败: {e}") # 返回占位数据,避免中断训练(或根据需求跳过该样本) return {"pixel_values": torch.zeros(self.num_frames, 3, 224, 224), "labels": 0}
同时遍历全量数据集,排查是否存在返回None的样本:
for idx in range(len(dataset)): sample = dataset[idx] if sample is None or any(v is None for v in sample.values()): print(f"无效样本索引: {idx}")
2. 确保Dataset正确实现__len__方法
检查VideoFrameDataset的__len__方法,确保返回有效整数:
def __len__(self): # 确保self.video_paths是已初始化的非空列表 return len(self.video_paths)
3. 检查预处理函数的返回值
如果使用了自定义预处理逻辑,确保每个样本处理后都返回包含pixel_values和labels的有效字典:
def preprocess_sample(sample): processed_frames = self.processor( sample["pixel_values"], return_tensors="pt" )["pixel_values"].squeeze() return {"pixel_values": processed_frames, "labels": sample["labels"]}
4. 自定义Trainer的collate_fn过滤无效数据
如果默认的collate_fn无法处理异常样本,自定义一个过滤逻辑:
from transformers import default_data_collator def custom_collate_fn(batch): # 过滤掉所有None类型的样本 batch = [item for item in batch if item is not None] return default_data_collator(batch)
初始化Trainer时传入该函数:
trainer = Trainer( model=model, args=training_args, train_dataset=train_dataset, eval_dataset=eval_dataset, data_collator=custom_collate_fn )
验证步骤
- 单独遍历训练集和验证集,确认所有样本都能返回有效数据
- 用少量样本(比如前10个)测试
trainer.train(),缩小错误范围
内容的提问来源于stack exchange,提问作者Hamza Azhar
相关产品推荐
相关产品推荐

