RuntimeError: Expected 4-dimensional input for 4-dimensional weight [32, 1, 5, 5]

2023-05-16

文章目录

  • 1. 问题引入
  • 2. 运行报错
  • 3. 代码
  • 4. 分析原因
  • 5.解决办法
  • 6. 完整代码
  • 7. 参考文献

1. 问题引入

今天在使用pytorch训练一个模型的,数据集的读取是使用pytorch自带的函数来进行读取和预处理的,网络使用的是自定义的CNN,然后在运行的时候出现了如标题所示的这种小错误。

2. 运行报错

如下所示:

RuntimeError: Expected 4-dimensional input for 4-dimensional weight [32, 1, 5, 5], but got 2-dimensional input of size [32, 784] instead

3. 代码

首先是我自己自定义的CNN网络如下所示:

class MNIST_Model(nn.Module):
    def __init__(self, n_in):
        super(MNIST_Model, self).__init__()

        self.conv1 = nn.Sequential(
            nn.Conv2d(in_channels=n_in,
                      out_channels=32,
                      kernel_size=(5, 5),
                      padding=2,
                      stride=1),
        )

        self.maxp1 = nn.MaxPool2d(
                       kernel_size=(2, 2))

        self.conv2 = nn.Sequential(
            nn.Conv2d(in_channels=32,
                      out_channels=64,
                      kernel_size=(5, 5),
                      padding=0,
                      stride=1),
        )

        self.maxp2 = nn.MaxPool2d(kernel_size=(2, 2))
        
        self.fc1 = nn.Sequential(
            nn.Linear(in_features=64 * 5 * 5, out_features=200)  # Mnist
        )

        self.fc2 = nn.Sequential(
            nn.Linear(in_features=200, out_features=10),
            nn.ReLU()
        )


    def forward(self, x):
        x = self.conv1(x)
        x = self.maxp1(x)
        x = self.conv2(x)
        x = self.maxp2(x)
        x = x.contiguous().view(x.size(0), -1)
        x = self.fc1(x)
        x = self.fc2(x)
        return x

然后是在训练模型的代码

#实例化网络,只考虑使用CPU
model = model.MNIST_Model(1)
net = model.to(device)
#定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
#momentum:动量因子有什么用处?
optimizer = optim.SGD(model.parameters(),lr=lr,momentum=momentum)


#开始训练 先定义存储损失函数和准确率的数组
losses = []
acces = []
#测试用
eval_losses = []
eval_acces = []

for epoch in range(nums_epoches):
    #每次训练先清零
    train_loss = 0
    train_acc = 0
    #将模型设置为训练模式
    model.train()
    #动态学习率
    if epoch%5 == 0:
        optimizer.param_groups[0]['lr'] *= 0.1
    for img,label in train_loader:
        #前向传播,将图片数据传入模型中
        # out输出10维,分别是各数字的概率,即每个类别的得分
        out = model(img)
        #这里注意参数out是64*10,label是一维的64
        loss = criterion(out,label)
        #反向传播
        #optimizer.zero_grad()意思是把梯度置零,也就是把loss关于weight的导数变成0
        optimizer.zero_grad()
        loss.backward()
        #这个方法会更新所有的参数,一旦梯度被如backward()之类的函数计算好后,我们就可以调用这个函数
        optimizer.step()
        
        #记录误差 
        train_loss += loss.item()
        
        #计算分类的准确率,找到概率最大的下标
        _,pred = out.max(1)
        num_correct = (pred == label).sum().item()#记录标签正确的个数
        acc = num_correct/img.shape[0]
        train_acc += acc
    losses.append(train_loss/len(train_loader))
    acces.append(train_acc/len(train_loader))
    
    eval_loss = 0
    eval_acc = 0
    model.eval()
    for img,label in test_loader:
        img = img.view(img.size(0),-1)
        
        out = model(img)
        loss = criterion(out,label)
        
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
        eval_loss += loss.item()
        
        _,pred = out.max(1)
        num_correct = (pred == label).sum().item()
        acc = num_correct/img.shape[0]
        eval_acc += acc
    eval_losses.append(eval_loss/len(test_loader))
    eval_acces.append(eval_acc/len(test_loader))
    

    print('epoch:{},Train Loss:{:.4f},Train Acc:{:.4f},Test Loss:{:.4f},Test Acc:{:.4f}'
             .format(epoch,train_loss/len(train_loader),train_acc/len(train_loader),
                    eval_loss/len(test_loader),eval_acc/len(test_loader)))

