前言: 小毕总结了四个常用的激活函数 相信大家肯定都知道 也用烂了都 , 那就再帮大家复习一下吧! 我也借着写文章这个机会 回忆回忆 几个常用的激活函数 嘻嘻
简易网络结构 :
SoftMax 激活函数
概念: SoftMax 一般运用在 多分类需求的 输出层上
举例 : 你输入的是一张图片的数字9 你想让模型预测到 这张图里显示的是9 那么你在设置网络结构的时候 输出层 就会有10个的logits(原始值) 的输出 因为logits是加权和的原始值 , 你需要用SoftMax激活函数 把logits原始值 变成概率值 这样 你选取10个概率值为最大的即可 就能获得到你想要的数字9
SoftMax激活函数公式 :
SoftMax( z i ) 中的 zi 代表输出层的其中一个类别的 加权和
分子 : 本次计算类别的 加权和
分母: 所有类别的 加权和
公式对全部类别进行SoftMax计算 就会得到每个类别的 概率值啦 而且这些类别的概率值加到一起是 等于 1 的 最后您选择做大的概率值即可
代码:
# 输入层 ----> 隐藏层 ----> 输出层
# 1. 将原始数据送入输入层 --> 例如是 一串描述
# 2. 在隐藏层进行加权和计算 --> 例如是 0.2,0.02,0.15,0.15,1.3,0.5,0.06,1.1,0.05,3.75
# 3. 在输出层输出 各个类别的原始值(logits)结果
logits = torch.tensor([0.2,0.02,0.15,0.15,1.3,0.5,0.06,1.1,0.05,3.75])
# 4. 对输出的 logits 原始值 进行 softmax激活 转化为概率值
softmax_logits = torch.softmax(logits,dim=0)
# 5. 得到全部概率值
print(softmax_logits)
# 6. 取最大值
print(softmax_logits.argmax())
# 得到的结果
tensor([0.0212, 0.0177, 0.0202, 0.0202, 0.0638, 0.0287, 0.0185, 0.0522, 0.0183,0.7392])
# 通过 argmax方法 寻找最大概率值 的结果
tensor(0.7392)
ReLu 激活函数
俗话说 无路可走选 ReLu 即使有路可走也要先试试 ReLu , 总之 遇到事情不要慌 选 ReLu 就完事了 !
概念 : ReLu 激活函数 是人工智能大牛''何凯明'' 提出 并广泛运用 常常也在隐藏层中使用
ReLu的优缺点
优点:
不管是在计算机中计算 还是 人工求导 都及其简便 只有 0 和 1两个选择 加权和 > 0 导数就是1 , 加权和 < 0 就是0 ! 没了! 就是这么简单方便!!
ReLu没有梯度消失 梯度爆炸 , 因为 要么是 0 要么是 1
加权和为负数时 ReLu激活函数求导会为0 导致一部分神经元死亡 , 虽然听上去是坏事 但也不然 小部分神经元死亡 也会防止我们的模型过拟合 , 并且也会简化我们的网络结构,减小网络复杂度 ,从这种角度上来看其实也算是优点啦
缺点:
如果过多的加权和为负数 会导致 神经元大面积死亡 导致模型毫无作用 , 不过这种也不算常见 大部分情况下 ReLu不会发生 因为一般我们在训练模型的时候 batch_size 都设置为随机 很难发生那种 得多幸运 才会大面积的加权和都为负数 导致大面积神经元死亡 , 不过在 yolo中也会出现 我们就使用 LeakyReLu 或者 PReLu 等等 ReLu的进化版 来解决此情况即可
ReLu公式 :
x 依然代表 加权和
Max 代表 加权和如果 > 0 导数就是 1 , 加权和如果 < 0 导数就是 0 , 每次比较是 你的X加权和 和 0 做比较 谁大用谁
函数图像 导数图像
大家也可以自己生成一下图像看看呀
# 激活函数图像 (relu 举例)
import torch
import matplotlib.pyplot as pl # 画图工具
x = torch.linspace(-20,20,10000) # 取值范围 -20~20 并随机生成10000个点
y = torch.relu(x) # 效果和用公式一样
pl.plot(x,y)
pl.grid() # 给图像增加网格
pl.show() # 查看图像
# 激活函数导数图像 (relu 举例)
import torch
import matplotlib.pyplot as pl # 画图工具
# 取值范围 -20~20 并随机生成10000个点 并且设置为可'求导'
x = torch.linspace(-20,20,1000 , requires_grad= True)
# 因为在进行 反向传播(自动微分)之前,x的值必须为常数向量,所以这里需要将Tensor用sum()求成常数向量 才能进行反向传播
torch.relu(x).sum().backward()
# 拿 relu 举例 : 如若要进行绘制图像:
# 此时网络中是由无数个wb和relu激活函数组成的relu此时还都在计算图上 需要用 detach() 方法将他们从计算图中剥离出来
pl.plot(x.detach(),x.grad)
pl.grid() # 给图像增加网格Î
pl.show() # 查看图像
Sigmoid 激活函数
俗话说 遇到事情不要慌 先选择.... 我实在想不出来词了 哈哈哈哈哈哈
Sigmoid介绍 : Sigmoid常常在 二分类的 输出层使用 因为他的函数范围在 0 - 1 正好可以用来作为, 是或者否的 概率事情 , Sigmoid激活函数的最大导数是 0.25 所以他很不适合做 反向传播 因为会导致越传播 越更新参数越小 不超过六层 基本就会出现梯度消失 所以这个 Sigmoid激活函数 还是尽量用在 输出层中使用较为合适滴
公式:
这里的 f(x) 中的x 表示 每个神经元的 (加权和) 我们是对加权和进行 激活函数
图像:
函数图像 导数图像
我们在 Sigmoid 函数图像中可以看到 他在 0 附近的梯度较大 当超过 -6 到 6 时 会出现梯度消失 而且他的值域只有 0-1之间 较小 而且不对称 , 他的导数图像 最大导数只有 0.25而已 如果用来做隐藏层的激活函数 梯度会更新的很慢 而且非常容易传播传播着就 梯度消失了 , 虽然也可以在加权和的过程中 把导数控制在 0-1之间 但返现传播的时候 是从深层传播到浅层 , 这个过程中sigmoid导数的最大梯度为0.25 , 如果超过了5层依然会导致梯度消失 所以依然不能构建很深层次的网络 所以不建议使用 sigmoid做隐藏层的使用 如此看来 , 根据他 0 -1 的值域范围 还是比较适合用来做 二分类的激活函数较为合适!
Sigmoid 激活函数图像生成代码:
# 激活函数图像 (sigmoid 举例)
import torch
import matplotlib.pyplot as pl # 画图工具
x = torch.linspace(-20,20,10000) # 取值范围 -20~20 并随机生成10000个点
y = torch.sigmoid(x) # 效果和用公式一样
pl.plot(x,y)
pl.grid() # 给图像增加网格
pl.show() # 查看图像
# 激活函数导数图像 (relu 举例)
import torch
import matplotlib.pyplot as pl # 画图工具
# 取值范围 -20~20 并随机生成10000个点 并且设置为可'求导'
x = torch.linspace(-20,20,1000 , requires_grad= True)
# 因为在进行 反向传播(自动微分)之前,x的值必须为常数向量,所以这里需要将Tensor用sum()求成常数向量 才能进行反向传播
torch.sigmoid(x).sum().backward()
# 拿 relu 举例 : 如若要进行绘制图像:
# 此时网络中是由无数个wb和relu激活函数组成的relu此时还都在计算图上 需要用 detach() 方法将他们从计算图中剥离出来
pl.plot(x.detach(),x.grad)
pl.grid() # 给图像增加网格Î
pl.show() # 查看图像
Tanh 激活函数
小毕认为 Tanh 激活函数 是对 Sigmoid进行优化得来的 他可以运用到 二分类的 隐藏层中
Tanh介绍: 根据他的函数图像我们可以看到 他是一条很优美的 对称的曲线 以0为轴 值域是 -1 到 1 之间 而且最大导数可以到1
公式:
图像:
函数图像 导数图像
解释: Tanh 是 Sigmoid 的优化版 Sigmoid不能运用在 隐藏层因为导数太小 容易梯度消失 但Tanh可以 因为他的导数较大 而且相对于Sigmoid来讲 Tanh的梯度更陡峭 能更加快速的进行梯度下降 , 也就意味着能节省更多的训练时间 不过 他的导数 在 -3 到 3之后 依然会发生梯度消失,
Tanh 梯度最大值为 1 与 sigmoid 相比 不容易出现梯度消失(sigmoid每次往前传播的时候都会乘0.25 值会越来越小 很容易出现梯度消失) 可以缓解梯度消失的问题 , 也可以做 标准正态分布 来缓解梯度消失问题 , 但是不会根除梯度消失的问题 我们可以 把要送入Tanh激活函数的 加权和 进行一些处理 让他不要落在 -3 --3 之外的地方 来保证不会出现 梯度消失 , 并且 相对于 sigmoid 在 -3 -- 3 之间 Tanh的梯度更陡峭 梯度下降的时候更新的会更快(收敛的快) 训练轮次也会减少(训练时间短)
Tanh 激活函数图像生成代码:
# 激活函数图像 (tanh 举例)
import torch
import matplotlib.pyplot as pl # 画图工具
x = torch.linspace(-20,20,10000) # 取值范围 -20~20 并随机生成10000个点
y = torch.tanh(x) # 效果和用公式一样
pl.plot(x,y)
pl.grid() # 给图像增加网格
pl.show() # 查看图像
# 激活函数导数图像 (relu 举例)
import torch
import matplotlib.pyplot as pl # 画图工具
# 取值范围 -20~20 并随机生成10000个点 并且设置为可'求导'
x = torch.linspace(-20,20,1000 , requires_grad= True)
# 因为在进行 反向传播(自动微分)之前,x的值必须为常数向量,所以这里需要将Tensor用sum()求成常数向量 才能进行反向传播
torch.tanh(x).sum().backward()
# 拿 relu 举例 : 如若要进行绘制图像:
# 此时网络中是由无数个wb和relu激活函数组成的relu此时还都在计算图上 需要用 detach() 方法将他们从计算图中剥离出来
pl.plot(x.detach(),x.grad)
pl.grid() # 给图像增加网格Î
pl.show() # 查看图像
小毕是Ai初学者 说的肯定都比较浅显 大家将就看 有什么不对的地方 还请大家多指教呀 小毕很愿意虚心学习! 嘻嘻
--- 小毕祝您一切顺利 一直幸福
2024-11-16
毕航聚