YOLO v4常見(jiàn)的非線性激活函數(shù)詳解
YOLO v4中用到的激活函數(shù)是Mish激活函數(shù)
在YOLO v4中被提及的激活函數(shù)有: ReLU, Leaky ReLU, PReLU, ReLU6, SELU, Swish, Mish
其中Leaky ReLU, PReLU難以訓(xùn)練,ReLU6轉(zhuǎn)為量化網(wǎng)絡(luò)設(shè)計(jì)
激活函數(shù)使用過(guò)程圖:
一、飽和激活函數(shù)
1.1、Sigmoid
函數(shù)表達(dá)式:

Sigmoid函數(shù)圖像及其導(dǎo)數(shù)圖像:
優(yōu)點(diǎn):
- 是一個(gè)便于求導(dǎo)的平滑函數(shù);
- 能壓縮數(shù)據(jù),使輸出保證在 [ 0 , 1 ] [0,1] [0,1]之間(相當(dāng)于對(duì)輸出做了歸一化),保證數(shù)據(jù)幅度不會(huì)有問(wèn)題;
- (有上下界)適合用于前向傳播,但是不利于反向傳播。
缺點(diǎn):
- 容易出現(xiàn)梯度消失(gradient vanishing),不利于權(quán)重更新;
- 不是0均值(zero-centered)的,這會(huì)導(dǎo)致后層的神經(jīng)元的輸入是非0均值的信號(hào),這會(huì)對(duì)梯度產(chǎn)生影響。以 f=sigmoid(wx+b)為例, 假設(shè)輸入均為正數(shù)(或負(fù)數(shù)),那么對(duì)w的導(dǎo)數(shù)總是正數(shù)(或負(fù)數(shù)),這樣在反向傳播過(guò)程中要么都往正方向更新,要么都往負(fù)方向更新,導(dǎo)致有一種捆綁效果,使得收斂緩慢。
- 指數(shù)運(yùn)算,相對(duì)耗時(shí)。
1.2、hard-Sigmoid函數(shù)
hard-Sigmoid函數(shù)時(shí)Sigmoid激活函數(shù)的分段線性近似。
函數(shù)公式:

hard-Sigmoid函數(shù)圖像和Sigmoid函數(shù)圖像對(duì)比:
hard-Sigmoid函數(shù)圖像及其導(dǎo)數(shù)圖像:
優(yōu)點(diǎn):
- 從公示和曲線上來(lái)看,其更易計(jì)算,沒(méi)有指數(shù)運(yùn)算,因此會(huì)提高訓(xùn)練的效率。
缺點(diǎn):
- 首次派生值為零可能會(huì)導(dǎo)致神經(jīng)元died或者過(guò)慢的學(xué)習(xí)率。
1.3、Tanh雙曲正切
函數(shù)表達(dá)式:

Tanh函數(shù)圖像及其導(dǎo)函數(shù)圖像:
優(yōu)點(diǎn):
- 解決了Sigmoid函數(shù)的非zero-centered問(wèn)題
- 能壓縮數(shù)據(jù),使輸出保證在 [ 0 , 1 ] [0,1] [0,1]之間(相當(dāng)于對(duì)輸出做了歸一化),保證數(shù)據(jù)幅度不會(huì)有問(wèn)題;(有上下界)
缺點(diǎn):
- 還是容易出現(xiàn)梯度消失(gradient vanishing),不利于權(quán)重更新;
- 指數(shù)運(yùn)算,相對(duì)耗時(shí)。
二、非飽和激活函數(shù)
2.1、ReLU(修正線性單元)
函數(shù)表達(dá)式:
ReLU函數(shù)圖像及其導(dǎo)數(shù)圖像:
優(yōu)點(diǎn):
- ReLu的收斂速度比 sigmoid 和 tanh 快;
- 輸入為正時(shí),解決了梯度消失的問(wèn)題,適合用于反向傳播。;
- 計(jì)算復(fù)雜度低,不需要進(jìn)行指數(shù)運(yùn)算;
缺點(diǎn):
- ReLU的輸出不是zero-centered;
- ReLU不會(huì)對(duì)數(shù)據(jù)做幅度壓縮,所以數(shù)據(jù)的幅度會(huì)隨著模型層數(shù)的增加不斷擴(kuò)張。(有下界無(wú)上界)
- Dead ReLU Problem(神經(jīng)元壞死現(xiàn)象):x為負(fù)數(shù)時(shí),梯度都是0,這些神經(jīng)元可能永遠(yuǎn)不會(huì)被激活,導(dǎo)致相應(yīng)參數(shù)永遠(yuǎn)不會(huì)被更新。(輸入為負(fù)時(shí),函數(shù)存在梯度消失的現(xiàn)象)
2.2、ReLU6(抑制其最大值)
函數(shù)表達(dá)式:
ReLU函數(shù)圖像和ReLU6函數(shù)圖像對(duì)比:
ReLU6函數(shù)圖像及其導(dǎo)數(shù)圖像:
2.3、Leakly ReLU
函數(shù)表達(dá)式:
ReLU函數(shù)圖像和Leakly ReLU函數(shù)圖像對(duì)比:
Leakly ReLU函數(shù)圖像及其導(dǎo)數(shù)圖像:
優(yōu)點(diǎn):
- 解決上述的dead ReLU現(xiàn)象, 讓負(fù)數(shù)區(qū)域也會(huì)梯度消失;
理論上Leaky ReLU 是優(yōu)于ReLU的,但是實(shí)際操作中,并不一定。
2.4、PReLU(parametric ReLU)
函數(shù)公式:

