nn.Module

nn.Module 是 PyTorch 中所有神经网络模块的基类,包括各种层(如卷积层、全连接层等)以及用户自定义的模型。它提供了神经网络构建所需的基本功能,并允许用户通过继承 nn.Module 类来定义自己的网络结构。

构建基本模型

为了构建基本模型,我们先导入 nn.Module 类并继承它:

from torch.nn import Module

class Mymodel(Module):
    
    def __init__(self):
        super().__init__()

    def forward(self, input):
        return input + 1

其中前向传播(forward方法)是一个你需要实现的方法,描述了输入数据经过该模块时会发生什么。

我们可以尝试调用它:

import torch

tensor_data = torch.tensor(1.0) # 初始化张量
output = Mymodel()(tensor_data) # 调用自定义模型
print(output) # 打印输出

卷积层

在PyTorch中,卷积层通常是指用于实现卷积操作的神经网络层。这些层特别适用于处理图像、视频、语音、自然语言处理中具有空间或时间结构的输入数据。卷积层通过应用卷积滤波器(或称为卷积核)来学习输入数据的局部特征

PyTorch中常用的卷积层包括:

  1. nn.Conv1d:一维卷积层,常用于处理序列数据或一维信号。它的输入是三维张量(batch_size, input_channels, width),输出也是三维张量(batch_size, output_channels, output_width)

  2. nn.Conv2d:二维卷积层,最常用于处理图像数据。它的输入是四维张量(batch_size, input_channels, height, width),输出也是四维张量(batch_size, output_channels, output_height, output_width)。二维卷积层在图像识别、目标检测、语义分割等任务中非常关键。

  3. nn.Conv3d:三维卷积层,用于处理三维数据,如医学图像(如MRI)或三维空间中的体素数据。它的输入是五维张量(batch_size, input_channels, depth, height, width),输出也是五维张量(batch_size, output_channels, output_depth, output_height, output_width)

  4. nn.ConvTranspose1d/2d/3d:转置卷积层,有时也被称为反卷积层(尽管它们并不是真正的反卷积操作)。这些层用于上采样,即从低分辨率特征图生成高分辨率特征图。它们在生成模型(如GANs)和某些分割任务中很有用。

  5. 其他变种:除了上述基本的卷积层外,PyTorch还提供了许多其他类型的卷积层,如空洞卷积(nn.Conv2d中的dilation参数)、分组卷积(groups参数)等。这些变种提供了更多的灵活性,以适应不同的应用场景和需求。

为了实现卷积层,我们先下载现有的datasets,并用DataLoader将它加载进去:

from torchvision import datasets
from torchvision.transforms import ToTensor
from torch.utils.data import DataLoader

datasets = datasets.CIFAR10(root="./CIFAR10", train=False, transform=ToTensor(), download=True)
dataloader = DataLoader(dataset=datasets, batch_size=64)

接下来使用创建神经网络模型,并使用二维卷积层处理图像数据

from torch.nn import Module, Conv2d

class MyModule(Module):

    def __init__(self):
        super().__init__()
        self.conv2d = Conv2d(in_channels=3, out_channels=6, kernel_size=3, stride=1, padding=0)

    def forward(self, input):
        return self.conv2d(input)

上面Conv2d中输入的参数意义如下:

  1. in_channels: 输入通道数。这指的是输入特征图的通道数。例如,对于彩色图像,通道数通常是3(对应红、绿、蓝三个颜色通道)。在你的例子中,in_channels=3表示输入是一个具有3个通道的特征图,可能是一个彩色图像。

  2. out_channels: 输出通道数。这指的是卷积层将会产生的输出特征图的通道数。这通常也是卷积核的数量。在你的例子中,out_channels=6意味着该卷积层有6个不同的卷积核,将会产生6个输出特征图。

  3. kernel_size: 卷积核的大小。这可以是一个整数(对于正方形卷积核)或一个包含两个整数的元组(分别表示卷积核的高度和宽度)。kernel_size=3在你的例子中表示使用一个大小为3x3的卷积核。

  4. stride: 卷积步长。这可以是一个整数(对于垂直和水平方向上的相同步长)或一个包含两个整数的元组(分别表示垂直和水平方向上的步长)。stride=1表示卷积核在特征图上滑动时,每一步移动一个像素。

  5. padding: 填充大小。这可以是一个整数(对于四周相同的填充)或一个包含四个整数的元组(分别表示左、右、上、下的填充)。padding=0表示不对输入特征图进行任何填充。填充通常用于控制输出特征图的空间尺寸,以及避免边界信息过快地丢失。