4. 分析原因

定位出错位置

Traceback (most recent call last):
  File "train.py", line 73, in <module>
    out = model(img)
  File "/home/gzdx/anaconda3/envs/Torch/lib/python3.7/site-packages/torch/nn/modules/module.py", line 889, in _call_impl
    result = self.forward(*input, **kwargs)
  File "/home/gzdx/wyf/PARAD/model.py", line 48, in forward
    x = self.conv1(x)
  File "/home/gzdx/anaconda3/envs/Torch/lib/python3.7/site-packages/torch/nn/modules/module.py", line 889, in _call_impl
    result = self.forward(*input, **kwargs)
  File "/home/gzdx/anaconda3/envs/Torch/lib/python3.7/site-packages/torch/nn/modules/container.py", line 119, in forward
    input = module(input)
  File "/home/gzdx/anaconda3/envs/Torch/lib/python3.7/site-packages/torch/nn/modules/module.py", line 889, in _call_impl
    result = self.forward(*input, **kwargs)
  File "/home/gzdx/anaconda3/envs/Torch/lib/python3.7/site-packages/torch/nn/modules/conv.py", line 399, in forward
    return self._conv_forward(input, self.weight, self.bias)
  File "/home/gzdx/anaconda3/envs/Torch/lib/python3.7/site-packages/torch/nn/modules/conv.py", line 396, in _conv_forward
    self.padding, self.dilation, self.groups)
RuntimeError: Expected 4-dimensional input for 4-dimensional weight [32, 1, 5, 5], but got 2-dimensional input of size [32, 784] instead

可以看到这句提示,大致就是我们传入的数据输入到CNN网络,然后由于维度不同导致的。因为我们输入的是四维,但是得到的却是二维。

  File "train.py", line 73, in <module>
    out = model(img)

5.解决办法

对于这种问题网上给出了很多中不同的方案,这个哦个人也是参考我网上别人给出的一点想法然后自己修改了下,错误就解决了,如下所示:

for i,data in enumerate(train_loader):
        #前向传播,将图片数据传入模型中
        # out输出10维,分别是各数字的概率,即每个类别的得分
        inputs, labels = data
        inputs,labels = data[0].to(device), data[1].to(device)
        # inputs torch.Size([32, 1, 28, 28])
        out = model(inputs)

解决办法也是很简单,就是将上面训练开始阶段将数据按照这种读取方式来赋值,然后在传入到model里面就不会出现上面那种错误了。

6. 完整代码

import numpy as np
import model
import torch

#导入PyTorch内置的mnist数据
from torchvision.datasets import mnist

#导入预处理模块
from torchvision import transforms
from torch.utils.data import DataLoader

#导入神经网络工具
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

#定义后面要用到的超参数
train_batch_size = 32
test_batch_size = 32

#学习率与训练次数
learning_rate = 0.01
nums_epoches = 50

#优化器的时候使用的参数
lr = 0.1
momentum = 0.5

#用compose来定意预处理函数
transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize([0.5],[0.5])])

#下载数据,在工程文件夹里新建一个data文件夹储存下载的数据
train_dataset = mnist.MNIST('./data', train=True, transform=transform, target_transform=None, download=False)
test_dataset = mnist.MNIST('./data', train=False, transform=transform, target_transform=None, download=False)

#数据加载器,组合数据集和采样器,并在数据集上提供单进程或多进程迭代器
train_loader = DataLoader(train_dataset, batch_size=train_batch_size, shuffle=True, num_workers=0)
test_loader = DataLoader(test_dataset, batch_size=test_batch_size, shuffle=False)

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

#实例化网络,只考虑使用CPU
model = model.MNIST_Model(1)
net = model.to(device)
#定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
#momentum:动量因子有什么用处?
optimizer = optim.SGD(model.parameters(),lr=lr,momentum=momentum)




#开始训练 先定义存储损失函数和准确率的数组
losses = []
acces = []
#测试用
eval_losses = []
eval_acces = []

