PythonでSoftmax関数を実装する方法


245

Udacityの深い学習クラス、Y_Iのソフトマックスは、単に全体のYベクトルの指数の合計で割った指数です。

ここに画像の説明を入力してください

どこS(y_i)のソフトマックス関数であるy_ie指数関数的であるとjnoです。入力ベクトルYの列の数。

私は以下を試しました:

import numpy as np

def softmax(x):
    """Compute softmax values for each sets of scores in x."""
    e_x = np.exp(x - np.max(x))
    return e_x / e_x.sum()

scores = [3.0, 1.0, 0.2]
print(softmax(scores))

これは次を返します:

[ 0.8360188   0.11314284  0.05083836]

しかし、提案された解決策は:

def softmax(x):
    """Compute softmax values for each sets of scores in x."""
    return np.exp(x) / np.sum(np.exp(x), axis=0)

これは、最初の実装が各列と最大値の差を明示的に取り、合計で除算した場合でも、最初の実装と同じ出力を生成します。

誰かが数学的に理由を示すことができますか?1つは正しいですか、もう1つは間違っていますか?

コードと時間の複雑さの点で実装は似ていますか?どちらがより効率的ですか?


6
max関数を使用してこの方法で実装しようとした理由を知りたいと思います。そのように考えたのはなぜですか?
BBischof 2016年

1
わかりません。最大値を0として扱い、グラフを左に移動して0でクリップするのが役立つと思いました。次に、私の範囲は、から-inf to +infに短縮され-inf to 0ます。私は考えすぎだったと思います。hahahaaa
alvas

1
私はまだ1つのサブ)質問がありますが、以下では答えられないようです。axis = 0Udacityによって提案された答えの意味は何ですか?
Parva Thakkar 16年

3
numpyのドキュメントを見ると、sum(x、axis = 0)と同様にaxis = 1が何を行うかが説明されています。つまり、配列の配列を合計する方向を提供します。この場合、ベクトルに沿って合計するように指示します。この場合、これはsoftmax関数の分母に対応します。
BBischof 2016年

3
それは隔週のようです、私の数学が誰が正しいかを決定するのに十分ではないところまで、より正しい答えがあります=)答えを提供しなかった数学の専門家がどれが正しいかを決定するのを助けることができますか?
alvas

回答:


137

どちらも正しいですが、数値の安定性の観点からはあなたの方が好ましいです。

あなたは

