web-dev-qa-db-ja.com

テンソル流におけるクロスエントロピー損失の選び方

ロジスティック回帰や多項ロジスティック回帰などの分類問題は、クロスエントロピーの損失を最適化します。通常、クロスエントロピー層は確率分布を生成するsoftmax層に従います。

テンソルフローでは、少なくとも1つのダースの異なるクロスエントロピー損失関数があります。

  • tf.losses.softmax_cross_entropy
  • tf.losses.sparse_softmax_cross_entropy
  • tf.losses.sigmoid_cross_entropy
  • tf.contrib.losses.softmax_cross_entropy
  • tf.contrib.losses.sigmoid_cross_entropy
  • tf.nn.softmax_cross_entropy_with_logits
  • tf.nn.sigmoid_cross_entropy_with_logits
  • ...

二項分類にのみ有効で、多クラス問題に適しているものはどれですか。 sigmoidの代わりにsoftmaxをいつ使用すべきですか。 sparseの関数は他の関数とどう違うのですか、そしてなぜそれがsoftmaxだけなのですか?

関連する(より数学指向の)議論: クロスエントロピージャングル

57
Maxim

予備的事実

  • 機能的には、クラス数が2の場合、 シグモイドはsoftmax関数の部分的な場合 になります。両方とも同じ操作を行います。ロジット(下記参照)を確率に変換します。

    単純なバイナリ分類では、両者の間に大きな違いはありませんが、多項式分類の場合、sigmoidは非排他的ラベル(別名multi-labels)を扱うことができますが、softmaxは排他クラスを扱います(下記参照)。

  • 確率を計算する前のlogit(スコアとも呼ばれる)は、 クラスに関連付けられた未調整のスケールなしの値 です。ニューラルネットワークアーキテクチャの観点からは、これはロジットが密(完全に接続された)レイヤの出力であることを意味します。

    Tensorflowの命名は少々奇妙です。以下の関数はすべて、確率ではなくロジットを受け入れ、変換自体を適用します(これは単により効率的です)。

シグモイド関数ファミリー

前述のように、sigmoidの損失関数はバイナリ分類用です。しかし、テンソルフロー関数はより一般的であり、クラスが独立している場合はマルチラベル分類を行うことができます。つまり、tf.nn.sigmoid_cross_entropy_with_logitsNのバイナリ分類を一度に解決します。

ラベルはワンホットエンコードされているか、ソフトクラス確率を含むことができます。

さらにtf.losses.sigmoid_cross_entropyバッチ内ウェイトを設定することを可能にします。すなわち、いくつかの例を他の例より重要にします。 tf.nn.weighted_cross_entropy_with_logitsは、クラスの重み(分類はバイナリです)を設定することを可能にします。すなわち、正の誤差を負の誤差より大きくします。これは、トレーニングデータが不均衡な場合に役立ちます。

Softmax機能ファミリー

これらの損失関数は、多項式の相互に排他的な分類、すなわちNクラスから1つを選ぶために使用されるべきです。 N = 2の場合にも適用可能です。

ラベルはワンホット符号化されるか、ソフトクラス確率を含むことができます。特定の例は、50%の確率でクラスAと50%の確率でクラスBに属することができます。厳密に言えば、それが両方のクラスに属するという意味ではありませんが、確率をこのように解釈することができます。

sigmoidファミリと同様に、tf.losses.softmax_cross_entropyではバッチ内の重みを設定できます。つまり、いくつかの例を他の例よりも重要にすることができます。私の知る限りでは、tensorflow 1.3以降では、class weightsを設定するための組み込みの方法はありません。

[UPD]tensorflow 1.5では、v2 version 導入された と元のsoftmax_cross_entropy_with_logitsの損失は廃止予定となりました。唯一の違いは、新しいバージョンでは逆伝播がロジットとラベルの両方に発生するということです( これは議論の場です なぜこれが便利かもしれません)。

スパース関数ファミリー

上記の通常のsoftmaxと同様に、これらの損失関数は多項式の相互に排他的な分類、すなわちNクラスから1つを選ぶために使用されるべきです。違いはラベルのエンコーディングにあります。クラスはワンホットベクトルではなく整数(クラスインデックス)として指定されます。明らかに、これはソフトなクラスを許可しませんが、何千あるいは何百万ものクラスがあるときそれはいくらかのメモリを節約することができます。ただし、logits引数には各クラスごとにロジットを含める必要があるため、少なくとも[batch_size, classes]メモリを消費します。

上記のように、tf.lossesバージョンには、バッチ内の重みを設定することができるweights引数があります。

サンプルソフトマックス関数ファミリ

これらの関数は膨大な数のクラスを扱うためのもう一つの選択肢を提供します。正確な確率分布を計算して比較する代わりに、無作為標本から損失推定値を計算します。

引数weightsおよびbiasesは、選択されたサンプルのロジットを計算するために使用される独立した完全接続層を指定します。

上記のように、labelsはワンホットエンコードされていませんが、[batch_size, num_true]という形をしています。

サンプル関数はトレーニングにのみ適しています。テスト時には、実際の分布を得るために標準的なsoftmaxの損失(スパースまたはワンホット)を使用することをお勧めします。

もう1つの代替的な損失はtf.nn.nce_lossで、これはノイズ対比推定を実行します(興味がある場合は、これを参照してください 非常に詳細な説明 )。 NCEはsoftmaxの近似を極限で保証するため、私はこの機能をsoftmaxファミリに含めました。

106
Maxim

しかし、バージョン1.5では、次のように引数をsoftmax_cross_entropy_with_logits_v2で使用しながら、代わりにargument key=...を使用する必要があります>

softmax_cross_entropy_with_logits_v2(_sentinel=None, labels=y,\
logits = my_prediction, dim=-1, name=None)
5
Hamidreza