for epoch in range(nums_epoches):
    #每次训练先清零
    train_loss = 0
    train_acc = 0
    #将模型设置为训练模式
    model.train()

    #动态学习率
    if epoch%5 == 0:
        optimizer.param_groups[0]['lr'] *= 0.1
    for i,data in enumerate(train_loader):
        #前向传播,将图片数据传入模型中
        # out输出10维,分别是各数字的概率,即每个类别的得分
        inputs, labels = data
        inputs,labels = data[0].to(device), data[1].to(device)
        out = model(inputs)
        #这里注意参数out是64*10,label是一维的64
        loss = criterion(out,labels)
        #反向传播
        #optimizer.zero_grad()意思是把梯度置零,也就是把loss关于weight的导数变成0
        optimizer.zero_grad()
        loss.backward()
        #这个方法会更新所有的参数,一旦梯度被如backward()之类的函数计算好后,我们就可以调用这个函数
        optimizer.step()
        
        #记录误差 
        train_loss += loss.item()
        
        #计算分类的准确率,找到概率最大的下标
        _,pred = out.max(1)
        num_correct = (pred == labels).sum().item() #记录标签正确的个数
        acc = num_correct/inputs.shape[0]
        train_acc += acc
    losses.append(train_loss/len(train_loader))
    acces.append(train_acc/len(train_loader))
    print('Finished Training') 

    # 保存模型
    PATH = './model/mnist_net.pth'
    torch.save(net.state_dict(), PATH)
    
    eval_loss = 0
    eval_acc = 0
    model.eval()
    for i,data in enumerate(test_loader):
        inputs, labels = data
        inputs,labels = data[0].to(device), data[1].to(device)
        out = model(inputs)
        loss = criterion(out,labels)
        
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
        eval_loss += loss.item()
        
        _,pred = out.max(1)
        num_correct = (pred == labels).sum().item()
        acc = num_correct/inputs.shape[0]
        eval_acc += acc
    eval_losses.append(eval_loss/len(test_loader))
    eval_acces.append(eval_acc/len(test_loader))
    

    print('epoch:{},Train Loss:{:.4f},Train Acc:{:.4f},Test Loss:{:.4f},Test Acc:{:.4f}'
             .format(epoch,train_loss/len(train_loader),train_acc/len(train_loader),
                    eval_loss/len(test_loader),eval_acc/len(test_loader)))




7. 参考文献

1.pytorch学习笔记—搭建CNN识别MNIST

2.使用Pytorch框架的CNN网络实现手写数字(MNIST)识别

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

RuntimeError: Expected 4-dimensional input for 4-dimensional weight [32, 1, 5, 5] 的相关文章

