Swish函數先對來說是比較新的一些激活函數,算是由之前的激活函數複合而成出來的。也是由Google提出的,畢竟資力雄厚,承擔的起搜索的任務。而且這個算法感覺曝光率還算比較高,就在這裏整理一下,同時後面的文章也會再次提到這個函數。
對前面的激活函數有了一定的基礎之後,理解Swish激活就容易很多了,Swish函數的表達式是,就是sigmoid函數。因爲sigmoid函數的飽和性容易導致梯度消失,借鑑ReLU的效果,當非常大的時候,這個時候有趨近於,但是當,函數的大致走勢和ReLU比較相似,但是又比ReLU複雜。
但是呢,爲了讓自己理論看起來更厲害一些,所以通常就把自己的想法抽象成一個框架,以囊括更多的東西進去。通常在函數上體現就是加幾個超參數進去,然後呈現出更多的特性。在Swish中,加了一個超參數使得函數表達式變成了,然後說這個可以是常量,或者是可訓練參數。函數的圖像如下。
接下來就是考慮這個激活函數的反向傳播了,核心步驟就是求導。顯然這裏就是複合求導。則有
上面已經提到過的情況,容易明白在的時候,同樣是不存在梯度消失的情況。而在的時候,神經元也不會像ReLU一樣出現死亡的情況。同時Swish相比於ReLU導數不是一成不變的,這也是一種優勢。而且Swish處處可導,連續光滑。另外還有一個特點就是Swish並非一個單調的函數。但是swish也並非沒有任何缺點,最大的缺點就是計算量大,本來sigmoid函數就不容易計算。
在Swish之上,後面有人提出了一種激活函數叫h-swish,這個h代表hard(硬)的意思。大概是想讓激活函數硬起來。我說的是邊界,sigmoid函數取值位於[0,1]之間,兩側邊界都是趨近於0或者1,這個趨近於就是soft的意思,如果直接就是常量,這就是hard。
找到一個sigmoid函數的近似,但是兩邊邊界是hard的。這個函數就是,relu6代表着什麼,因爲relu函數無上界,給relu函數加一個上界,如果大於6,就讓relu函數的值等於6,就是relu6。圖像如下。
顯然如果對relu6再除6再向左平移三個單位,就會得到一條類似於sigmoid函數的圖像。對比圖如下。
可以看到swish中使用到了sigmoid函數,如果我們使用h-sigmoid來構造swish函數,就得到了h-swish函數。這樣一近似,計算量也變小了。
這個激活後函數基本就是這樣了,不知道以後是否會變成一種範式,徹底撼動ReLU的地位。
pytorch實現
class SwishImplementation(torch.autograd.Function):
@staticmethod
def forward(ctx, i):
ctx.save_for_backward(i)
return i * torch.sigmoid(i)
@staticmethod
def backward(ctx, grad_output):
sigmoid_i = torch.sigmoid(ctx.saved_variables[0])
return grad_output * (sigmoid_i * (1 + ctx.saved_variables[0] * (1 - sigmoid_i)))
class Swish(nn.Module):
def forward(self, x):
return SwishImplementation.apply(x)
系列文章:
神經網絡中的激活函數總述
sigmoid激活函數
tanh激活函數
ReLU系列激活函數
maxout激活函數
Swish激活函數