Python/torch/深度学习——torch.nn库和torch函数参数记录
文章目录
前言
用于记录torch库和nn库函数参数。
torch库安装
安装命令如下,cuda版本以11.8为例,命令来自pytorch官方
# conda版(部分修改了镜像源可能不能用,原因不明)
conda install pytorch torchvision torchaudio pytorch-cuda=11.8 -c pytorch -c nvidia
# pip版
pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
nn.Conv2d
卷积层
torch.nn.Conv2d(
in_channels, # 输入通道数
out_channels, # 输出通道数
kernel_size, # 卷积核大小
stride=1, # 卷积核移动步长
padding=0, # 外围一圈填充的像素层数
dilation=1, # 是否采用空洞卷积,默认为1(不采用)。
# 数字表示卷积核元素之间的间距,可以是一个整数或者一个元组,如(2,2)。
# 如果为0,意味着两个参数在同一位置,不存在这种情况,因此最小为1
groups=1, # 是否采用分组卷积,可以是一个整数,默认值为1。
# nn.Conv2d的groups参数用于将输入和输出的通道进行分组,每一组单独进行卷积操作,然后再把结果拼接起来。
# 例如,输入数据大小为[1,4,5,5],输出数据大小为[1,8,5,5],groups=2。
# 这种情况下,将输入的4个通道分成2个2的通道,输出的8个通道分成2个4的通道,
# 每个输入的2个通道和输出的4个通道组成一组,每组做完卷积后的输出大小为[1,4,5,5]。
# 最后把两组结果拼起来,形成8通道的输出
bias=True, # 是否要添加偏置参数作为可学习参数中的一个,后面有BN的话一般设为False
padding_mode='zeros', # 即padding的模式,默认采用零填充
# 填充方式有reflect、zeros、circular
# zeros:用0填充
# reflect:使用图像的对称副本来填充边缘区域,即以边界为对称轴,将边界外的像素值镜像复制到边界内进行填充。
# 这样可以避免出现人工填充时可能出现的边缘效应。
# circular:循环填充。在卷积过程中,如果卷积核的边缘超出了输入张量的边缘,
# 那么就会从输入张量的另 一侧继续卷积,即将输入张量视为一个环形,从另一侧继续卷积。
device=None, # 设置学习使用的设备,即用GPU还是CPU,这个一般不在这里设置
dtype=None # 指定卷积运算的数据类型,默认使用输入数据的dtype,即为None。
)
# 示例
nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1,
stride=1, bias=False, groups=1)
nn.Conv2d(in_channels, out_channels, kernel_size=(3,3), padding=1,
stride=1, bias=False, groups=1)
参考PyTorch
尺寸计算公式如下:
nn.MaxPool2d、nn.AvgPool2d
MaxPool2d最大池化层,AvgPool2d平均池化层
MaxPool2d与nn.AvgPool2d参数几乎完全一致
区别在于MaxPool2d输出的是最大值,而AvgPool2d输出的是平均值
以下用MaxPool2d举例参数
torch.nn.MaxPool2d(
kernel_size, # 卷积核大小
stride=None, # 卷积核移动步长,默认为 kernel_size 的大小
padding=0, # 外围一圈填充的像素层数
dilation=1, # 是否采用空洞卷积,默认为1(不采用)。
return_indices=False,
ceil_mode=False # 为 True 时, 使用向上取整代替向下取整计算 shape,
# 即,如果最后剩余的像素不足 kernel_size、ceil_mode=True 时,会依然在剩余的像素中取最大值
# 否则将舍弃(W 和 H 的结果一致)
)
参考PyTorch
尺寸计算公式如下:
torch.squeeze
squeeze()函数的功能是压缩维度,返回一个tensor(张量)。
删除 input 中大小为1的所有维都已删除。
torch.squeeze(
input, # 输入Tensor类型
dim=None # 如果给了,就只压缩指定维度下的1
)
x = torch.zeros(2, 1, 2, 1, 2)
x.size()
torch.Size([2, 1, 2, 1, 2])
y = torch.squeeze(x)
y.size()
torch.Size([2, 2, 2])
y = torch.squeeze(x, 0) # 压缩0维
y.size()
torch.Size([2, 1, 2, 1, 2])
y = torch.squeeze(x, 1) # 压缩1维
y.size()
torch.Size([2, 2, 1, 2])
y = torch.squeeze(x, (1, 2, 3)) # 压缩1、2、3维
torch.Size([2, 2, 2])
nn.Sequential()
一个序列容器,用于存储神经网络模块,模块需按照执行顺序添加到nn.Sequential()容器中;模型前向传播时调用forward(),模型按照nn.Sequential()中的网络模块顺序执行。下面用一个网络模块举例
class NetWork(nn.Module):
def __init__(self):
super(NetWork, self).__init__()
self.struct1 = nn.Sequential(
nn.Conv2d(in_channels=3, out_channels=32, kernel_size=5, padding=2),
nn.MaxPool2d(2),
nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, padding=2),
nn.MaxPool2d(2),
nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, padding=2),
nn.MaxPool2d(2),
nn.Flatten(),
nn.Linear(1024, 64),
nn.Linear(64, 10),
)
self.struct2 = nn.Sequential(
nn.Conv2d(in_channels=3, out_channels=32, kernel_size=5, padding=2),
nn.MaxPool2d(2),
nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, padding=2),
nn.MaxPool2d(2),
nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, padding=2),
nn.MaxPool2d(2),
nn.Flatten(),
nn.Linear(1024, 64),
nn.Linear(64, 10),
)
def forward(self, x):
# 法1
# x = self.struct1(x)
# x = self.struct2(x)
# 法2
for conv in self.struct1:
x = conv(x)
for conv in self.struct2:
x = conv(x)
# 同一循环下同步执行
for conv1, conv2 in zip(self.struct1, self.struct2):
x1 = conv1(x)
x2 = conv2(x)
x = x1 + x2
return x
# 另一种使用方式
test_seq = nn.Sequential() # 定义空Sequential
test_seq.add_module('in_channel', nn.Conv2d(3, 64, kernel_size=1, stride=1)) # 添加卷积层至最后
test_seq.insert(1, nn.Conv2d(64, 64, kernel_size=1, stride=1)) # 添加卷积层至第1层(从0开始,后面的层相应后移)
test_seq.add_module('out_channel', nn.Conv2d(64, 3, kernel_size=1, stride=1)) # 添加卷积层至最后
print(test_seq) # 打印Sequential中包含的内容
test_seq.__delitem__(0) # 删除第0层(从0开始,后面的层前移)
print(test_seq)
# 在这里module.insert()有个bug,index的值不能为0,否则无法添加层,或是会导致直接退出
# 测试环境PyCharm2023,根据源码怀疑是str(0)导致程序直接退出运行
nn.Linear
全连接层
torch.nn.Linear(
in_feature, # 输入特征数(不是通道,h*w*c)
out_feature, # 输出特征数(不是通道)
bias=None, # 是否要添加偏置
scale=None, # 输出大小,如果为None, 源自输入大小?(基本没用)
zero_point=None # 输出0点,如果为None, 源自输入0点?(基本没用)
)