最后,我们调用dataloader,然后进行训练即可

from torch.utils.tensorboard import SummaryWriter

module = MyModule()
with SummaryWriter("./logs") as su:
    step = 1
    for data in dataloader:
        image, targets = data
        output = module(image)
        print(image.shape)
        print(output.shape)
        su.add_image(tag="input", img_tensor=image, global_step=step)
        su.add_image(tag="output", img_tensor=image, global_step=step)
        step += 1

最大池化

在PyTorch中,最大池化(Max Pooling)是一种下采样(subsampling)技术,常用于卷积神经网络(CNNs)中以减小特征图的尺寸,同时保留最重要的信息。最大池化操作通过在输入特征图的每个局部区域内选择最大值来实现这一点。

PyTorch中的最大池化层可以通过nn.MaxPool2d类来实现,对于二维特征图进行最大池化。nn.MaxPool1dnn.MaxPool3d则分别用于一维和三维数据的最大池化。

from torchvision import datasets
from torchvision.transforms import ToTensor
from torch.utils.data import DataLoader

datasets = datasets.CIFAR10(root="./CIFAR10", train=False, transform=ToTensor(), download=True)
dataloader = DataLoader(dataset=datasets, batch_size=64)

接下来使用创建神经网络模型,并使用最大池化处理图像数据

from torch.nn import Module, MaxPool2d

class MyModule(Module):

    def __init__(self):
        super().__init__()
        self.maxpool2d = MaxPool2d(kernel_size=3, ceil_mode=True)

    def forward(self, input):
        return self.maxpool2d(input)

以下是nn.MaxPool2d的常用参数:

  • kernel_size:最大池化操作的窗口大小。可以是一个整数(表示正方形窗口)或一个包含两个整数的元组(分别表示窗口的高度和宽度)。

  • stride:窗口滑动的步长。可以是一个整数或一个包含两个整数的元组。默认值是kernel_size

  • padding:在特征图周围填充零的层数。可以是一个整数或一个包含四个整数的元组(分别表示左、右、上、下的填充层数)。默认值是0。

  • dilation:控制窗口中元素的间距。默认值是1。

  • return_indices:如果设置为True,则返回最大值的索引,这在某些情况下(如最大反池化)可能很有用。默认值是False

  • ceil_mode:如果设置为True,将使用ceil而不是floor来计算输出形状。默认值是False

最后,我们调用dataloader,然后进行训练即可

from torch.utils.tensorboard import SummaryWriter

module = MyModule()
with SummaryWriter("./logs") as su:
    step = 1
    for data in dataloader:
        image, targets = data
        output = module(image)
        print(image.shape)
        print(output.shape)
        su.add_image(tag="input", img_tensor=image, global_step=step)
        su.add_image(tag="output", img_tensor=image, global_step=step)
        step += 1

非线性激活

在PyTorch中,非线性激活函数是神经网络的重要组成部分,它们为模型提供了非线性特性,使其能够学习并执行复杂的任务。没有非线性激活函数,神经网络只能表示线性变换,这将大大限制其学习和表示能力。

