web-dev-qa-db-ja.com

不均衡なデータと加重クロスエントロピー

不均衡なデータでネットワークをトレーニングしようとしています。 A(198個のサンプル)、B(436個のサンプル)、C(710個のサンプル)、D(272個のサンプル)があり、「weighted_cross_entropy_with_logits」について読みましたが、見つかったすべての例はバイナリ分類のためです。これらの重みの設定方法に自信があります。

合計サンプル:1616

A_weight:198/1616 = 0.12?

私が理解していれば、背後にある考え方は、市長クラスのエラーにペナルティを科し、少数派のヒットをより積極的に評価することですよね?

私のコード:

weights = tf.constant([0.12, 0.26, 0.43, 0.17])
cost = tf.reduce_mean(tf.nn.weighted_cross_entropy_with_logits(logits=pred, targets=y, pos_weight=weights))

私は this one を読みましたが、他の例ではバイナリ分類をしていますが、まだあまり明確ではありません。

前もって感謝します。

43
Sergiodiaz53

weighted_cross_entropy_with_logitssigmoid_cross_entropy_with_logitsの重み付きバリアントであることに注意してください。シグモイドクロスエントロピーは、通常、バイナリ分類に使用されます。はい、複数のラベルを処理できますが、シグモイドクロスエントロピーは基本的に各ラベルに対して(バイナリ)決定を行います。たとえば、顔認識ネットの場合、(相互に排他的ではない)ラベルは「Does the被験者は眼鏡をかけますか? "、" 被験者は女性ですか? "など.

バイナリ分類では、各出力チャネルはバイナリ(ソフト)決定に対応します。したがって、損失の計算内で重み付けを行う必要があります。これは、クロスエントロピーの1つの項に他の項を重み付けすることにより、weighted_cross_entropy_with_logitsが行うことです。

相互に排他的なマルチラベル分類では、softmax_cross_entropy_with_logitsを使用します。これは動作が異なります。各出力チャネルはクラス候補のスコアに対応します。決定はafterで、各チャネルのそれぞれの出力を比較します。

したがって、最終決定の前に加重することは、通常、加重を掛けることにより、スコアを比較する前にスコアを修正するという単純な問題です。たとえば、三項分類タスクの場合、

# your class weights
class_weights = tf.constant([[1.0, 2.0, 3.0]])
# deduce weights for batch samples based on their true label
weights = tf.reduce_sum(class_weights * onehot_labels, axis=1)
# compute your (unweighted) softmax cross entropy loss
unweighted_losses = tf.nn.softmax_cross_entropy_with_logits(onehot_labels, logits)
# apply the weights, relying on broadcasting of the multiplication
weighted_losses = unweighted_losses * weights
# reduce the result to get your final loss
loss = tf.reduce_mean(weighted_losses)

tf.losses.softmax_cross_entropyを使用して、最後の3つのステップを処理することもできます。

あなたの場合、データの不均衡に取り組む必要がある場合、クラスの重みは実際に列車データの頻度に反比例する可能性があります。合計が1つまたはクラスの数になるように正規化することも理にかなっています。

上記では、サンプルの真のラベルに基づいて損失にペナルティを課していることに注意してください。また、単に定義するだけで推定ラベルに基づいて損失をペナルティにすることもできます。

weights = class_weights

そして、残りのコードは、ブロードキャストマジックのおかげで変更する必要はありません。

一般的な場合、エラーの種類に応じた重みが必要になります。つまり、ラベルXYの各ペアに対して、真のラベルがXである場合に、ラベルYを選択した場合のペナルティ方法を選択できます。最終的な重み行列全体になり、上記のweightsが完全な(num_samples, num_classes)テンソルになります。これはあなたが望むものを少し超えていますが、それでも、重みテンソルの定義だけを上記のコードで変更する必要があることを知っておくと便利かもしれません。

65
P-Gn

Sparse_softmax_cross_entropyで機能する代替ソリューションについては、 この回答 を参照してください。

import  tensorflow as tf
import numpy as np

np.random.seed(123)
sess = tf.InteractiveSession()

# let's say we have the logits and labels of a batch of size 6 with 5 classes
logits = tf.constant(np.random.randint(0, 10, 30).reshape(6, 5), dtype=tf.float32)
labels = tf.constant(np.random.randint(0, 5, 6), dtype=tf.int32)

# specify some class weightings
class_weights = tf.constant([0.3, 0.1, 0.2, 0.3, 0.1])

# specify the weights for each sample in the batch (without having to compute the onehot label matrix)
weights = tf.gather(class_weights, labels)

# compute the loss
tf.losses.sparse_softmax_cross_entropy(labels, logits, weights).eval()
0
DankMasterDan