7

ニューラルネットワークライブラリについては、いくつかの活性化関数と損失関数とその派生関数を実装しました。それらは任意に組み合わせることができ、出力層の微分は、損失導関数と活性化導関数の積になります。どのように損失関数から独立してSoftmax派生を実装するのですか?

しかし、私はSoftmax活性化関数の派生を損失関数とは独立に実装することができませんでした。方程式の正規化すなわち分母のために、単一の入力アクチベーションを変更すると、1つではなく、すべての出力アクチベーションが変更される。

派生物が約1%勾配検査に失敗するSoftmaxの実装がここにあります。ソフトマックスのデリバティブをどのように実装すれば、どのような損失機能と組み合わせることができますか?

import numpy as np 


class Softmax: 

    def compute(self, incoming): 
     exps = np.exp(incoming) 
     return exps/exps.sum() 

    def delta(self, incoming, outgoing): 
     exps = np.exp(incoming) 
     others = exps.sum() - exps 
     return 1/(2 + exps/others + others/exps) 


activation = Softmax() 
cost = SquaredError() 

outgoing = activation.compute(incoming) 
delta_output_layer = activation.delta(incoming) * cost.delta(outgoing) 

答えて

3

は、数学的に、Xjのに対して、ソフトマックス(XI)の誘導体である:赤デルタはクロネッカーのデルタである

enter image description here

あなたが反復的に実装する場合

def softmax_grad(s): 
    # input s is softmax value of the original input x. Its shape is (1,n) 
    # e.i. s = np.array([0.3,0.7]), x = np.array([0,1]) 

    # make the matrix whose size is n^2. 
    jacobian_m = np.diag(s) 

    for i in range(len(jacobian_m)): 
     for j in range(len(jacobian_m)): 
      if i == j: 
       jacobian_m[i][j] = s[i] * (1-s[i]) 
      else: 
       jacobian_m[i][j] = -s[i]*s[j] 
    return jacobian_m 

テスト:

In [95]: x 
Out[95]: array([1, 2]) 

In [96]: softmax(x) 
Out[96]: array([ 0.26894142, 0.73105858]) 

In [97]: softmax_grad(softmax(x)) 
Out[97]: 
array([[ 0.19661193, -0.19661193], 
     [-0.19661193, 0.19661193]]) 

あなたはベクトル化バージョンで実装する場合:あなたの答えのための

soft_max = softmax(x)  

# reshape softmax to 2d so np.dot gives matrix multiplication 

def softmax_grad(softmax): 
    s = softmax.reshape(-1,1) 
    return np.diagflat(s) - np.dot(s, s.T) 

softmax_grad(soft_max) 

#array([[ 0.19661193, -0.19661193], 
#  [-0.19661193, 0.19661193]]) 
+0

? –

10

それはこのようにする必要があります:(xはソフトマックス層に入力され、dyがデルタはそれ以上の損失から来ている)

dx = y * dy 
    s = dx.sum(axis=dx.ndim - 1, keepdims=True) 
    dx -= y * s 

    return dx 

しかし、あなたはエラーがあるべき計算方法:

yact = activation.compute(x) 
    ycost = cost.compute(yact) 
    dsoftmax = activation.delta(x, cost.delta(yact, ycost, ytrue)) 

説明:delta機能はバックプロパゲーションアルゴリズムの一部であるため、その責任は私にベクトルdyを(乗算することですコードoutgoingcompute(x)のヤコビアン関数は、xで評価されます。このヤコビのようなものをsoftmax [1]のように見せて、ベクトルdyで左から掛けると、少しの代数の後に私のPythonコードに相当するものが得られることがわかります。

[1] https://stats.stackexchange.com/questions/79454/softmax-layer-in-a-neural-network

+0

感謝を。あなたは 'res'によって何を参照していますか? – danijar

+0

私はdxを意味しました(私はこの回答のコードを手動でリファクタリングしていましたが、このコードの存在は忘れていました)。私は答えでそれを修正しました。 – ticcky

+0

あなたのソリューションはうまく動作します。勾配チェックが合格。好奇心のために、あなたはその式を思いついた方法を簡単に説明できますか?私は本当にそれを理解したいと思います。 – danijar

関連する問題