注意:
函數(shù)圖像:
優(yōu)點(diǎn):
- 可以避免dead ReLU現(xiàn)象;
- 與ELU相比,輸入為負(fù)數(shù)時(shí)不會(huì)出現(xiàn)梯度消失。
2.5、ELU(指數(shù)線性函數(shù))
函數(shù)表達(dá)式:

ELU函數(shù)圖像及其導(dǎo)數(shù)圖像( α = 1.5 \alpha=1.5 α=1.5):
優(yōu)點(diǎn):
- 有ReLU的所有優(yōu)點(diǎn),且沒(méi)有Dead ReLU Problem(神經(jīng)元壞死現(xiàn)象);
- 輸出是zero-centered的,輸出平均值接近0;
- 通過(guò)減少偏置偏移的影響,使正常梯度更加接近自然梯度,從而使均值向0加速學(xué)習(xí)。
缺點(diǎn):
- 計(jì)算量更高了。
理論上ELU優(yōu)于ReLU, 但是真實(shí)數(shù)據(jù)下,并不一定。
2.6、SELU
SELU就是在ELU的基礎(chǔ)上添加了一個(gè) λ \lambda λ參數(shù),且 λ > 1 \lambda>1 λ>1
函數(shù)表達(dá)式:

ELU函數(shù)圖像和SELU函數(shù)圖像對(duì)比( α = 1.5 , λ = 2 \alpha=1.5, \lambda=2 α=1.5,λ=2):
SELU函數(shù)圖像及其導(dǎo)數(shù)圖像( α = 1.5 , λ = 2 \alpha=1.5, \lambda=2 α=1.5,λ=2):
優(yōu)點(diǎn):
- 以前的ReLU、P-ReLU、ELU等激活函數(shù)都是在負(fù)半軸坡度平緩,這樣在激活的方差過(guò)大時(shí)可以讓梯度減小,防止了梯度爆炸,但是在正半軸其梯度簡(jiǎn)答的設(shè)置為了1。而SELU的正半軸大于1,在方差過(guò)小的時(shí)候可以讓它增大,但是同時(shí)防止了梯度消失。這樣激活函數(shù)就有了一個(gè)不動(dòng)點(diǎn),網(wǎng)絡(luò)深了之后每一層的輸出都是均值為0,方差為1. 2.7、Swish
函數(shù)表達(dá)式:

