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

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)识别

  • 13
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 28
    评论
Two-dimensional phase unwrapping: theory, algorithms, and software Phase unwrapping is a mathematical problem-solving technique increasingly used in synthetic aperture radar (SAR) interferometry, optical interferometry, adaptive optics, and medical imaging. In Two-Dimensional Phase Unwrapping, two internationally recognized experts sort through the multitude of ideas and algorithms cluttering current research, explain clearly how to solve phase unwrapping problems, and provide practicable algorithms that can be applied to problems encountered in diverse disciplines. Complete with case studies and examples as well as hundreds of images and figures illustrating the concepts, this book features: * A thorough introduction to the theory of phase unwrapping * Eight algorithms that constitute the state of the art in phase unwrapping * Detailed description and analysis of each algorithm and its performance in a number of phase unwrapping problems * C language software that provides a complete implementation of each algorithm * Comparative analysis of the algorithms and techniques for evaluating results * A discussion of future trends in phase unwrapping research * Foreword by former NASA scientist Dr. John C. Curlander Two-Dimensional Phase Unwrapping skillfully integrates concepts, algorithms, software, and examples into a powerful benchmark against which new ideas and algorithms for phase unwrapping can be tested. This unique introduction to a dynamic, rapidly evolving field is essential for professionals and graduate students in SAR interferometry, optical interferometry, adaptive optics, and magnetic resonance imaging (MRI).
评论 28
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值