基于PyTorch Hub的I3D ResNet微调自定义数据集池化层报错问题
问题解决:I3D ResNet微调时池化层输入尺寸不匹配报错
报错原因
你使用的I3D R50是针对Kinetics 400数据集的32帧输入设计的,模型头部的AvgPool3d默认核尺寸为(4,7,7)。而你输入的是5帧图像,经过模型前几层的时间维度下采样后,到池化层时时间维度被压缩至2,小于池化核的时间维度4,因此触发尺寸不匹配报错。
两种解决方法
方法1:调整输入帧数量(推荐,对齐预训练设置)
将自定义Dataset中返回的图像序列长度从5帧改为32帧(和预训练数据集的输入规格一致),这样经过模型下采样后,时间维度会刚好匹配池化核的要求。如果你的数据集单段视频帧不足32,可以通过帧重复或插值补帧的方式补充:
# 示例:将5帧补到32帧(重复帧方式) processed_images = processed_images.repeat(7, 1, 1, 1)[:32] # 5*7=35,取前32帧
方法2:修改模型头部的池化层
如果无法调整输入帧数量,直接修改模型最后一层的池化核尺寸,让时间维度的核大小等于下采样后的实际尺寸(此处为2):
model = torch.hub.load("facebookresearch/pytorchvideo", "i3d_r50", pretrained=True) num_classes = 4 # 修改输出全连接层 model.blocks[6].proj = torch.nn.Linear(2048, num_classes) # 修改池化层,将时间维度核大小从4改为2 model.blocks[6].pool = torch.nn.AvgPool3d(kernel_size=(2, 7, 7), stride=(1, 1, 1))
额外注意点
你的target是独热编码张量,但PyTorch的CrossEntropyLoss默认要求输入是类别索引(形状为[batch_size])而非独热编码。如果用独热编码计算损失,需要改用BCELoss并在模型输出后加sigmoid激活,或者将target转换为类别索引:
# 将独热编码转为类别索引 labels_ = torch.argmax(labels_, dim=1)
内容的提问来源于stack exchange,提问作者Carlo
相关产品推荐
相关产品推荐