Swish函數(shù)圖像( β = 0.1 , β = 1 , β = 10 \beta=0.1, \beta=1,\beta=10 β=0.1,β=1,β=10):
Swish函數(shù)梯度圖像( β = 0.1 , β = 1 , β = 10 \beta=0.1, \beta=1,\beta=10 β=0.1,β=1,β=10):
優(yōu)點(diǎn):
- 在x > 0的時(shí)候,同樣是不存在梯度消失的情況;而在x < 0時(shí)候,神經(jīng)元也不會(huì)像ReLU一樣出現(xiàn)死亡的情況。
- 同時(shí)Swish相比于ReLU導(dǎo)數(shù)不是一成不變的,這也是一種優(yōu)勢(shì)。
- 而且Swish處處可導(dǎo),連續(xù)光滑。
缺點(diǎn):
- 計(jì)算量大,本來(lái)sigmoid函數(shù)就不容易計(jì)算,它比sigmoid還難。 2.8、hard-Swish
hard = 硬,就是讓圖像在整體上沒(méi)那么光滑(從下面兩個(gè)圖都可以看出來(lái))
函數(shù)表達(dá)式:
hard-Swish函數(shù)圖像和Swish( β = 1 \beta=1 β=1)函數(shù)圖像對(duì)比:
hard-Swish函數(shù)圖像和Swish( β = 1 \beta=1 β=1)函數(shù)梯度圖像對(duì)比:
優(yōu)點(diǎn):
- hard-Swish近似達(dá)到了Swish的效果;
- 且改善了Swish的計(jì)算量過(guò)大的問(wèn)題,在量化模式下,ReLU函數(shù)相比Sigmoid好算太多了;
2.9、Mish
論文地址:
https://arxiv.org/pdf/1908.08681.pdf
關(guān)于激活函數(shù)改進(jìn)的最新一篇文章,且被廣泛用于YOLO4中,相比Swish有0.494%的提升,相比ReLU有1.671%的提升。
Mish函數(shù)公式:
Mish函數(shù)圖像和Swish( β = 1 \beta=1 β=1)函數(shù)圖像對(duì)比:
Mish函數(shù)圖像和Swish( β = 1 \beta=1 β=1)函數(shù)導(dǎo)數(shù)圖像對(duì)比:
為什么Mish表現(xiàn)的更好:
上面無(wú)邊界(即正值可以達(dá)到任何高度)避免了由于封頂而導(dǎo)致的飽和。理論上對(duì)負(fù)值的輕微允許更好的梯度流,而不是像ReLU中那樣的硬零邊界。
最后,可能也是最重要的,目前的想法是,平滑的激活函數(shù)允許更好的信息深入神經(jīng)網(wǎng)絡(luò),從而得到更好的準(zhǔn)確性和泛化。Mish函數(shù)在曲線上幾乎所有點(diǎn)上都極其平滑。
三、PyTorch 實(shí)現(xiàn)
import matplotlib.pyplot as plt import numpy as np class ActivateFunc(): def __init__(self, x, b=None, lamb=None, alpha=None, a=None): super(ActivateFunc, self).__init__() self.x = x self.b = b self.lamb = lamb self.alpha = alpha self.a = a def Sigmoid(self): y = np.exp(self.x) / (np.exp(self.x) + 1) y_grad = y*(1-y) return [y, y_grad] def Hard_Sigmoid(self): f = (2 * self.x + 5) / 10 y = np.where(np.where(f > 1, 1, f) < 0, 0, np.where(f > 1, 1, f)) y_grad = np.where(f > 0, np.where(f >= 1, 0, 1 / 5), 0) return [y, y_grad] def Tanh(self): y = np.tanh(self.x) y_grad = 1 - y * y return [y, y_grad] def ReLU(self): y = np.where(self.x < 0, 0, self.x) y_grad = np.where(self.x < 0, 0, 1) return [y, y_grad] def ReLU6(self): y = np.where(np.where(self.x < 0, 0, self.x) > 6, 6, np.where(self.x < 0, 0, self.x)) y_grad = np.where(self.x > 6, 0, np.where(self.x < 0, 0, 1)) return [y, y_grad] def LeakyReLU(self): # a大于1,指定a y = np.where(self.x < 0, self.x / self.a, self.x) y_grad = np.where(self.x < 0, 1 / self.a, 1) return [y, y_grad] def PReLU(self): # a大于1,指定a y = np.where(self.x < 0, self.x / self.a, self.x) y_grad = np.where(self.x < 0, 1 / self.a, 1) return [y, y_grad] def ELU(self): # alpha是個(gè)常數(shù),指定alpha y = np.where(self.x > 0, self.x, self.alpha * (np.exp(self.x) - 1)) y_grad = np.where(self.x > 0, 1, self.alpha * np.exp(self.x)) return [y, y_grad] def SELU(self): # lamb大于1,指定lamb和alpha y = np.where(self.x > 0, self.lamb * self.x, self.lamb * self.alpha * (np.exp(self.x) - 1)) y_grad = np.where(self.x > 0, self.lamb * 1, self.lamb * self.alpha * np.exp(self.x)) return [y, y_grad] def Swish(self): # b是一個(gè)常數(shù),指定b y = self.x * (np.exp(self.b*self.x) / (np.exp(self.b*self.x) + 1)) y_grad = np.exp(self.b*self.x)/(1+np.exp(self.b*self.x)) + self.x * (self.b*np.exp(self.b*self.x) / ((1+np.exp(self.b*self.x))*(1+np.exp(self.b*self.x)))) return [y, y_grad] def Hard_Swish(self): f = self.x + 3 relu6 = np.where(np.where(f < 0, 0, f) > 6, 6, np.where(f < 0, 0, f)) relu6_grad = np.where(f > 6, 0, np.where(f < 0, 0, 1)) y = self.x * relu6 / 6 y_grad = relu6 / 6 + self.x * relu6_grad / 6 return [y, y_grad] def Mish(self): f = 1 + np.exp(x) y = self.x * ((f*f-1) / (f*f+1)) y_grad = (f*f-1) / (f*f+1) + self.x*(4*f*(f-1)) / ((f*f+1)*(f*f+1)) return [y, y_grad] def PlotActiFunc(x, y, title): plt.grid(which='minor', alpha=0.2) plt.grid(which='major', alpha=0.5) plt.plot(x, y) plt.title(title) plt.show() def PlotMultiFunc(x, y): plt.grid(which='minor', alpha=0.2) plt.grid(which='major', alpha=0.5) plt.plot(x, y) if __name__ == '__main__': x = np.arange(-10, 10, 0.01) activateFunc = ActivateFunc(x) activateFunc.a = 100 activateFunc.b= 1 activateFunc.alpha = 1.5 activateFunc.lamb = 2 plt.figure(1) PlotMultiFunc(x, activateFunc.Sigmoid()[0]) PlotMultiFunc(x, activateFunc.Hard_Sigmoid()[0]) PlotMultiFunc(x, activateFunc.Tanh()[0]) PlotMultiFunc(x, activateFunc.ReLU()[0]) PlotMultiFunc(x, activateFunc.ReLU6()[0]) PlotMultiFunc(x, activateFunc.LeakyReLU()[0]) PlotMultiFunc(x, activateFunc.ELU()[0]) PlotMultiFunc(x, activateFunc.SELU()[0]) PlotMultiFunc(x, activateFunc.Swish()[0]) PlotMultiFunc(x, activateFunc.Hard_Swish()[0]) PlotMultiFunc(x, activateFunc.Mish()[0]) plt.legend(['Sigmoid', 'Hard_Sigmoid', 'Tanh', 'ReLU', 'ReLU6', 'LeakyReLU', 'ELU', 'SELU', 'Swish', 'Hard_Swish', 'Mish']) plt.show()
四、結(jié)果顯示
Reference
https://arxiv.org/pdf/1908.08681.pdf
到此這篇關(guān)于YOLO v4常見(jiàn)的非線性激活函數(shù)詳解的文章就介紹到這了,更多相關(guān)YOLO v4激活函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- pytorch/transformers?最后一層不加激活函數(shù)的原因分析
- python人工智能tensorflow常用激活函數(shù)Activation?Functions
- python 深度學(xué)習(xí)中的4種激活函數(shù)
- 使用keras實(shí)現(xiàn)非線性回歸(兩種加激活函數(shù)的方式)
- Keras 中Leaky ReLU等高級(jí)激活函數(shù)的用法
- tensorflow自定義激活函數(shù)實(shí)例
- pytorch方法測(cè)試——激活函數(shù)(ReLU)詳解
- 詳解Python中常用的激活函數(shù)(Sigmoid、Tanh、ReLU等)
相關(guān)文章
Eclipse 誤刪文件的恢復(fù)與代碼的恢復(fù)詳解
這篇文章主要介紹了Eclipse 誤刪文件的恢復(fù),代碼的恢復(fù)的相關(guān)資料,需要的朋友可以參考下2016-09-09Scala函數(shù)式編程專題--scala集合和函數(shù)
這篇文章主要介紹了scala集合和函數(shù)的的相關(guān)資料,文中示例代碼非常詳細(xì),幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下2020-06-06計(jì)算機(jī)二級(jí)如何一次性通過(guò)?給NCRE焦躁心情降溫!
計(jì)算機(jī)二級(jí)到現(xiàn)階段應(yīng)該如何備考,該聽(tīng)什么課?該針對(duì)哪些考點(diǎn)重點(diǎn)學(xué)習(xí),這些都要做到心里有數(shù),有計(jì)劃性。這篇文章為大家分享了計(jì)算機(jī)二級(jí)備考技巧,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08聊聊自學(xué),那些讓你事半功倍的自學(xué)資源(干貨分享)
B站是一個(gè)學(xué)習(xí)網(wǎng)站。一入B站深似海,從此游戲是路人。B站雖然視頻資源多,但是內(nèi)容也是五花八門(mén)、參差不齊,本文給大家收集了關(guān)于學(xué)習(xí)計(jì)算機(jī)編程的視頻,這里有我曾經(jīng)的入門(mén)視頻,也有跟朋友交流獲得的,特此篩選了下面這些視頻,分享給大家2021-04-04ascii碼表(二進(jìn)制 十進(jìn)制 十六進(jìn)制)詳細(xì)介紹
這篇文章主要介紹了ascii碼表二進(jìn)制 十進(jìn)制 十六進(jìn)制詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下2017-01-01