最近在跑一个简单的CNN做图像分类,输入是64x64的RGB图,batch size设了32。网络结构就是conv+pool+fc,最后一层fc我算过应该输出128维,然后接一个Linear(128, 10)。但一跑训练就报错:size mismatch for fc2.weight: copying a param with shape torch.Size([64, 128]) from checkpoint, but the checkpoint has torch.Size([32, 128])。
我明明记得模型定义里是128输入到10输出,怎么加载权重时它说期望64?检查了state_dict的key和形状,发现是保存模型时把fc2写错了,但代码里没改过啊……是不是我哪里对nn.Sequential的索引理解有误?求指点,网上搜了一圈全是英文,看得头疼。
用PyTorch训练时报错shape不匹配,但自查逻辑没问题,大佬们帮看看?
全部回复
共 53 条你这个报错信息里其实已经写得很清楚了,checkpoint里存的是[32,128],但模型加载时想要的是[64,128],所以问题大概率不是模型定义,而是你保存权重时用的batch size是32,加载时却用了64。我也经常踩这种坑,建议你在保存模型时别直接用state_dict,而是把整个模型结构一起存下来,或者检查一下是不是哪里不小心改了fc层的输入维度。另外可以打印一下模型每一层的shape对比下,十有八九是前面卷积或者pool的输出尺寸算错了,导致fc输入不是128而是64。
看这个报错信息,感觉问题可能不在模型定义上,而是出在加载checkpoint的方式上。你是不是用了什么预训练权重或者保存过多次模型?报错里说fc2.weight期望是[64,128]但checkpoint里是[32,128],这明显是checkpoint里的参数和你当前模型的结构对不上,可能你保存模型的时候batch size是32,但加载时模型里fc2的输入维度被改成了64?建议直接打印一下你加载的state_dict里每个key的shape,和你当前模型的一一比对,多半能找到是哪一层定义错了。另外如果用的是官方预训练权重,记得看下他们用的输入尺寸是不是和你一样是64x64,说不定人家默认是224x224。
这报错摆明是checkpoint和模型结构对不上,你是不是保存权重前改过网络,或者加载时没建对模型?
这报错信息其实已经说得挺清楚了,checkpoint里存的fc2权重是[32,128],但你模型现在加载时期望的是[64,128]。也就是说要么你保存权重时的模型结构和现在不完全一样,要么中间改过fc层的输入维度,比如pool之后没展平直接接了fc,导致实际输入是64而不是你手算的128。建议你在加载checkpoint前先print一下当前模型的fc2.weight.shape,再对比一下保存时的状态字典,大概率能找到差异。我之前也踩过类似的坑,多半是模型定义里某个卷积层的padding或stride改了一下,后面全连接输入维度就全变了。
可能是之前保存的模型结构和现在定义的不一致,建议打印下当前模型的fc层尺寸和checkpoint里的对比下。
你这报错其实不是shape逻辑问题,是加载checkpoint时把旧模型的fc2权重盖到新结构上了。错误里期望64、checkpoint是32,说明保存权重那版模型最后一层fc输出维度跟现在不一样。先确认是不是没加strict=False,或者干脆别load旧权重,只加载backbone部分试试。
这报错其实挺典型的,关键点在于错误信息里的“from checkpoint”和“the checkpoint has”,说明你大概率是在加载某个预训练权重或者之前保存的模型,而不是单纯跑前向时报的shape不匹配。你自查网络定义是128到10没错,但加载的权重里fc2.weight却是64x128,这就意味着保存权重时的模型结构和你现在定义的模型不是同一个版本。我遇到过类似情况,往往是中间改过fc1的输出维度,比如从64改到128,但旧权重没重新训练,加载时就会炸。建议你先把torch.load出来的state_dict打印一下,看看每一层的shape,再和你当前模型的state_dict逐层对比,差异一眼就能看出来。另外也要注意load_state_dict默认strict=True,如果只是部分层对不上,可以先用strict=False看看哪些层被跳过,但正式训练前最好还是让结构完全一致。如果确实是旧权重,要么重新训练,要么把当前模型fc1改成64再加载,别硬扛。
你贴的报错里写的是从checkpoint加载,但描述里又在说训练,这俩场景不太一样啊。如果是加载预训练权重,那大概率是保存的那个模型fc2输出是64类,跟你现在定义的10类对不上,跟batch size没关系。建议先print一下checkpoint里所有key的shape,跟当前模型逐层对一遍,基本就能定位到是哪层结构改过了。
这个报错其实不是模型定义的问题,是你加载的 checkpoint 里 fc2.weight 形状是 [32,128],而当前模型期望 [64,128],说明保存权重时的模型结构和现在这套对不上。你说的 Linear(128,10) 没错,但报错里的 64 和 32 很可能来自前面的通道数或 batch 维度,跟输出 10 没关系,建议打印一下 state_dict 的 key 和 shape 对比。另外确认下加载时是不是 strict=True,可以先 strict=False 看看到底哪几层不匹配。
你贴的报错是加载checkpoint时shape对不上,跟模型定义其实没关系。检查一下你保存权重的时候是不是用了DataParallel或者多卡训练,那样fc2.weight会多出一个卡数的维度,恢复时得用model.module.load_state_dict或者去掉module.前缀。另外你标题里说Linear(128,10),但报错期望的是64,这俩数字对不上,建议先把实际打印的模型结构贴出来看看。
你贴的报错其实是加载checkpoint时对不上,不是前向传播挂的。fc2.weight期望64x128说明你保存权重那版模型最后一层输入是64,现在这版变成128了,多半是中间某层通道数改过或者flatten后维度算错了。建议先print一下模型fc2的in_features,再对比checkpoint里的shape,基本就定位了。另外输入64x64经过几层下采样后实际拉平是多少,也得跟着核对一遍。
你那个报错里写着从checkpoint加载,是不是加载了别的模型权重?看错误提示expected [64,128]但checkpoint是[32,128],这俩维度明显对不上,跟你说的128到10完全不是一回事。先确认下是不是load_state_dict时把旧模型的权重塞进来了,或者保存的时候存错了对象。我之前也踩过这种坑,模型结构改了但权重文件没更新,报的错跟实际位置差十万八千里。
这个报错其实跟模型定义没关,是你在加载 checkpoint 的时候,fc2.weight 的维度对不上——checkpoint 里存的是 [32,128],说明保存那会儿 fc2 的输入维度是 32,不是现在的 128。大概率是你之前改过网络结构(比如某个 fc 层输出从 32 改成 128),但加载的是旧权重。可以先 print 一下当前模型 fc2.weight.shape 和 checkpoint 里对应的 key,对比下就清楚了,实在不行就换个匹配的权重或者干脆不加载这一层。