mish算子

156 篇文章 17 订阅
98 篇文章 7 订阅

在看YOLOV4的网络结构的时候遇到了一个之前未曾遇到过的名为MISH的算子,MISH算子在YOLOV4网络中使用非常频繁,值得记录一下。下面引用知乎上的的一段介绍

“相信做过目标检测的同学对 yolo 肯定比较熟悉了,yolov4是 2020 年初提出的,相继后来有了 yolov5 和其他一些变体,yolov4 中汇集了很多 tricks,其中 mish 激活函数也在其中。mish 在这篇论文《Mish: A Self Regularized Non-Monotonic Activation Function》里进行了详细介绍,这里我做了一些函数本身的介绍以及 tensorrt 怎么样去实现 mish 算子”

对激活函数的研究一直没有停止过,ReLU还是统治着深度学习的激活函数,不过,这种情况有可能会被Mish改变。

在论文中的定义:

首先看一下原版的darknet yolov3.cfg网络结构:

从算子位置上看,它属于每层网络的末端处理,位置上属于激活函数的的范围,事实上它却是也是一个激活函数。

经过VIP工具转换后的JSON格式的YOLOV4网络结构如下,可以看到MIST算子被独立了出来:

mish函数的数学公式为:

\\ mish(x)=f(x)=x\cdot tanh\big(ln(1+e^x)\big)

根据解析式可以看出,mish函数由常数和基本初等函数经过有限次的四则运算和有限次的函数复合步骤所构成并可用于一个解析式表示的函数,所以它是一个初等函数。我们逐个分析它的组成函数。

首先,mish函数可以拆分为更为基础的函数:

\\ mish(x)=f(x)=x\cdot tanh\big(ln(1+e^x)\big)=k(x)\cdot tanh(g(x))\ \ g(x)=ln(1+e^x)

的形式。

其中

y=k(x)=x

是正比函数

y=tanh(x)

是双曲正切函数,它的解析式为:

y=f(x)=tanh(x)=\frac{e^x-e^{-x}}{e^x+e^{-x}}

最后一个

y=g(x)=ln(1+e^x)

实际上是softplus(注意和softmax的区别)函数,根据形状可以看出,它是Relu的平滑,所以mish函数也可以写成:

\\ mish(x)=f(x)=x\cdot tanh\big(ln(1+e^x)\big)=x\cdot tanh\big(softplus(x)\big)

把这些函数绘制在一起为:

 根据图像可以看出来,mish函数和softplus,Relu函数图像相似,既然如此,已经有了softplus,Relu函数的情况下,为何还要实现mish算子呢,原来是mish函数在精度方面有所提升。

根据论文《Mish: A Self Regularized Non-Monotonic Activation Function》的一些实验进行说明。

这是 relu 和 mish 的梯度对比,可以看到 mish 的梯度更加平滑。

 精度方面,在 ImageNet-1K 数据集上对 mish、swish、relu、leaky relu 激活函数对网络精度的提升对了对比,数据如下:

以下是在 MS-COCO 目标检测数据集的对比数据:

从实测的精度提升数据来看,mish 具有十分明显的优势。

性能方面,在 pytorch 框架中,对 relu、softplus、mish、mish-cuda (RTX-2070) 在 fp32 和 fp16 精度下进行了性能对比,数据如下,可以看到 relu 在推理效率上要比 mish 快,mish-cuda 在用 cuda 进行优化后性能能提升很多。

Mish的C语言实现:

将mish函数变形:

\\y=f(x)=x\cdot tanh(ln(1+e^x))=x\frac{e^{ln(1+e^x)}-e^{-{ln(1+e^x)}}}{e^{ln(1+e^x)}+e^{-{ln(1+e^x)}}}=x\frac{(1+e^x)-\frac{1}{1+e^x}}{(1+e^x) +\frac{1}{1+e^x}} =\\ x\cdot \frac{(1+e^x)^2 -1}{(1+e^x)^2 +1}=x\cdot \frac{e^{2x} +2e^x}{(1+e^x)^2 +1}=x\cdot \frac{(1+e^x)^2 +1 -2}{(1+e^x)^2 +1}=x(1-\frac{2}{(1+e^x)^2 +1})=\\ x-\frac{2x}{(1+e^x)^2 +1}

所以,代码实现为:

/*
 * =====================================================================================
 *
 *       Filename:  mish.c
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  2021年11月10日 23时00分33秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  YOUR NAME (), 
 *   Organization:  
 *
 * =====================================================================================
 */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
 
double mish(double f)
{
	double exp_res=exp(f);
	double fenmu = (1+exp_res) * (1+exp_res) + 1;
	double fenzi = 2*f;
	double res1 = fenzi/fenmu;
	double res = f - res1;
 
	return res;
}
 
int main(void)
{
	int i;
	
	for(i = -10; i < 100; i ++)
	{
		printf("febnaqi(%d)=%f.\n", i, mish(i));
	}
 
	return 0;
}

运行结果为:

可以看到,数值计算得到的值很好的符合了MISH的图像,侧面反映了程序的正确性。

Pytorch中mish的实现:

swish激活函数:

和mish激活函数非常相似的还有另外一个叫做swish函数的激活函数,它的解析式有两个,分别是

f(x)=x\cdot sigmoid(x)=x\cdot \frac{1}{1+e^{-x}}

f(x)=x\cdot sigmoid(bx)=x\cdot \frac{1}{1+e^{-bx}}

它是谷歌在不久前提出的,其同样具有不饱和,光滑,非单调性的特征,和mish函数非常相似,其图形如下:

总结

ReLU有一些已知的弱点,但是通常它执行起来很轻,并且在计算上很轻。Mish具有较强的理论渊源,在测试中,就训练稳定性和准确性而言,Mish的平均性能优于ReLU。

复杂度只稍微增加了一点(V100 GPU和Mish,相对于ReLU,每epoch增加大约1秒),考虑到训练稳定性的提高和最终精度的提高,稍微增加一点时间似乎是值得的。

最终,在今年测试了大量新的激活函数后,Mish在这方面处于领先地位,它很有可能成为AI未来的新ReLU。

结束!

  • 7
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

papaofdoudou

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

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

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

打赏作者

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

抵扣说明:

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

余额充值