最近为了找创新点,重拾pytorch,在看小土堆的网课时,报了些错误,于是整理了一下。
(1)需要引用的库不同
Conv2d需要引用torch.nn,(即import torch.nn)
conv2d是torch.nn.functional中的方法,需要引用torch.nn.functional(即 import torch.nn.functional),引用错会报NameError: name ‘conv2d’ is not defined
(2)传参方式不同
Conv2d()的传参方式如下:
in_channels代表输入图片的通道数
out_channels代表输出图片的通道数
kernal_size代表卷积核的大小,如果是nn的卷积核,则kernal_size = n,如果是ab的卷积核,则kernal_size = [a,b],在这里Conv2d()的作用是在前向网络中搭建一个卷积层,所以用户没法自定义卷积核中的每个参数,只能由pytorch自己初始化。
stride代表卷积核的步长
padding代表在图片周围补充的像素数量,如果在图片上下分别补充了x1行0,在图片的左右分别补充了x2列0,那么我们可以令padding = [x1, x2]
dilation代表卷积核之间参数的距离,如果dilation = 1,那么卷积核中各参数连续排列,如果dilation = 2,那么卷积核中各参数(在横向和纵向上)相距一个像素。(如下图所示)
其余参数一般保持默认
conv2d()的传参方式如下:
input是输入图像,必须是tensor形式,且需要通过reshape()转换为特定的格式,具体转换方式见代码。
(tensor形式可使用torchvision.transforms.ToTensor(imag)进行类型转换)
这里的weight其实是卷积核kernal,也必须是tensor形式
conv2d()执行的操作是:用我们定义好的卷积核kernal对输入图像进行卷积操作,而不是作为前向通道的一部分。
如果误将conv2d的参数传给Conv2d,例如误将conv2d(input, kernal, stride=1)写成Conv2d(input,kernal,kernel_size=3,stride=1),那么可能报错:RuntimeError: Boolean value of Tensor with more than one value is ambiguous
conv2d代码演示
程序功能:输入一个矩阵或图像(input),接着自定义一个卷积核kernal,用kernal对输入矩阵进行卷积操作
import torch.nn.functional as F
#import torch.nn as F
input = torch.tensor([[1, 2, 0, 1, 1],
[2, 2, 0, 3, 6],
[1, 2, 5, 3, 1],
[5, 3, 0, 4, 1],
[1, 2, 3, 4, 5]])
kernal = torch.tensor([[1, 2, 1],
[0, 0, 0],
[-1, -2, -1]])
input = torch.reshape(input, (1, 1, 5, 5)) #(channel数为1, ??, input的size为4*5)
kernal = torch.reshape(kernal, (1, 1, 3, 3)) #(channel数为1, ??, input的size为3*3)
#RuntimeError: shape '[1, 1, 3, 3]' is invalid for input of size 20
# 这种错误是因为reshape的第一个参数和第二个没对应起来
print(input.shape)
print(kernal.shape)
output = F.conv2d(input, kernal, stride=1) #之前使用Conv2d,一直不好使。后来发现要用conv2d,又报错找不到conv2d,但是conv2d下还不报错,以为是版本问题,
#最后发现我在一开始引用了torch.nn ,改为import torch.nn.functional 问题解决。
#output2 = F.Conv2d(input, kernal, kernel_size=3,stride=1) #要import torch.nn 才能使用Conv2d,但是使用方法是不同的
print(output)
Conv2d代码演示
程序功能:搭建一个只有单层卷积层的前向传播网络,卷积核由pytorch随机初始化,卷积核大小为3
#搭建一个卷积层
import torch
import torchvision
from tensorboardX import SummaryWriter
from torch import nn
from torch.nn import Conv2d
from torch.utils.data import DataLoader
from torchvision.transforms import ToTensor
dataset = torchvision.datasets.CIFAR10("./dataset", train=False, transform=torchvision.transforms.ToTensor(),download=True) #获取测试集
dataloader = DataLoader(dataset, batch_size=64) #以64张为一组,抽取数据
class single_conv(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = Conv2d(in_channels=3, out_channels=6, kernel_size=3, stride=1, bias=True)
def forward(self, input):
output = self.conv1(input)
return output
writer = SummaryWriter("./Ni_Conv2d")
Ni_Conv2d = single_conv()
step = 1
for data in dataloader:
image, target = data
print(image.type)
# x = ToTensor(image) image已经是tensor数据类型了,所以不需要转换了
output = Ni_Conv2d(image) #这里写Ni_Conv2d()或者Ni_Conv2d.forward()都是可以的,前者是通过内置的__call__来调用的
print(image.shape) # torch.Size([64, 3, 32, 32])
print(output.shape) # torch.Size([64, 6, 30, 30]) 从数据结果来看,因为未加padding,所以从32*32变为了30*30
output2 = torch.reshape(output, (-1, 3, 30, 30)) #最好一步一步实例化,而不要只写一行 torch.reshape(output, (-1, 3, 30, 30)),
# 这样是没法改变output的数据形式的
print(output2.shape)
#output是六通道的,无法显示所以我们需要从【64, 6, 30, 30】 -->【xx, 3, 30, 30】 所以xx=128
writer.add_images("output", output2, step)
step = step + 1
writer.close()