激活函数 05 ——Swish

Swish背景


发展阶段典型函数主要特性局限性
早期阶段Sigmoid/Tanh平滑可导,输出有界梯度消失问题
现代阶段ReLU计算高效,缓解梯度消失神经元死亡现象
改进阶段LeakyReLU改善负区间响应参数敏感性
新星阶段Swish/GELU自适应非线性计算复杂度略高

Swish激活函数由Google Brain团队在2017年首次提出,论文:PDF

Swish ( x ) = x ⋅ σ ( β x ) \text{Swish}(x) = x \cdot \sigma(\beta x) \quad Swish(x)=xσ(βx)
其中  σ ( z ) = 1 1 + e − z \text{其中} \ \sigma(z) = \frac{1}{1+e^{-z}} 其中 σ(z)=1+ez1

原始版本中 β=1,后续研究发现可训练参数β能获得更好效果。该函数结合了ReLU的线性响应特性和Sigmoid的平滑特性。建议从固定 β=1 开始,当模型参数量>1M时考虑可训练参数版本。

函数形态

令β=1时的函数形态:

  • 正区间 lim ⁡ x → + ∞ Swish ( x ) = x \lim_{x→+\infty}\text{Swish}(x)=x limx+Swish(x)=x(与ReLU渐近一致)
  • 负区间 lim ⁡ x → − ∞ Swish ( x ) = 0 \lim_{x→-∞}\text{Swish}(x)=0 limxSwish(x)=0(保留有限梯度)
  • 原点特性 Swish ( 0 ) = 0 ⋅ σ ( 0 ) = 0 \text {Swish}(0) = 0·σ(0) = 0 Swish(0)=0σ(0)=0
  • 非单调性:在 x ∈ ( − 1.278 , 0 ) x∈(-1.278, 0) x(1.278,0) 区间呈现局部极小值

在这里插入图片描述

d d x Swish ( x ) = σ ( x ) + x ⋅ σ ( x ) ( 1 − σ ( x ) ) = σ ( x ) ( 1 + x − x σ ( x ) ) = Swish ( x ) + σ ( x ) ( 1 − Swish ( x ) ) \begin{aligned} \frac{d}{dx}\text{Swish}(x) &= \sigma(x) + x \cdot \sigma(x)(1-\sigma(x)) \\ &= \sigma(x)(1 + x - x\sigma(x)) \\ &= \text{Swish}(x) + \sigma(x)(1 - \text{Swish}(x)) \end{aligned} dxdSwish(x)=σ(x)+xσ(x)(1σ(x))=σ(x)(1+xxσ(x))=Swish(x)+σ(x)(1Swish(x))

导数特性:最大梯度值约为1.099,出现在x≈1.0处;负区间保持非零梯度(解决ReLU死亡问题);梯度曲线二阶可导,有利于高阶优化方法

参数化Swish变体

后续研究提出可训练参数版本:

Swish β ( x ) = x ⋅ σ ( β x ) \text{Swish}_β(x) = x \cdot \sigma(\beta x) Swishβ(x)=xσ(βx)

通过反向传播自动学习β参数,实验显示在图像分类任务中β常收敛到区间 [ 1.0 , 1.5 ] [1.0,1.5] [1.0,1.5]

适合场景

深层网络:尤其适合50层以上的深度架构
低初始化场景:对参数初始化敏感性低于ReLU
长期训练:在超过100epoch的训练中优势更明显

计算开销:相比ReLU增加约15%的计算量
硬件优化:需要开启自动混合精度训练(AMP)
初始化策略:建议配合He正态初始化

Pytorch实现

import torch
import torch.nn as nn

class Swish(nn.Module):
    def forward(self, x):
        return x * torch.sigmoid(x)

自动求导特性实现内存高效

class MemoryEfficientSwish(nn.Module):
    class F(torch.autograd.Function):
        @staticmethod
        def forward(ctx, x):
            ctx.save_for_backward(x)
            return x * torch.sigmoid(x)

        @staticmethod
        def backward(ctx, grad_output):
            x = ctx.saved_tensors[0]
            sigmoid_x = torch.sigmoid(x)
            return grad_output * (sigmoid_x * (1 + x * (1 - sigmoid_x)))

    def forward(self, x):
        return self.F.apply(x)

参数化

class ParametricSwish(nn.Module):
    def __init__(self, beta=1.0, trainable=True):
        super().__init__()
        self.beta = nn.Parameter(torch.tensor(beta), requires_grad=trainable)
        
    def forward(self, x):
        return x * torch.sigmoid(self.beta * x)
### 关于EfficientNet-B0中的Swish激活函数 在神经网络设计中,激活函数扮演着至关重要的角色。对于EfficientNet系列模型而言,引入了一种新型激活函数——Swish[^1]。 #### Swish激活函数定义 Swish是一种自门控激活函数,表达式如下: \[ f(x) = x \cdot \sigma(\beta x) \] 其中 \( \sigma() \) 表示Sigmoid函数,\( \beta \) 是可选参数,在实际应用中通常设置为常数1或者通过学习获得。当 \( \beta=1 \) 时,可以简化表示为: ```python import torch.nn.functional as F def swish(x): return x * F.sigmoid(x) ``` 这种形式使得Swish既保留了ReLU的优点又克服了一些缺点,比如解决了梯度消失问题并允许负输入传递信息[^2]。 #### 应用于EfficientNet-B0的优势 相比于传统的ReLU和其他变体,Swish具有更好的表现力和平滑特性,有助于提升深层网络的学习能力。具体来说,在EfficientNet-B0架构下采用Swish能够带来更优的收敛速度和更高的精度,尤其是在资源受限的情况下也能保持良好的性能[^3]。 #### 实现细节 在实现层面,PyTorch等框架提供了便捷的方式去集成Swish作为默认激活单元之一。这不仅提高了编程效率也促进了不同组件间的兼容性。 ```python class MBConvBlock(nn.Module): def __init__(self, ...): super(MBConvBlock, self).__init__() ... self.act_fn = nn.SiLU(inplace=True) # SiLU即为Swish的一种实现方式 def forward(self, inputs): ... outputs = self.act_fn(x) ... ``` 上述代码片段展示了如何在一个典型的MBConv(Mobile Inverted Bottleneck Convolutional Block)内部配置Swish激活函数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Echo-Nie

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值