Pytorch学习记录(7)非线性激活的使用
非线性激活函数的意义:
激活函数(Activation Function)是在神经网络中负责将神经元的输入映射到输出端的函数。激活函数将非线性特性引入到神经网络中。如下图所示,在神经元中,输入的 inputs 通过加权,求和后,还被作用了一个函数,这个函数就是激活函数。引入激活函数是为了增加神经网络模型的非线性。没有激活函数的每层都相当于矩阵相乘。就算你叠加了若干层之后,无非还是个矩阵相乘罢了。
![](https://i-blog.csdnimg.cn/blog_migrate/371dbac8a45ec26441d8b830483aeb66.png)
引入非线性函数作为激活函数之后,深层神经网络才有意义,可以逼近任意函数。
激活函数通常具备下述特征:非线性、可微性、单调性、f ( x ) ≈ x f(x)\approx xf(x)≈x、输出值有范围、计算简单、归一化。
常见的4种非线性激活函数:
对于常见的非线性激活函数的具体参数,详见:torch.nn — PyTorch 1.13 documentation
以下举例出4种常见的非线性激活函数进行介绍:
2.1 sigmoid函数:
Sigmoid函数是传统的神经网络和深度学习领域开始时使用频率最高的激活函数。
其优点主要是连续,平滑便于求导。
但是其的缺点也很致命:
梯度消失问题(Vanishing Gradient problem):观看图像可知当x>2或x<2时Sigmod输出趋于平滑,导致梯度减小,权重和偏置更新过慢导致网络不更新。
非零均值特性(none-zero-centered):会使训练震荡达不到最优解,使收敛变慢。
导数计算复杂,影响速度。
![](https://i-blog.csdnimg.cn/blog_migrate/0dc85b1a43dfa3456cacfb4ec18d129d.png)
2.2 Tanh函数:
Tanh主要解决了Sigmod非零均值特性的问题,但是其还是存在计算复杂和梯度消失的问题。
![](https://i-blog.csdnimg.cn/blog_migrate/d34b71e2d250d5fd72b7bb432b9dde71.png)
2.3 ReLu函数:
ReLU函数是目前神经网络中使用最多的激活函数,ReLU函数的线性特点使得其收敛速度比Sigmoid函数和tanh函数都要快,并且不会出现梯度饱和的情况,计算效率更高。
![](https://i-blog.csdnimg.cn/blog_migrate/1f778e7301f88117dc65d6f8d8a998d4.png)
Relu的主要优点有:
大于0时,其导数恒为1,不会存在梯度消失的问题
计算速度非常快,只需要判断 x 是大于0还是小于0
收敛速度远远快于前面的 Sigmoid 和 Tanh函数
但是ReLu也是有着缺陷的:
非零均值特性
所有负值均被截断为结果0,从而导致特征丢失的情形。同时,ReLU函数要求学习率不能太高,如果学习率太大,会使网络中很多的神经元都失效,一般设置一个较小的学习率,为0.005。
2.4 Leaky ReLU函数:
为了解决ReLU函数中的负值被截断为0的问题,推出带泄露修正的线性单元Leaky ReLU函数:
![](https://i-blog.csdnimg.cn/blog_migrate/133f25ce704e755d14385cf15a2f73b3.png)
![](https://i-blog.csdnimg.cn/blog_migrate/208b912f48c3f7b07de83ecc409eaf16.png)
Leaky ReLU函树是给出一个负数梯度值,在x<=0的情况,f(x) = ax,其中a是一个较小的值,通常为0.01。虽然同时 Leaky ReLU函数具有 ReLU 的所有优点。但是在实际操作中并没有完全证明好于 ReLU 函数。
使用ReLu函数处理矩阵:
用ReLU函数对矩阵执行非线性操作代码如下
import torch
from torch import nn
from torch.nn import ReLU
input = torch.tensor([[1, -0.5],
[-1, 3]])
input = torch.reshape(input, (-1, 1, 2, 2))
print(input.shape)
class Model(nn.Module):
def __init__(self):
super(Model, self).__init__()
self.relu1 = ReLU()
def forward(self, input):
output = self.relu1(input)
return output
model = Model()
output = model(input)
print(output)
上述代码中处理了2×2的矩阵,原始矩阵为:[[1, -0.5],[-1, 3]],得到的输出结果为:
![](https://i-blog.csdnimg.cn/blog_migrate/49dc9af63bcd5e71a70d59eecd8f78f2.png)
使用sigmoid函数处理图像:
用sigmoid函数对图像执行非线性操作代码如下:
import torch
import torchvision
from torch import nn
from torch.nn import ReLU, Sigmoid
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
dataset = torchvision.datasets.CIFAR10("./data", train=False, download=True,
transform=torchvision.transforms.ToTensor())
dataloader = DataLoader(dataset, batch_size=64)
class Model(nn.Module):
def __init__(self):
super(Model, self).__init__()
self.sigmoid1 = Sigmoid()
def forward(self, input):
output = self.sigmoid1(input)
return output
model = Model()
writer = SummaryWriter("logs")
step = 0
for data in dataloader:
imgs, targets = data
writer.add_images("input", imgs, global_step=step)
output = model(imgs)
writer.add_images("output", output, step)
step = step + 1
writer.close()
得到的结果通过tensorboard进行查看:
![](https://i-blog.csdnimg.cn/blog_migrate/228b5557a033346b203cca51ba1ef174.png)
![](https://i-blog.csdnimg.cn/blog_migrate/9eb706b780aa3b12be11a7a7bb9bea99.png)
通过对比非线性操作前后的图像,发现经过非线性激活函数处理之后的图像中的主要内容更突出了。
ReLU函数处理自然语言效果更佳,Sigmoid函数处理图像效果更佳。
总结:
在本文中总结了神经网络的非线性激活函数的基本使用方法,并通过构建一个类Test分别介绍了ReLU()函数和Sigmoid()函数的使用方法。