随机推荐

  • C++串口通信

    一 串口通信的基本原理 串口的本质功能是作为 CPU 和串行设备间的编码转换器 当数据从 CPU 经过串行端口发送出去时 xff0c 字节数据转换为串行的位 xff08 bit xff09 xff1b 在接收数据时 xff0c 串行的位被转
  • 死锁的四个必要条件以及处理策略

    一 什么是死锁 死锁是指两个或两个以上的进程 xff08 线程 xff09 在运行过程中因争夺资源而造成的一种僵局 例如 xff0c 某计算机系统中只有一台打印机和一台输入设备 xff0c 进程P1正占用输入设备 xff0c 同时又提出使用
  • EM算法简介

    1 简介 EM算法是一种迭代优化策略 xff0c 由于它的计算方法中每一次迭代都分两步 xff0c 其中一个为期望步 xff08 E步 xff09 xff0c 另一个为极大步 xff08 M步 xff09 xff0c 所以算法被称为EM算法
  • 三菱PLC MC协议

    1 MC协议的目的 xff1a 允许外部设备读写PLC内部寄存器 2 协议格式 xff1a 通讯方式有RS485和TCP IP两种 xff0c 通讯格式有很多种 xff1a 3E 3C 4C 4E帧格式 xff0c 通讯内容分为二进制和AS
  • find和find_if用法

    一 find的用法 STL容器中有很多find xff0c 比如说set xff0c map 他们内部都有内置的find函数 xff0c 一般情况下 xff0c 如果我们用到这些容器 xff0c 那么我们直接用它的内置find就可以了 xf
  • QTreeView节点拖放

    拖放操作分为拖动 Drag 和放置 Drop 两种操作 xff0c 当拖动时需要把拖动的数据进行存储 称为编码 xff0c 数据存储为QMimeData类型的对象 称为放置数据 xff0c 当执行放置操作时需要把存储的数据读取出来 称为解码
  • OOD七大原则

    1 单一职责原则 xff08 Single Responsibility Principle xff09 一个类或一个接口只有一个职责 xff0c 有且仅有一个原因引起变化 2 开闭原则 xff08 Open Closed Principl
  • 微服务探索之路05篇jenkins构建net6和vue docker镜像到Harbor自动更新k8s服务镜像

    从1 4篇已经学习了docker Harbor k8s的基本用法 接下来进阶一下使用jenkins结合起来做到自动部署项目 1 安装jenkins 1 1前提条件 docker环境 xff0c 可参考第01篇安装docker本文使用的是li
  • linux为用户添加sudo权限

    一 linux为用户添加sudo权限 用sudo时提示 34 xxx is not in the sudoers file This incident will be reported 其中XXX是你的用户名 xff0c 这是止当前用户没有
  • pixhawk多线程编程

    金错刀 pixhawk多线程程序编写 pixhawk源码多线程程序的编写 主要是针对pixhawk源码进行第二次开发的学习笔记 xff0c 记录下以便日后查阅 期望达到的目标 添加一个app应用 xff0c 在nsh的后台中运行该应用 xf
  • [视觉惯性导航系列]相机标定工具--kalibr

    前言 有很多博主推荐kalibr进行相机标定 我参考博主 纷繁中淡定 Kalibr标定Intel D435i相机 完成相机标定 但是kalibr在安装过程中会出现很多令人头秃的报错信息 综合了网上好多人的方法 才完成 本文做一点记录 本文不
  • C++ Exception

    Exception type Derived types scattered throughout different library headers bad alloc Exception thrown on failure alloca
  • 什么是最优化问题(Optimization Problem)?

    最优化问题是人们在科学研究和生产实践中经常遇到的问题 1 人类所从事的一切生产或者社会活动均是有目的的 其行为总是在特点的价值观念或者审美取向的支配下进行的 xff0c 因此经常面临一个可行的甚至是最优化的方案的决策问题 这就是最优化问题
  • 单例模式(java代码实现)

    应用单例模式时 xff0c 类只能有一个对象实例 xff0c 这么做的目的是避免不一致状态 饿汉式单例 xff1a xff08 立即加载 xff09 饿汉式单例 public class Singleton1 指向自己实例的私有静态引用 x
  • C++函数后面加“:”的含义

    转载 xff1a C 43 43 函数后面加 xff1a 的含义 hhd1988的专栏 CSDN博客 1 c 43 43 成员函数后面跟 xff1a 表示的是赋值 xff0c 这是c 43 43 的特性 如下 xff1a A int aa
  • 因子图(factor graph)

    因子图 xff08 factor graph xff09 Factor Graph 是概率图的一种 xff0c 概率图有很多种 xff0c 最常见的就是Bayesian Network 贝叶斯网络 和Markov Random Fields
  • 词袋模型(Bag of Features,BOF)

    Bag of Features xff08 BOF xff09 对于程序而言这个人就是一堆像素嘛 xff0c 让它直接找的话它只能一个个像素的去比较然后返回最接近的了 xff08 近邻算法 xff09 但是现实中物体的形状颜色会发生变化 x
  • SNMPv3基于用户的安全模型USM及消息格式

    一 USM相关网址 SNMPv3使用了基于用户的安全模型USM RFC 3411 Architecture for SNMP Frameworks http www ietf org rfc rfc3411 txtRFC 3414 User
  • 超详细的python搭建区块链(下)

    在前面 超详细的python搭建区块链 xff08 中 xff09 我们搭建了一个简单的区块链 在这个简单的区块链能够实现交易 挖矿等基本功能 不过 xff0c 区块链上的节点应该是分散的 如果它们是分散的 xff0c 我们究竟如何确保它们
  • RuntimeError: Expected 4-dimensional input for 4-dimensional weight [32, 1, 5, 5]

    文章目录 1 问题引入2 运行报错3 代码4 分析原因5 解决办法6 完整代码7 参考文献 1 问题引入 今天在使用pytorch训练一个模型的 xff0c 数据集的读取是使用pytorch自带的函数来进行读取和预处理的 xff0c 网络使