首页人工智能Pytorch【深度学习(PyTorch...

【深度学习(PyTorch篇)】38.nn.functional

本系列文章配套代码获取有以下两种途径:

  • 通过百度网盘获取:
链接:https://pan.baidu.com/s/1XuxKa9_G00NznvSK0cr5qw?pwd=mnsj 提取码:mnsj
  • 前往GitHub获取
https://github.com/returu/PyTorch





Pytorch中包括一个很常用的模块torch.nn.functional,提供了许多用于构建神经网络的函数。nn.Module中的大多数Layernn.functional中都有一个与之对应的函数。

nn.Module是一个基类使用nn.Module实现的Layer是一个特殊的类,由class layer(nn.Module)定义,会自动追踪和管理网络中的参数(如权重和偏置),以及提供训练/评估模式切换的方法。

nn.functional中的函数更加基础和灵活,由def function(input)定义,它们不保存任何状态,而是接受输入张量并返回输出张量,因此它们可以被看作是“纯函数”。

01

nn.functional


torch.nn.functional提供了许多神经网络中常用的函数,这些函数可以在不创建类实例的情况下直接使用。以下是一些 torch.nn.functional 中包含的主要函数类别和示例:
  • 激活函数:

  • relu(input, inplace=False): ReLU (Rectified Linear Unit) 激活函数。
  • sigmoid(input): Sigmoid 激活函数。
  • tanh(input): 双曲正切激活函数。
  • softmax(input,dim=None,_stacklevel=3,dtype=None):Softmax激活函数。
  • log_softmax(input,dim=None,_stacklevel=3,dtype=None):Log-Softmax激活函数。

  • 卷积函数:

conv2d(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1): 二维卷积。
  • 池化函数:

  • max_pool2d(input, kernel_size, stride=None, padding=0, dilation=1, ceil_mode=False, return_indices=False): 二维最大池化。
  • avg_pool2d(input, kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True): 二维平均池化。

  • 正则化函数:

  • batch_norm(input, running_mean, running_var, weight=None, bias=None, training=False, momentum=0.1, eps=1e-05): 批量归一化。
  • normalize(input, p=2, dim=1, eps=1e-12): 对输入张量进行归一化。

  • 损失函数:

  • cross_entropy(input, target, weight=None, size_average=None, ignore_index=-100, reduce=None, reduction=’mean’): 交叉熵损失。
  • mse_loss(input, target, size_average=None, reduce=None, reduction=’mean’): 均方误差损失。
  • margin_ranking_loss(input1, input2, target, margin=0, size_average=None, reduce=None, reduction=’mean’): 排序损失。

  • 其他实用函数:
  • pad(input, pad, mode=’constant’, value=0): 对输入进行填充。
  • dropout(input, p=0.5, train=False, inplace=False): 应用 dropout

上述只是 torch.nn.functional 中可用函数的一个子集。PyTorch 官方文档提供了完整的函数列表和详细说明,建议查阅以获取更多信息。
02

nn.Module和nn.functional对比


下面分别使用nn.Modulenn.functional来执行卷积操作,并验证了两种方法得到的结果是否一致。
  • 使用nn.Module创建卷积层并执行卷积操作:

data = torch.randn(1, 1, 200, 200)

# 使用nn.Module创建一个卷积层
# 这里使用5x5的卷积核,输入通道为1,输出通道为3,其他参数使用默认值
conv = nn.Conv2d(1,3,(5,5))
# 权重张量和偏置张量的大小
conv.weight.shape , conv.bias.shape
# 对图像张量进行卷积操作 
out_module = conv(data)
# 输出卷积后的结果形状  
print("Output shape:", out_module.shape)
# Output shape: torch.Size([1, 3, 196, 196])
  • 使用nn.functional执行卷积操作:

首先了解下torch.nn.functional.conv2d() 函数中各参数的含义:
torch.nn.functional.conv2d(input, 
                           weight,
                           bias=None
                           stride=1
                           padding=0
                           dilation=1
                           groups=1)

其中:

  • input:输入张量,形状为 (batch, channels, height, width)
  • weight:卷积核张量,形状为 (out_channels, in_channels/groups, height, width)
  • bias(可选):偏置张量,形状为 (out_channels,)。如果没有提供,则假设偏置为零。
  • stride(可选):卷积的步长,可以是一个数字或一个二元组 (stride_height, stride_width)。默认值为 1。
  • padding(可选):输入数据边缘的零填充数量,可以是一个数字或一个二元组 (padding_height, padding_width)。默认值为 0。
  • dilation(可选):卷积核元素之间的空间距离,可以是一个数字或一个二元组 (dilation_height, dilation_width)。默认值为 1。
  • groups(可选):控制输入和输出之间的连接。默认值为 1,表示所有输入通道都与每个输出通道相连。如果 groupsin_channels,则每个输入通道仅与一个输出通道相连。
要使用 torch.nn.functional.conv2d(),需要手动定义 weightbias并传递给函数。这不同于使用 torch.nn.Conv2d 层,后者会在创建层时自动初始化权重和偏置,并在训练过程中更新它们。
# 使用nn.functional创建一个卷积层
import torch.nn.functional as F
# 为了保持参数一致,使用第一个卷积层的权重和偏置张量值
weight = conv.weight # 随机初始化权重值torch.randn(3, 1, 5, 5)  
bias = conv.bias # 随机初始化偏置值torch.randn(3)
# 使用 conv2d 函数进行卷积操作  
output_functional = F.conv2d(data, weight,bias) 
# 输出卷积后的结果形状  
print("Output shape:", output_functional.shape)
# Output shape: torch.Size([1, 3, 196, 196])
  • 结果比较:

最后,比较使用nn.Modulenn.functional两种方法得到的卷积结果是否相同:
# 查看两者是否相同:
out_module.equal(output_functional)
# True
从输出结果可以看出,由于两种方法都使用了相同的权重和偏置,并且其他卷积参数(如步长、填充等)都使用了默认值,因此它们得到的结果是相同的。
03

搭配使用nn.Module和nn.functional创建网络


搭配使用nn.Modulenn.functional来创建神经网络模型,在两者的选择上有以下注意事项:
如果模型中有可学习的参数,最好使用nn.Module,否则两者均可使用。例如,卷积层、全连接层等具有可学习参数的层使用nn.Module;激活函数、池化层等没有可学习参数的层两者均可使用。
对于Dropout层,虽说该参数没有可学习参数,但是仍建议使用nn.Module,这是因为dropout操作在训练阶段和测试阶段的行为有所差异,使用nn.Module可以通过model.eval()操作加以区分。
下面举例说明如何在网络搭建中搭配使用nn.Modulenn.functional
对于激活函数、池化层,使用nn.functional,这样就可以不同将其放置在构造函数__init__()中。
class Net(nn.Module):
    # 初始化函数
    def __init__(self):
        # 调用父类的初始化函数
        super().__init__()
        # 定义第一个卷积层,输入通道数为3,输出通道数为6,卷积核大小为5x5
        self.conv1 = nn.Conv2d(3,6,5)
        # 定义第二个卷积层,输入通道数为6,输出通道数为16,卷积核大小为5x5
        self.conv2 = nn.Conv2d(6,16,5)
        # 定义第一个全连接层,输入特征数为16*5*5,输出特征数为100
        self.fc1 = nn.Linear(16*3*3,100)
        # 定义第二个全连接层,输入特征数为100,输出特征数为50 
        self.fc2 = nn.Linear(100,50)
        # 定义第三层,输入特征数为50,输出特征数为10
        self.fc3 = nn.Linear(50,10)

    # 前向传播函数
    def forward(self,x):
        # 通过第一个卷积层,然后应用ReLU激活函数和最大池化层,池化核大小为2
        x = F.max_pool2d(F.relu(self.conv1(x)) , 2)
        # 通过第二个卷积层,然后应用ReLU激活函数和最大池化层,池化核大小为2
        x = F.max_pool2d(F.relu(self.conv2(x)) , 2)
        # 将特征图展平,以便输入到全连接层中
        x = x.view(-1,16*3*3)
        # 通过第一个全连接层,并应用ReLU激活函数
        x = F.relu(self.fc1(x))
        # 通过第二个全连接层,并应用ReLU激活函数
        x = F.relu(self.fc2(x))
        # 通过第三个全连接层,得到最终的输出
        x = self.fc3(x)

        return x

# 生成一个形状为 (1, 3, 24, 24) 的随机张量  
# 1张图像,每张图像有3个颜色通道,图像大小为24x24像素
data = torch.randn(132424)

# 实例化神经网络模型
net = Net()

# 使用前向传播,计算模型的输出
net(data)


更多内容可以前往官网查看

https://pytorch.org/


本篇文章来源于微信公众号: 码农设计师

RELATED ARTICLES

欢迎留下您的宝贵建议

Please enter your comment!
Please enter your name here

- Advertisment -

Most Popular

Recent Comments