在PyTorch中,常用的非线性激活函数包括以下几种:

  1. ReLU (Rectified Linear Activation)

    • 函数形式:f(x) = max(0, x)

    • PyTorch中的实现:torch.relu()torch.nn.ReLU()

  2. Leaky ReLU

    • 函数形式:f(x) = α * x for x < 0, f(x) = x for x >= 0,其中α是一个小的非零斜率。

    • PyTorch中的实现:torch.nn.LeakyReLU()

  3. Parametric ReLU (PReLU)

    • 函数形式:与Leaky ReLU相似,但允许负输入值的小激活,并且斜率α是可以学习的参数。

    • PyTorch中的实现:torch.nn.PReLU()

  4. Sigmoid

    • 函数形式:f(x) = 1 / (1 + exp(-x))

    • PyTorch中的实现:torch.sigmoid()torch.nn.Sigmoid()

  5. Hyperbolic Tangent (Tanh)

    • 函数形式:f(x) = (exp(x) - exp(-x)) / (exp(x) + exp(-x))

    • PyTorch中的实现:torch.tanh()torch.nn.Tanh()

  6. Softplus

    • 函数形式:f(x) = log(1 + exp(x))

    • PyTorch中的实现:torch.nn.Softplus()

  7. Softsign

    • 函数形式:f(x) = x / (1 + |x|)

    • PyTorch中的实现:torch.nn.Softsign()

  8. Exponential Linear Units (ELU)

    • 函数形式:f(x) = α * (exp(x) - 1) for x < 0, f(x) = x for x >= 0

    • PyTorch中的实现:torch.nn.ELU()

  9. SELU (Scaled Exponential Linear Units)

    • 函数形式:是ELU的一个变体,其中乘上了一个缩放因子,以尝试达到自归一化的效果。

    • PyTorch中的实现:可能需要自定义,因为PyTorch标准库中没有直接提供SELU。

  10. Swish

    • 函数形式:f(x) = x * sigmoid(β * x)

    • PyTorch中的实现:在较新版本的PyTorch中,可以使用torch.nn.Swish()

  11. GELU (Gaussian Error Linear Unit)

    • 函数形式:f(x) = 0.5 * x * (1 + torch.tanh(sqrt(2 / π) * (x + 0.044715 * x^3))),这是一个近似形式,原始GELU涉及高斯分布的积分。

    • PyTorch中的实现:torch.nn.GELU()

  12. SiLU (Sigmoid Linear Unit) 或 Swish-1

    • 函数形式:与Swish相同,f(x) = x * sigmoid(x),有时也被称为Swish的一个特例(当β=1时)。

    • PyTorch中的实现:torch.nn.SiLU()

选择激活函数时,通常会根据特定任务、网络架构和实验效果来进行。不同的激活函数具有不同的特性,如计算复杂性、输出范围、梯度行为等,这些都会影响模型的训练动态和性能。

下面用ReLU示例,

from torchvision import datasets
from torchvision.transforms import ToTensor
from torch.utils.data import DataLoader

datasets = datasets.CIFAR10(root="./CIFAR10", train=False, transform=ToTensor(), download=True)
dataloader = DataLoader(dataset=datasets, batch_size=64)

接下来使用创建神经网络模型,并使用ReLU处理图像数据

from torch.nn import Module, ReLU

class MyModule(Module):

    def __init__(self):
        super().__init__()
        self.relu = ReLU()

    def forward(self, input):
        return self.relu(input)

最后,我们调用dataloader,然后进行训练即可

from torch.utils.tensorboard import SummaryWriter

module = MyModule()
with SummaryWriter("./logs") as su:
    step = 1
    for data in dataloader:
        image, targets = data
        output = module(image)
        print(image.shape)
        print(output.shape)
        su.add_image(tag="input", img_tensor=image, global_step=step)
        su.add_image(tag="output", img_tensor=image, global_step=step)
        step += 1

线性层

在PyTorch中,线性层(Linear Layer)也被称为全连接层(Fully Connected Layer)或仿射变换(Affine Transformation),是一种常用的神经网络层。线性层对输入数据执行线性变换,即输出是输入的加权和加上偏置项。具体来说,线性层通过学习输入数据的线性组合来生成输出。

线性层的数学表达式为:

y = xA^T + b

其中:

  • y 是输出向量;

  • x 是输入向量;

  • A 是权重矩阵;

  • b 是偏置向量;

  • A^T 表示权重矩阵的转置。

在PyTorch中,你可以使用torch.nn.Linear类来创建一个线性层。这个类需要指定输入特征的数量(in_features)和输出特征的数量(out_features),以及是否要学习偏置项(bias,默认为True)。