e ^ (x - max(x)) / sum(e^(x - max(x))

a ^(b-c)=(a ^ b)/(a ^ c)という事実を使用して

= e ^ x / (e ^ max(x) * sum(e ^ x / e ^ max(x)))

= e ^ x / sum(e ^ x)

それは他の答えが言うことです。max(x)を任意の変数に置き換えると、キャンセルされます。


4
さらに明確にするために、回答を@TrevorMで再フォーマットします:e ^(x-max(x))/ sum(e ^(x-max(x))using a ^(b-c)=(a ^ b)/(a ^ c)あります= e ^ x / {e ^ max(x)* sum(e ^ x / e ^ max(x))} = e ^ x / sum(e ^ x)
shanky_thebearer 2016年

5
@Trevor Merrifield、最初のアプローチには「不要な用語」があったとは思いません。実際には、2番目のアプローチよりも優れています。この点は別の答えとして追加しました。
Shagun Sodhani、2016

6
@Shagun正解です。この2つは数学的には同等ですが、数値の安定性については考慮していませんでした。
Trevor Merrifield、2016

よろしくお願いします。コメントが読まれない(またはコメントが消える)場合に備えて、「不要な用語」を編集しました。このページは検索エンジンからかなりのトラフィックを得ており、これは現在、人々が目にする最初の回答です。
Alex Riley

なぜmax(abs(x))ではなくmax(x)を減算するのでしょうか(値を決定した後で符号を修正してください)。すべての値がゼロ未満で、絶対値が非常に大きい場合、値(最大値)のみがゼロに近い場合、最大値を減算しても何も変わりません。まだ数値的に不安定ではないでしょうか?
チェルノ

101

(まあ...質問と回答の両方でここで多くの混乱...)

まず、2つのソリューション(つまり、あなたのソリューションと推奨されるソリューション)は同等ではありません。それらは起こるのみ1-Dスコアアレイの特殊な場合のために同等であること。Udacityクイズで提供された例の2次元スコア配列も試した場合、それを発見したでしょう。

結果として、2つのソリューションの実際の違いはaxis=0引数のみです。これが事実であることを確認するには、ソリューション(your_softmax)と、唯一の違いがaxis引数であるソリューションを試してみましょう。

import numpy as np

# your solution:
def your_softmax(x):
    """Compute softmax values for each sets of scores in x."""
    e_x = np.exp(x - np.max(x))
    return e_x / e_x.sum()

# correct solution:
def softmax(x):
    """Compute softmax values for each sets of scores in x."""
    e_x = np.exp(x - np.max(x))
    return e_x / e_x.sum(axis=0) # only difference

すでに述べたように、1次元のスコア配列の場合、結果は実際に同じです。

scores = [3.0, 1.0, 0.2]
print(your_softmax(scores))
# [ 0.8360188   0.11314284  0.05083836]
print(softmax(scores))
# [ 0.8360188   0.11314284  0.05083836]
your_softmax(scores) == softmax(scores)
# array([ True,  True,  True], dtype=bool)

それにもかかわらず、テストの例としてUdacityクイズで与えられた2次元スコア配列の結果は次のとおりです。

scores2D = np.array([[1, 2, 3, 6],
                     [2, 4, 5, 6],
                     [3, 8, 7, 6]])

print(your_softmax(scores2D))
# [[  4.89907947e-04   1.33170787e-03   3.61995731e-03   7.27087861e-02]
#  [  1.33170787e-03   9.84006416e-03   2.67480676e-02   7.27087861e-02]
#  [  3.61995731e-03   5.37249300e-01   1.97642972e-01   7.27087861e-02]]

print(softmax(scores2D))
# [[ 0.09003057  0.00242826  0.01587624  0.33333333]
#  [ 0.24472847  0.01794253  0.11731043  0.33333333]
#  [ 0.66524096  0.97962921  0.86681333  0.33333333]]

結果は異なります。2番目の列は実際にUdacityクイズで予想されるものとまったく同じです。最初の(間違った)結果とは異なり、すべての列の合計が1になります。

だから、すべての大騒ぎは実際には実装の詳細- axis議論のためでした。numpy.sumドキュメントによると:

デフォルトのaxis = Noneは、入力配列のすべての要素を合計します

ここにいる間、私たちは、したがって、行方向に合計しますaxis=0。1次元配列の場合、(唯一の)行の合計とすべての要素の合計は偶然同じになるため、その場合の結果は同じになります...

axis問題はさておき、あなたの実装(最大最初を減算するつまり、あなたの選択は)実際にはより良い提案された解決策よりも!実際、これはsoftmax関数を実装するための推奨される方法です- 正当化についてはこちらを参照してください(数値の安定性、他のいくつかの回答でも指摘されています)。


まあ、多次元配列について話しているだけなら。最初のソリューションはaxismaxとの両方に引数を追加することで簡単に修正できますsum。ただし、最初の実装は、服用すると簡単にオーバーフローする可能性があるため、さらに優れていますexp
Louis Yang

@LouisYang私はフォローしていません。「最初の」ソリューションはどれですか?どちらを使用しませexpか?ここで、axis引数を追加する以外に何が変更されましたか?
desertnaut

最初のソリューションは、@ alvasのソリューションを参照しています。違いは、alvasの質問で提案されている解決策には、最大値を差し引く部分がないということです。これは簡単にオーバーフローを引き起こす可能性があります。たとえば、exp(1000)/(exp(1000)+ exp(1001))vs exp(-1)/(exp(-1)+ exp(0))は数学的には同じですが、最初のものはオーバーフローします。
Louis Yang

@LouisYangまだ、私はあなたのコメントの必要性を理解しているのかわかりません-これはすべて回答ですでに明示的に対処されています。
desertnaut

@LouisYangは、スレッドの(その後の)人気に騙されないようにしてください。そして、独自の答えが提供されたコンテキストを想像してみてください:困惑したOP(「どちらも同じ結果が出る」)と(まだ!)受け入れられている答え「両方が正しい」と主張する(まあ、そうではない)。答えは「ソフトマックスを計算するための最も正確で効率的な方法ですという意味ではありませんでした。これは、議論された特定の Udacityクイズで、2つのソリューションが同等ではない理由を正当化するためだけのものでした
desertnaut

56

だから、これは本当に砂漠の人の答えへのコメントですが、私の評判のため、まだコメントすることはできません。彼が指摘したように、バージョンが正しいのは、入力が単一のサンプルで構成されている場合のみです。入力が複数のサンプルで構成されている場合は、誤りです。しかし、砂漠の飛行士の解決策も間違っています。問題は、1次元の入力を受け取ってから2次元の入力を受け取ることです。これをお見せしましょう。

import numpy as np

# your solution:
def your_softmax(x):
    """Compute softmax values for each sets of scores in x."""
    e_x = np.exp(x - np.max(x))
    return e_x / e_x.sum()

# desertnaut solution (copied from his answer): 
def desertnaut_softmax(x):
    """Compute softmax values for each sets of scores in x."""
    e_x = np.exp(x - np.max(x))
    return e_x / e_x.sum(axis=0) # only difference

# my (correct) solution:
def softmax(z):
    assert len(z.shape) == 2
    s = np.max(z, axis=1)
    s = s[:, np.newaxis] # necessary step to do broadcasting
    e_x = np.exp(z - s)
    div = np.sum(e_x, axis=1)
    div = div[:, np.newaxis] # dito
    return e_x / div

砂漠の飛行士の例を見てみましょう:

x1 = np.array([[1, 2, 3, 6]]) # notice that we put the data into 2 dimensions(!)

これは出力です:

your_softmax(x1)
array([[ 0.00626879,  0.01704033,  0.04632042,  0.93037047]])

desertnaut_softmax(x1)
array([[ 1.,  1.,  1.,  1.]])

softmax(x1)
array([[ 0.00626879,  0.01704033,  0.04632042,  0.93037047]])

この状況では、desernautsバージョンが失敗することがわかります。(入力がnp.array([1、2、3、6])のように1次元である場合は、そうではありません。

2次元の入力を使用するのはこのためです。次のx2は、desernautsの例のx2とは異なります。

x2 = np.array([[1, 2, 3, 6],  # sample 1
               [2, 4, 5, 6],  # sample 2
               [1, 2, 3, 6]]) # sample 1 again(!)

この入力は、3つのサンプルを含むバッチで構成されています。ただし、サンプル1と3は基本的に同じです。3行のsoftmaxアクティベーションが予想されます。最初のアクティベーションは3番目と同じで、x1のアクティベーションと同じである必要があります。

your_softmax(x2)
array([[ 0.00183535,  0.00498899,  0.01356148,  0.27238963],
       [ 0.00498899,  0.03686393,  0.10020655,  0.27238963],
       [ 0.00183535,  0.00498899,  0.01356148,  0.27238963]])


desertnaut_softmax(x2)
array([[ 0.21194156,  0.10650698,  0.10650698,  0.33333333],
       [ 0.57611688,  0.78698604,  0.78698604,  0.33333333],
       [ 0.21194156,  0.10650698,  0.10650698,  0.33333333]])

softmax(x2)
array([[ 0.00626879,  0.01704033,  0.04632042,  0.93037047],
       [ 0.01203764,  0.08894682,  0.24178252,  0.65723302],
       [ 0.00626879,  0.01704033,  0.04632042,  0.93037047]])

これが私の解決策の場合にのみ当てはまることをご理解いただければ幸いです。

softmax(x1) == softmax(x2)[0]
array([[ True,  True,  True,  True]], dtype=bool)

softmax(x1) == softmax(x2)[2]
array([[ True,  True,  True,  True]], dtype=bool)

さらに、TensorFlows softmax実装の結果は次のとおりです。

import tensorflow as tf
import numpy as np
batch = np.asarray([[1,2,3,6],[2,4,5,6],[1,2,3,6]])
x = tf.placeholder(tf.float32, shape=[None, 4])
y = tf.nn.softmax(x)
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(y, feed_dict={x: batch})

そしてその結果:

array([[ 0.00626879,  0.01704033,  0.04632042,  0.93037045],
       [ 0.01203764,  0.08894681,  0.24178252,  0.657233  ],
       [ 0.00626879,  0.01704033,  0.04632042,  0.93037045]], dtype=float32)

6
それはコメントの地獄だったでしょう;-)
Michael Benjamin

27
np.exp(z)/ np.sum(np.exp(z)、axis = 1、keepdims = True)は、softmax関数と同じ結果になります。sの手順は不要です。
PabTorre 2016年

の代わりにs = s[:, np.newaxis]、動作する s = s.reshape(z.shape[0],1)はずです。
Debashish 2017

2
このページには、多くの正しくない/非効率的なソリューションがあります。自分の好みに合わせてPabTorreを使用してください
Miss Palmer

@PabTorreあなたはaxis = -1を意味しましたか?axis = 1は1次元入力では機能しません
DiehardTheTryhard

36

どちらも数学的には正しいですが、実装面では最初のほうが良いと思います。softmaxを計算すると、中間値が非常に大きくなる場合があります。2つの大きな数値を除算すると、数値的に不安定になる可能性があります。これらのメモ(スタンフォードから)は、本質的にあなたがやっていることである正規化のトリックに言及しています。


3
壊滅的なキャンセルの影響を過小評価することはできません。
Cesar

24

sklearnはsoftmaxの実装も提供しています

from sklearn.utils.extmath import softmax
import numpy as np

x = np.array([[ 0.50839931,  0.49767588,  0.51260159]])
softmax(x)

# output
array([[ 0.3340521 ,  0.33048906,  0.33545884]]) 

3
これは具体的な質問にどのように正確に答えますか?これは実装自体に関するものであり、一部のサードパーティライブラリの可用性に関するものではありませんか?
砂漠の飛行士

8
両方のアプローチの結果を検証するためのサードパーティの実装を探していました。これは、このコメントが役立つ方法です。
Eugenio F. Martinez Pacheco

13

数学的な観点からは、両側は等しい。

そして、あなたは簡単にこれを証明することができます。しましょうm=max(x)。ここで、関数softmaxはi番目の座標が等しいベクトルを返します

ここに画像の説明を入力してください

これはすべてのために働くことを予告m全て(複雑な)番号のため、e^m != 0

  • 計算の複雑さの観点からは、これらも同等であり、どちらもO(n)時間内に実行されnます。ここで、はベクトルのサイズです。

  • 数値の安定性の観点からは、最初の解決策が推奨されます。これe^xは、非常に速く成長し、かなり小さい値でxもオーバーフローするためです。最大値を引くと、このオーバーフローを取り除くことができます。私が話していたことを実際に体験するにはx = np.array([1000, 5])、両方の機能をフィードしてみてください。1つは正しい確率を返し、2つ目はオーバーフローしますnan

  • あなたのソリューションはベクトルに対してのみ機能します(Udacityクイズでは、行列についても計算する必要があります)。それを修正するには、使用する必要がありますsum(axis=0)


1
ベクトルではなく行列でソフトマックスを計算できると便利な場合は?つまり、どのモデルの出力行列ですか?それはさらに次元化できますか?
mrgloom

2
「数値安定性の観点から、2番目のソリューションが優先される...」の最初のソリューションを意味しますか?
Dataman、2018年

10

編集。バージョン1.2.0以降、scipyには特別な機能としてsoftmaxが含まれています。

https://scipy.github.io/devdocs/generated/scipy.special.softmax.html

私は任意の軸にソフトマックスを適用する関数を書きました:

def softmax(X, theta = 1.0, axis = None):
    """
    Compute the softmax of each element along an axis of X.

    Parameters
    ----------
    X: ND-Array. Probably should be floats. 
    theta (optional): float parameter, used as a multiplier
        prior to exponentiation. Default = 1.0
    axis (optional): axis to compute values along. Default is the 
        first non-singleton axis.

    Returns an array the same size as X. The result will sum to 1
    along the specified axis.
    """

    # make X at least 2d
    y = np.atleast_2d(X)

    # find axis
    if axis is None:
        axis = next(j[0] for j in enumerate(y.shape) if j[1] > 1)

    # multiply y against the theta parameter, 
    y = y * float(theta)

    # subtract the max for numerical stability
    y = y - np.expand_dims(np.max(y, axis = axis), axis)

    # exponentiate y
    y = np.exp(y)

    # take the sum along the specified axis
    ax_sum = np.expand_dims(np.sum(y, axis = axis), axis)

    # finally: divide elementwise
    p = y / ax_sum

    # flatten if X was 1D
    if len(X.shape) == 1: p = p.flatten()

    return p

他のユーザーが説明したように、最大​​値を引くことは良い習慣です。私はそれについての詳細な投稿をここに書きました。


9

ここでは、彼らが使用した理由を見つけることができます- max

そこから:

「実際にSoftmax関数を計算するためのコードを記述している場合、指数のために中間項が非常に大きくなる可能性があります。大きな数を除算すると数値的に不安定になる可能性があるため、正規化の手法を使用することが重要です。」



4

代替のソリューションを提供するにexp(x)は、アンダーフロー(負の場合)またはオーバーフロー(正の場合)になるような引数の大きさが非常に大きい場合を検討してください。ここでは、可能な限りログスペースにとどまり、結果が正常に動作することを信頼できる最後にのみ累乗する必要があります。

import scipy.special as sc
import numpy as np

def softmax(x: np.ndarray) -> np.ndarray:
    return np.exp(x - sc.logsumexp(x))

投稿者コードと同じにするためにaxis=0、引数としてをに追加する必要がありますlogsumexp
ビョルンLindqvist

あるいは、logsumexpに渡す追加の引数をアンパックすることもできます。
PikalaxALT

3

Tensorflowからの密な層の出力と互換性のあるものが必要でした。

データのバッチがあるため、@ desertnautのソリューションはこの場合機能しません。したがって、私は両方のケースで機能する別のソリューションを用意しました:

def softmax(x, axis=-1):
    e_x = np.exp(x - np.max(x)) # same code
    return e_x / e_x.sum(axis=axis, keepdims=True)

結果:

logits = np.asarray([
    [-0.0052024,  -0.00770216,  0.01360943, -0.008921], # 1
    [-0.0052024,  -0.00770216,  0.01360943, -0.008921]  # 2
])

print(softmax(logits))

#[[0.2492037  0.24858153 0.25393605 0.24827873]
# [0.2492037  0.24858153 0.25393605 0.24827873]]

参照:Tensorflow softmax


回答は質問で説明されている非常に具体的な設定を指すことに注意してください。「どのような状況下でも、またはお好みのデータ形式で一般に
ソフトマックス

質問は「Udacityのディープラーニングクラス」に関するもので、Tensorflowを使用してモデルを構築している場合は機能しないため、ここに入れました。あなたのソリューションはクールでクリーンですが、非常に特定のシナリオでのみ機能します。とにかくありがとう。
Lucas Casagrande


1

数値の安定性を維持するには、max(x)を差し引く必要があります。以下は、softmax関数のコードです。

def softmax(x):

if len(x.shape) > 1:
    tmp = np.max(x, axis = 1)
    x -= tmp.reshape((x.shape[0], 1))
    x = np.exp(x)
    tmp = np.sum(x, axis = 1)
    x /= tmp.reshape((x.shape[0], 1))
else:
    tmp = np.max(x)
    x -= tmp
    x = np.exp(x)
    tmp = np.sum(x)
    x /= tmp


return x

1

上記の回答ですでに詳細に回答しています。maxオーバーフローを避けるために差し引かれます。ここにpython3の実装をもう1つ追加します。

import numpy as np
def softmax(x):
    mx = np.amax(x,axis=1,keepdims = True)
    x_exp = np.exp(x - mx)
    x_sum = np.sum(x_exp, axis = 1, keepdims = True)
    res = x_exp / x_sum
    return res

x = np.array([[3,2,4],[4,5,6]])
print(softmax(x))

1

誰もが彼らの解決策を投稿しているようですので、私が投稿します:

def softmax(x):
    e_x = np.exp(x.T - np.max(x, axis = -1))
    return (e_x / e_x.sum(axis=0)).T

sklearnからインポートしたものとまったく同じ結果が得られます。

from sklearn.utils.extmath import softmax

1
import tensorflow as tf
import numpy as np

def softmax(x):
    return (np.exp(x).T / np.exp(x).sum(axis=-1)).T

logits = np.array([[1, 2, 3], [3, 10, 1], [1, 2, 5], [4, 6.5, 1.2], [3, 6, 1]])

sess = tf.Session()
print(softmax(logits))
print(sess.run(tf.nn.softmax(logits)))
sess.close()

SOへようこそ。コードが質問にどのように答えるかの説明は常に役立ちます。
Nick

1

すべての回答とCS231nのメモに基づいて、要約させてください。

def softmax(x, axis):
    x -= np.max(x, axis=axis, keepdims=True)
    return np.exp(x) / np.exp(x).sum(axis=axis, keepdims=True)

使用法:

x = np.array([[1, 0, 2,-1],
              [2, 4, 6, 8], 
              [3, 2, 1, 0]])
softmax(x, axis=1).round(2)

出力:

array([[0.24, 0.09, 0.64, 0.03],
       [0.  , 0.02, 0.12, 0.86],
       [0.64, 0.24, 0.09, 0.03]])

0

問題の理解をもう少し補足したいと思います。ここでは、配列の最大値を差し引くのが正しいです。しかし、他の投稿でコードを実行すると、配列が2次元以上の場合、正しい答えが得られないことがわかります。

ここに私はあなたにいくつかの提案をします:

  1. 最大値を取得するには、x軸に沿ってそれを実行すると、1D配列が取得されます。
  2. max配列を元の形状に再形成します。
  3. np.expを実行して指数値を取得します。
  4. 軸に沿ってnp.sumを実行します。
  5. 最終結果を取得します。

結果に従って、ベクトル化を行うと正しい答えが得られます。大学の宿題に関係しているので、正確なコードをここに掲載することはできません。


1
これは、大学の宿題とは関係ありません。次のステップで正解が提供される、認定されていないコースでの段階的でないクイズにのみ関係します...
砂漠の飛行士、

0

softmax関数の目的は、値が飽和する(つまり、+ /-1(tanh)または0から1(logistical)の傾向がある)ときにエンドポイントをS字型に押しつぶすのではなく、ベクトルの比率を維持することです。これは、エンドポイントでの変化率に関するより多くの情報を保持するため、Nの1の出力エンコーディングを使用するニューラルネットに適用できるためです(つまり、エンドポイントを押しつぶすと、1を区別するのが難しくなります。 -Nの出力クラスは、それらが押しつぶされたために「最大」または「最小」のどちらであるかを判別できないためです。); また、合計出力の合計が1になり、明確な勝者は1に近く、他の数値が互いに近い場合は合計が1 / pになります。ここで、pは同様の値を持つ出力ニューロンの数です。

ベクトルから最大値を減算する目的は、e ^ y指数を実行すると、フロートを最大値でクリップしてタイにつながる非常に高い値を取得する可能性があることです。この例ではそうではありません。最大値を減算して負の数値を作成すると、これは大きな問題となり、比率を変更して値を急速に縮小する負の指数があります。これは、投稿者の質問で発生し、誤った回答が得られたものです。

Udacityによって提供される答えは恐ろしく非効率的です。最初に行う必要があるのは、すべてのベクトルコンポーネントのe ^ y_jを計算し、KEEP THOSE VALUESを計算してから、それらを合計して除算することです。Udacityがめちゃくちゃになっているのは、e ^ y_j TWICEの計算です!!! 正解は次のとおりです。

def softmax(y):
    e_to_the_y_j = np.exp(y)
    return e_to_the_y_j / np.sum(e_to_the_y_j, axis=0)

0

目標は、NumpyとTensorflowを使用して同様の結果を達成することでした。元の回答からの唯一の変更はaxisnp.sumapiのパラメーターです。

初期のアプローチaxis=0-ただし、これは次元がNの場合、意図した結果を提供しません。

変更されたアプローチaxis=len(e_x.shape)-1-常に最後の次元で合計します。これは、テンソルフローのソフトマックス関数と同様の結果を提供します。

def softmax_fn(input_array):
    """
    | **@author**: Prathyush SP
    |
    | Calculate Softmax for a given array
    :param input_array: Input Array
    :return: Softmax Score
    """
    e_x = np.exp(input_array - np.max(input_array))
    return e_x / e_x.sum(axis=len(e_x.shape)-1)

0

ここでは、テンソルフローとscipyの正確さのためにnumpyと比較を使用した一般化されたソリューションを示します。

データの準備:

import numpy as np

np.random.seed(2019)

batch_size = 1
n_items = 3
n_classes = 2
logits_np = np.random.rand(batch_size,n_items,n_classes).astype(np.float32)
print('logits_np.shape', logits_np.shape)
print('logits_np:')
print(logits_np)

出力:

logits_np.shape (1, 3, 2)
logits_np:
[[[0.9034822  0.3930805 ]
  [0.62397    0.6378774 ]
  [0.88049906 0.299172  ]]]

tensorflowを使用したSoftmax:

import tensorflow as tf

logits_tf = tf.convert_to_tensor(logits_np, np.float32)
scores_tf = tf.nn.softmax(logits_np, axis=-1)

print('logits_tf.shape', logits_tf.shape)
print('scores_tf.shape', scores_tf.shape)

with tf.Session() as sess:
    scores_np = sess.run(scores_tf)

print('scores_np.shape', scores_np.shape)
print('scores_np:')
print(scores_np)

print('np.sum(scores_np, axis=-1).shape', np.sum(scores_np,axis=-1).shape)
print('np.sum(scores_np, axis=-1):')
print(np.sum(scores_np, axis=-1))

出力:

logits_tf.shape (1, 3, 2)
scores_tf.shape (1, 3, 2)
scores_np.shape (1, 3, 2)
scores_np:
[[[0.62490064 0.37509936]
  [0.4965232  0.5034768 ]
  [0.64137274 0.3586273 ]]]
np.sum(scores_np, axis=-1).shape (1, 3)
np.sum(scores_np, axis=-1):
[[1. 1. 1.]]

scipyを使用したSoftmax:

from scipy.special import softmax

scores_np = softmax(logits_np, axis=-1)

print('scores_np.shape', scores_np.shape)
print('scores_np:')
print(scores_np)

print('np.sum(scores_np, axis=-1).shape', np.sum(scores_np, axis=-1).shape)
print('np.sum(scores_np, axis=-1):')
print(np.sum(scores_np, axis=-1))

出力:

scores_np.shape (1, 3, 2)
scores_np:
[[[0.62490064 0.37509936]
  [0.4965232  0.5034768 ]
  [0.6413727  0.35862732]]]
np.sum(scores_np, axis=-1).shape (1, 3)
np.sum(scores_np, axis=-1):
[[1. 1. 1.]]

numpyを使用したSoftmax(https://nolanbconaway.github.io/blog/2017/softmax-numpy):

def softmax(X, theta = 1.0, axis = None):
    """
    Compute the softmax of each element along an axis of X.

    Parameters
    ----------
    X: ND-Array. Probably should be floats.
    theta (optional): float parameter, used as a multiplier
        prior to exponentiation. Default = 1.0
    axis (optional): axis to compute values along. Default is the
        first non-singleton axis.

    Returns an array the same size as X. The result will sum to 1
    along the specified axis.
    """

    # make X at least 2d
    y = np.atleast_2d(X)

    # find axis
    if axis is None:
        axis = next(j[0] for j in enumerate(y.shape) if j[1] > 1)

    # multiply y against the theta parameter,
    y = y * float(theta)

    # subtract the max for numerical stability
    y = y - np.expand_dims(np.max(y, axis = axis), axis)

    # exponentiate y
    y = np.exp(y)

    # take the sum along the specified axis
    ax_sum = np.expand_dims(np.sum(y, axis = axis), axis)

    # finally: divide elementwise
    p = y / ax_sum

    # flatten if X was 1D
    if len(X.shape) == 1: p = p.flatten()

    return p


scores_np = softmax(logits_np, axis=-1)

print('scores_np.shape', scores_np.shape)
print('scores_np:')
print(scores_np)

print('np.sum(scores_np, axis=-1).shape', np.sum(scores_np, axis=-1).shape)
print('np.sum(scores_np, axis=-1):')
print(np.sum(scores_np, axis=-1))

出力:

scores_np.shape (1, 3, 2)
scores_np:
[[[0.62490064 0.37509936]
  [0.49652317 0.5034768 ]
  [0.64137274 0.3586273 ]]]
np.sum(scores_np, axis=-1).shape (1, 3)
np.sum(scores_np, axis=-1):
[[1. 1. 1.]]

0

softmax関数は、数値を1に合計する確率に変換するアクティブ化関数です。関数softmaxは、結果のリストの確率分布を表すベクトルを出力します。また、ディープラーニング分類タスクで使用されるコア要素でもあります。

Softmax関数は、複数のクラスがある場合に使用されます。

最大のクラスを見つけるのに役立ちます。確率。

Softmax関数は、各入力のクラスを定義する確率を実際に取得しようとしている出力層で理想的に使用されます。

範囲は0〜1です。

Softmax関数は、ロジット[2.0、1.0、0.1]を確率[0.7、0.2、0.1]に変換し、確率の合計を1にします。ロジットは、ニューラルネットワークの最後の層によって出力された生のスコアです。アクティベーションが行われる前。softmax関数を理解するには、(n-1)番目の層の出力を調べる必要があります。

softmax関数は、実際にはarg max関数です。つまり、入力から最大値を返すのではなく、最大値の位置を返します。

例えば:

ソフトマックスの前

X = [13, 31, 5]

ソフトマックス後

array([1.52299795e-08, 9.99999985e-01, 5.10908895e-12]

コード:

import numpy as np

# your solution:

def your_softmax(x): 

"""Compute softmax values for each sets of scores in x.""" 

e_x = np.exp(x - np.max(x)) 

return e_x / e_x.sum() 

# correct solution: 

def softmax(x): 

"""Compute softmax values for each sets of scores in x.""" 

e_x = np.exp(x - np.max(x)) 

return e_x / e_x.sum(axis=0) 

# only difference
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.