目录
1、自定义损失函数
前言:
首先,回顾一下上一次的核心内容:使用nn.Mudule来自定义激活函数,以及为激活函数设置可进行训练的参数,也就是参数化的激活函数
-
在深度学习框架PyTorch中已经内置了很多激活函数,如ReLU等
-
但是有时根据个人需要,需要自定义激活函数,甚至需要为激活函数添加可学习的参数,如PReLU,具体参见PyTorch官方github激活函数源码实现。
-
对于不需要可学习参数的激活函数的实现,比较简单,具体见PyTorch官网教程的一个例子
之前已经说过了pytorch自定义神经网络模型、自定义神经网络层、自定义激活函数,整个神经网络正向传播的搭建过程已经逐渐完整了
,下面再说一说反向传播和训练的过程。
这次主要内容:
-
nn.Module 和 nn.Functional 区别和联系
-
自定义损失函数
import warnings
from typing import Tuple, Optional
import torch
from torch import Tensor
from .linear import _LinearWithBias
from torch.nn.init import xavier_uniform_
from torch.nn.init import constant_
from torch.nn.init import xavier_normal_
from torch.nn.parameter import Parameter
from .module import Module
from .. import functional as F
-
在深度学习框架PyTorch中已经内置了很多激活函数,如ReLU等
-
但是有时根据个人需要,需要自定义激活函数,甚至需要为激活函数添加可学习的参数,如PReLU,具体参见PyTorch官方github激活函数源码实现。
-
对于不需要可学习参数的激活函数的实现,比较简单,具体见PyTorch官网教程的一个例子
1.1 nn.Module和nn.Functional的区别与联系
主要参考资料为:
1.1.1 二者的相似之处
-
nn.Xxx和nn.functional.xxx的实际功能是相同的
,即nn.Conv2d和nn.functional.conv2d 都是进行卷积,nn.Dropout 和nn.functional.dropout都是进行dropout,等等; -
运行效率也是近乎相同
但是,在不涉及可学习的参数情况下,推荐使用nn.Xxx,因为:
-
nn.functional.xxx只是函数接口,只涉及一些运算操作,但无法保留参数的信息
-
nn.Xxx是nn.functional.xxx的类封装,并且nn.Xxx都继承于一个共同祖先nn.Module
-
nn.Xxx除了具有nn.functional.xxx功能之外,内部附带了nn.Module相关的属性和方法,例如train(), eval(),load_state_dict, state_dict等
1.1.2 二者的差别之处
1.1.2.1 调用方式
nn.Xxx
需要先实例化并传入参数,然后以函数调用的方式调用实例化的对象并传入输入数据
inputs = torch.rand(64, 3, 244, 244)
conv = nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3, padding=1)
out = conv(inputs)
`nn.functional.xxx`
- 需要同时传入输入数据和weight, bias等其他参数
1.1.2.2 与nn.Sequential的结合运用
-
nn.Xxx继承于nn.Module, 能够很好的与nn.Sequential结合使用,
-
nn.functional.xxx无法与nn.Sequential结合使用
fm_layer = nn.Sequential(
nn.Conv2d(3, 64, kernel_size=3, padding=1),
nn.BatchNorm2d(num_features=64),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2),
nn.Dropout(0.2)
)
1.1.2.3 参数的管理
-
nn.Xxx不需要你自己定义和管理weight;
-
nn.functional.xxx需要你自己定义weight,每次调用的时候都需要手动传入weight, 不利于代码复用
(1)使用nn.Xxx定义一个CNN
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.cnn1 = nn.Conv2d(in_channels=1, out_channels=16, kernel_size=5,padding=0)
self.relu1 = nn.ReLU()
self.maxpool1 = nn.MaxPool2d(kernel_size=2)
self.cnn2 = nn.Conv2d(in_channels=16, out_channels=32, kernel_size=5, padding=