from torchvision import datasets
from torchvision.transforms import ToTensor
from torch.utils.data import DataLoader

datasets = datasets.CIFAR10(root="./CIFAR10", train=False, transform=ToTensor(), download=True)
dataloader = DataLoader(dataset=datasets, batch_size=64)

接下来使用创建神经网络模型,并使用线性层处理图像数据

from torch.nn import Module, Linear

class MyModule(Module):

    def __init__(self):
        super().__init__()
        self.linear = Linear()

    def forward(self, input):
        return self.linear(input)

最后,我们调用dataloader,然后进行训练即可

from torch.utils.tensorboard import SummaryWriter

module = MyModule()
with SummaryWriter("./logs") as su:
    step = 1
    for data in dataloader:
        image, targets = data
        output = module(image)
        print(image.shape)
        print(output.shape)
        su.add_image(tag="input", img_tensor=image, global_step=step)
        su.add_image(tag="output", img_tensor=image, global_step=step)
        step += 1

nn.Sequential

在深度学习中,模型可以是由各种不同类型的层组成的,例如卷积层、池化层、全连接层等,而 nn.Sequential 提供了将这些层组合在一起的有效方式。

nn.Sequential 是 PyTorch 中的一个有序容器。从功能上讲,这个类将按照传入构造器的顺序,依次创建相应的函数,并记录在 Sequential 类对象的数据结构中。同时,以神经网络模块为元素的有序字典也可以作为传入参数。因此,Sequential 可以看成是由多个函数运算对象串联而成的神经网络,其返回的是 Module 类型的神经网络对象。

在实际应用中,nn.Sequential 允许用户将多个神经网络层组合成一个神经网络模型,并按照顺序逐层进行计算。每个层的输出会作为下一个层的输入,从而形成一个完整的神经网络模型。这种方式非常灵活,因为可以根据具体需求灵活地添加或删除各种层。

模型前向传播时,会调用 forward() 方法,模型接收的输入首先被传入 nn.Sequential 包含的第一个网络模块中,然后按照顺序依次计算并传播,直到 nn.Sequential 里的最后一个模块输出结果。

我们在定义模型时,可以使用Sequential对输入的数据进行连续的处理:

from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential, Module

class MyModel(Module):
    def __init__(self):
        super().__init__()
        self.seq = Sequential(
            Conv2d(3, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 64, 5, padding=2),
            MaxPool2d(2),
            Flatten(),
            Linear(1024, 64),
            Linear(64, 10)
        )

    def forward(self, x):
        x = self.seq(x)
        return x

该模型等价于,可以很明显看到Sequential的便利性:

from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Module

class MyModel(Module):
    def __init__(self):
        super().__init__()
        self.conv2d_1 = Conv2d(3, 32, 5, padding=2),
        self.maxpool2d_1 = MaxPool2d(2),
        self.conv2d_2 = Conv2d(32, 32, 5, padding=2),
        self.maxpool2d_2 = MaxPool2d(2),
        self.conv2d_3 = Conv2d(32, 64, 5, padding=2),
        self.maxpool2d_3 = MaxPool2d(2),
        self.flatten = Flatten(),
        self.linear_1 = Linear(1024, 64),
        self.linear_2 = Linear(64, 10)

    def forward(self, x):
        x = self.conv2d_1(x)
        x = self.maxpool2d_1(x)
        x = self.conv2d_2(x)
        x = self.maxpool2d_2(x)
        x = self.conv2d_3(x)
        x = self.maxpool2d_3(x)
        x = self.flatten(x)
        x = self.linear_1(x)
        x = self.linear_2(x)
        return x

接下来创建模型,然后输入数据

module = MyModel()
print(module)
input = torch.ones((64, 3, 32, 32))
output = module(input)
print(output.shape)

可以将这些数据使用tensorboard查看详细的顺序

from torch.utils.tensorboard import SummaryWriter
writer = SummaryWriter("../logs")
writer.add_graph(module, input)
writer.close()

文章作者: Vsoapmac
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 soap的会员制餐厅
人工智能 人工智能 深度学习
喜欢就支持一下吧