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

PyTorch迁移至fastai时出现AttributeError问题排查与解决

问题描述

将代码从PyTorch迁移至fastai后,执行以下训练代码:

train_loader = self.init_train_dl(self.df, self.train_subjects)
test_loader = self.init_val_dl(self.df, self.val_subjects)

data = DataLoaders(train_loader, test_loader)
learn = Learner(data, AlexNet3D(4608), loss_func=F.mse_loss, opt_func=Adam, metrics=accuracy)
# learn = Learner(data, Net())
learn.fit_one_cycle(self.cli_args.epochs, self.cli_args.lr)

训练时触发如下异常:

epoch     train_loss  valid_loss  accuracy  time    
Epoch 1/1 : |----------------------------------------| 0.00% [0/135 00:00<?]python-BaseException
Traceback (most recent call last):
  File "/home/faird/shared/code/external/envs/miniconda3/mini3/envs/cabinet/lib/python3.9/contextlib.py", line 137, in __exit__
    self.gen.throw(typ, value, traceback)
  File "/home/miran045/reine097/projects/AlexNet_Abrol2021/venv/lib/python3.9/site-packages/fastai/learner.py", line 162, in added_cbs
    try: yield
  File "/home/miran045/reine097/projects/AlexNet_Abrol2021/venv/lib/python3.9/site-packages/fastai/learner.py", line 264, in fit
    self._with_events(self._do_fit, 'fit', CancelFitException, self._end_cleanup)
  File "/home/miran045/reine097/projects/AlexNet_Abrol2021/venv/lib/python3.9/site-packages/fastai/learner.py", line 199, in _with_events
    try: self(f'before_{event_type}');  f()
  File "/home/miran045/reine097/projects/AlexNet_Abrol2021/venv/lib/python3.9/site-packages/fastai/learner.py", line 253, in _do_fit
    self._with_events(self._do_epoch, 'epoch', CancelEpochException)
  File "/home/miran045/reine097/projects/AlexNet_Abrol2021/venv/lib/python3.9/site-packages/fastai/learner.py", line 199, in _with_events
    try: self(f'before_{event_type}');  f()
  File "/home/miran045/reine097/projects/AlexNet_Abrol2021/venv/lib/python3.9/site-packages/fastai/learner.py", line 247, in _do_epoch
    self._do_epoch_train()
  File "/home/miran045/reine097/projects/AlexNet_Abrol2021/venv/lib/python3.9/site-packages/fastai/learner.py", line 239, in _do_epoch_train
    self._with_events(self.all_batches, 'train', CancelTrainException)
  File "/home/miran045/reine097/projects/AlexNet_Abrol2021/venv/lib/python3.9/site-packages/fastai/learner.py", line 199, in _with_events
    try: self(f'before_{event_type}');  f()
  File "/home/miran045/reine097/projects/AlexNet_Abrol2021/venv/lib/python3.9/site-packages/fastai/learner.py", line 205, in all_batches
    for o in enumerate(self.dl): self.one_batch(*o)
  File "/home/miran045/reine097/projects/AlexNet_Abrol2021/venv/lib/python3.9/site-packages/fastai/learner.py", line 235, in one_batch
    self._with_events(self._do_one_batch, 'batch', CancelBatchException)
  File "/home/miran045/reine097/projects/AlexNet_Abrol2021/venv/lib/python3.9/site-packages/fastai/learner.py", line 199, in _with_events
    try: self(f'before_{event_type}');  f()
  File "/home/miran045/reine097/projects/AlexNet_Abrol2021/venv/lib/python3.9/site-packages/fastai/learner.py", line 219, in _do_one_batch
    self.loss_grad = self.loss_func(self.pred, *self.yb)
  File "/home/miran045/reine097/projects/AlexNet_Abrol2021/venv/lib/python3.9/site-packages/torch/nn/functional.py", line 3101, in mse_loss
    if not (target.size() == input.size()):
AttributeError: 'list' object has no attribute 'size'
问题成因
  • 核心问题是fastai的Learner在调用损失函数时,会将目标值yb以列表形式传入,但PyTorch原生的F.mse_loss仅接收PyTorch张量,直接传入列表会触发AttributeError(列表没有size()方法)。
  • 另一个可能的原因是数据加载器init_train_dl/init_val_dl返回的batch格式不符合预期:比如每个batch返回(输入张量, [目标张量])而非(输入张量, 目标张量),导致yb被包装成列表。
修复方案

方案1:包装损失函数适配列表输入

用lambda或自定义函数从yb列表中提取目标张量,再传入MSE损失:

# 用lambda快速包装
learn = Learner(data, AlexNet3D(4608), loss_func=lambda pred, yb: F.mse_loss(pred, yb[0]), opt_func=Adam, metrics=...)

或者自定义更健壮的损失函数:

def mse_loss_fastai(pred, yb):
    # 兼容列表或张量形式的目标
    target = yb[0] if isinstance(yb, list) else yb
    return F.mse_loss(pred, target)

learn = Learner(data, AlexNet3D(4608), loss_func=mse_loss_fastai, opt_func=Adam, metrics=...)

方案2:修正数据加载器的返回格式

检查init_train_dl和init_val_dl对应的数据集类,确保__getitem__方法返回单个张量的目标,而非列表:

错误示例

def __getitem__(self, idx):
    x = self.data[idx]
    y = [self.targets[idx]]  # 返回列表形式的目标
    return x, y

修正后

def __getitem__(self, idx):
    x = self.data[idx]
    y = self.targets[idx]  # 返回单个张量目标
    return x, y

额外提示

当前使用的accuracy是分类任务的指标,而MSE损失对应回归任务,两者不匹配。建议替换为回归任务适用的指标,比如fastai内置的rmse(均方根误差):

from fastai.metrics import rmse

learn = Learner(data, AlexNet3D(4608), loss_func=mse_loss_fastai, opt_func=Adam, metrics=rmse)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 03:52:32