激活函數Swish

  Swish函數先對來說是比較新的一些激活函數,算是由之前的激活函數複合而成出來的。也是由Google提出的,畢竟資力雄厚,承擔的起搜索的任務。而且這個算法感覺曝光率還算比較高,就在這裏整理一下,同時後面的文章也會再次提到這個函數。
  對前面的激活函數有了一定的基礎之後,理解Swish激活就容易很多了,Swish函數的表達式是f(x)=xσ(x)f(x)=x·\sigma(x)σ(x)\sigma(x)就是sigmoid函數。因爲sigmoid函數的飽和性容易導致梯度消失,借鑑ReLU的效果,當xx非常大的時候,這個時候有f(x)f(x)趨近於xx,但是當xf(x)0x→-∞,則f(x)→0,函數的大致走勢和ReLU比較相似,但是又比ReLU複雜。
  但是呢,爲了讓自己理論看起來更厲害一些,所以通常就把自己的想法抽象成一個框架,以囊括更多的東西進去。通常在函數上體現就是加幾個超參數進去,然後呈現出更多的特性。在Swish中,加了一個超參數使得函數表達式變成了f(x)=xσ(βx)f(x)=x·\sigma(\beta x),然後說這個β\beta可以是常量,或者是可訓練參數。函數的圖像如下。
Swish函數圖像
  接下來就是考慮這個激活函數的反向傳播了,核心步驟就是求導。顯然這裏就是複合求導。f(x)=xσ(βx)f(x)=x·\sigma(\beta x)則有
激活函數求導
激活函數導函數圖像
  上面已經提到過x±x→±∞的情況,容易明白在x>0x>0的時候,同樣是不存在梯度消失的情況。而在x<0x<0的時候,神經元也不會像ReLU一樣出現死亡的情況。同時Swish相比於ReLU導數不是一成不變的,這也是一種優勢。而且Swish處處可導,連續光滑。另外還有一個特點就是Swish並非一個單調的函數。但是swish也並非沒有任何缺點,最大的缺點就是計算量大,本來sigmoid函數就不容易計算。
  在Swish之上,後面有人提出了一種激活函數叫h-swish,這個h代表hard(硬)的意思。大概是想讓激活函數硬起來。我說的是邊界,sigmoid函數取值位於[0,1]之間,兩側邊界都是趨近於0或者1,這個趨近於就是soft的意思,如果直接就是常量,這就是hard。
  找到一個sigmoid函數的近似,但是兩邊邊界是hard的。這個函數就是f(x)=relu6(x+3)6f(x)=\frac{relu6(x+3)}{6},relu6代表着什麼,因爲relu函數無上界,給relu函數加一個上界,如果大於6,就讓relu函數的值等於6,就是relu6。圖像如下。
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激活函數

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章