私はtensorflow APIドキュメント ここ を見ていました。テンソルフロードキュメントでは、彼らはlogits
と呼ばれるキーワードを使いました。それは何ですか? APIドキュメントの多くのメソッドでは、次のように書かれています。
tf.nn.softmax(logits, name=None)
書かれているのがlogits
がTensors
のみであるとしたら、どうしてlogits
のような別の名前をつけるのでしょうか。
もう1つのことは、区別できない2つの方法があるということです。彼らはいた
tf.nn.softmax(logits, name=None)
tf.nn.softmax_cross_entropy_with_logits(logits, labels, name=None)
それらの違いは何ですか?文書は私には明確ではありません。私はtf.nn.softmax
が何をするのか知っています。しかし他ではありません。例は本当に役に立ちます。
Logitsは、関数が以前のレイヤーのスケーリングされていない出力で動作し、単位を理解するための相対的なスケールが線形であることを意味します。特に、入力の合計が1に等しくない可能性があることを意味します。つまり、値はnot確率です(5の入力がある可能性があります)。
tf.nn.softmax
は、入力テンソルに softmax関数 を適用した結果のみを生成します。 softmaxは、入力を「スキッシュ」し、sum(input) = 1
:正規化する方法です。 softmaxの出力の形状は入力と同じです。値を正規化するだけです。 softmaxの出力は確率として解釈できます。
a = tf.constant(np.array([[.1, .3, .5, .9]]))
print s.run(tf.nn.softmax(a))
[[ 0.16838508 0.205666 0.25120102 0.37474789]]
対照的に、tf.nn.softmax_cross_entropy_with_logits
は、softmax関数を適用した後、結果のクロスエントロピーを計算します(ただし、数学的に注意深い方法ですべてを一緒に行います)。次の結果に似ています。
sm = tf.nn.softmax(x)
ce = cross_entropy(sm)
クロスエントロピーは要約指標であり、要素全体で合計します。形状tf.nn.softmax_cross_entropy_with_logits
テンソル上の[2,5]
の出力は、形状[2,1]
です(最初の次元はバッチとして扱われます)。
クロスエントロピーとを最小化する最適化を行いたい場合、最後のレイヤーの後にソフトマックスを使用する場合は、代わりにtf.nn.softmax_cross_entropy_with_logits
を使用する必要があります数値的に不安定なコーナーケースを数学的に正しい方法でカバーするためです。さもなければ、あちこちに小さなイプシロンを追加して、ハッキングすることになります。
Edited 2016-02-07:単一クラスのラベルがあり、オブジェクトが1つのクラスにのみ属することができる場合、tf.nn.sparse_softmax_cross_entropy_with_logits
を使用すると、ラベルを密なワンホット配列に変換する必要がなくなります。この関数は、リリース0.6.0の後に追加されました。
ショートバージョン:
テンソルが2つあるとします。ここで、y_hat
には各クラスの計算スコアが含まれ(たとえば、y = W * x + bから)、y_true
には、ホットエンコードされたtrueラベルが含まれます。
y_hat = ... # Predicted label, e.g. y = tf.matmul(X, W) + b
y_true = ... # True label, one-hot encoded
y_hat
のスコアを正規化されていない対数確率として解釈した場合、それらは logits になります。
さらに、総クロスエントロピー損失は次のように計算されます。
y_hat_softmax = tf.nn.softmax(y_hat)
total_loss = tf.reduce_mean(-tf.reduce_sum(y_true * tf.log(y_hat_softmax), [1]))
これは本質的に関数softmax_cross_entropy_with_logits()
で計算されたクロスエントロピー損失の合計と等価です。
total_loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y_hat, y_true))
ロングバージョン:
ニューラルネットワークの出力層では、おそらく計算y_hat = W*x + b
のように、各トレーニングインスタンスのクラススコアを含む配列を計算します。例として、以下では2行3列の配列としてy_hat
を作成しました。ここで、行はトレーニングインスタンスに対応し、列はクラスに対応します。したがって、ここでは2つのトレーニングインスタンスと3つのクラスがあります。
import tensorflow as tf
import numpy as np
sess = tf.Session()
# Create example y_hat.
y_hat = tf.convert_to_tensor(np.array([[0.5, 1.5, 0.1],[2.2, 1.3, 1.7]]))
sess.run(y_hat)
# array([[ 0.5, 1.5, 0.1],
# [ 2.2, 1.3, 1.7]])
値は正規化されていないことに注意してください(つまり、行は1にならない)。それらを正規化するために、ソフトマックス関数を適用することができ、それは入力を非正規化対数確率(別名 logits )として解釈し、正規化された線形確率を出力する。
y_hat_softmax = tf.nn.softmax(y_hat)
sess.run(y_hat_softmax)
# array([[ 0.227863 , 0.61939586, 0.15274114],
# [ 0.49674623, 0.20196195, 0.30129182]])
Softmaxの出力が言っていることを完全に理解することが重要です。以下に、上記の出力をより明確に表す表を示しました。例えば、訓練インスタンス1が「クラス2」である確率は0.619であることが分かる。各トレーニングインスタンスのクラス確率は正規化されているため、各行の合計は1.0です。
Pr(Class 1) Pr(Class 2) Pr(Class 3)
,--------------------------------------
Training instance 1 | 0.227863 | 0.61939586 | 0.15274114
Training instance 2 | 0.49674623 | 0.20196195 | 0.30129182
これで、各トレーニングインスタンスのクラス確率が得られました。各行のargmax()を使用して最終的な分類を生成できます。上記から、トレーニングインスタンス1は「クラス2」に属し、トレーニングインスタンス2は「クラス1」に属すると生成することができる。
これらの分類は正しいですか?私達は訓練セットからの本当のラベルに対して測定する必要があります。ここでも、行がトレーニングインスタンスで列がクラスである、ワンホットエンコードされたy_true
配列が必要になります。以下に、トレーニングインスタンス1の本当のラベルが「クラス2」で、トレーニングインスタンス2の本当のラベルが「クラス3」であるy_true
one-hot配列の例を作成しました。
y_true = tf.convert_to_tensor(np.array([[0.0, 1.0, 0.0],[0.0, 0.0, 1.0]]))
sess.run(y_true)
# array([[ 0., 1., 0.],
# [ 0., 0., 1.]])
y_hat_softmax
の確率分布はy_true
の確率分布に近いですか? クロスエントロピー損失 を使って誤差を測定することができます。
行ごとにクロスエントロピー損失を計算して結果を見ることができます。以下では、トレーニングインスタンス1の損失が0.479であり、トレーニングインスタンス2の損失が1.200と高いことがわかります。上記の例では、y_hat_softmax
は、トレーニングインスタンス1の最も高い確率が「クラス2」であることを示したため、これは理にかなっています。これは、y_true
のトレーニングインスタンス1と一致します。しかし、訓練インスタンス2の予測は、「クラス1」について最も高い確率を示し、これは真のクラス「クラス3」と一致しない。
loss_per_instance_1 = -tf.reduce_sum(y_true * tf.log(y_hat_softmax), reduction_indices=[1])
sess.run(loss_per_instance_1)
# array([ 0.4790107 , 1.19967598])
私たちが本当に望んでいるのは、すべてのトレーニングインスタンスにわたる総損失です。だから我々は計算することができます:
total_loss_1 = tf.reduce_mean(-tf.reduce_sum(y_true * tf.log(y_hat_softmax), reduction_indices=[1]))
sess.run(total_loss_1)
# 0.83934333897877944
softmax_cross_entropy_with_logits()を使用する
以下に示すように、代わりにtf.nn.softmax_cross_entropy_with_logits()
関数を使用して総クロスエントロピー損失を計算することができます。
loss_per_instance_2 = tf.nn.softmax_cross_entropy_with_logits(y_hat, y_true)
sess.run(loss_per_instance_2)
# array([ 0.4790107 , 1.19967598])
total_loss_2 = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y_hat, y_true))
sess.run(total_loss_2)
# 0.83934333897877922
total_loss_1
とtotal_loss_2
は基本的に同等の結果をもたらしますが、最後の桁に若干の違いがあります。ただし、2番目の方法を使用することもできます。softmaxはsoftmax_cross_entropy_with_logits()
の内部で実行されるため、1行少ないコードで、累積するエラーが少なくなります。
tf.nn.softmax
は、softmaxレイヤを介した順方向伝搬を計算します。モデルが出力する確率を計算するときに、モデルの 評価 の間にそれを使用します。
tf.nn.softmax_cross_entropy_with_logits
は、softmaxレイヤのコストを計算します。 training の間だけ使われます。
ロジットは 非正規化ログ確率 モデルを出力する(softmax正規化が適用される前に出力される値).
上記の回答には、質問に対する十分な説明があります。
それに加えて、Tensorflowは活性化関数を適用し、それ自身の活性化とそれに続く費用関数を使って費用を計算する操作を最適化しました。したがって、tf.nn.softmax_cross_entropy()
よりtf.nn.softmax(); tf.nn.cross_entropy()
を使うのは良い習慣です。
リソース集約型モデルでそれらの間の顕著な違いを見つけることができます。
softmax
に行くのはlogitです。これは、J。ヒントンがコースラの動画で常に繰り返していることです。