不均衡データのTensorflow Adjusting Cost Function


12

非常に不均衡なデータの分類問題があります。過剰サンプリングと過少サンプリング、および過小評価されているカテゴリカル出力のコストを変更すると、より適切なフィッティングにつながることを読んだことがあります。これが行われる前は、テンソルフローは各入力を大多数のグループとして分類します(そして、90%を超える精度、つまり、意味がありません)。

各グループの逆パーセンテージの対数が、私が試した中で最高の乗数になったことに気づきました。コスト関数のより標準的な操作はありますか?これは正しく実装されていますか?

from collections import Counter
counts = Counter(category_train)
weightsArray =[]
for i in range(n_classes):
    weightsArray.append(math.log(category_train.shape[0]/max(counts[i],1))+1)

class_weight = tf.constant(weightsArray)
weighted_logits = tf.mul(pred, class_weight)
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(weighted_logits, y))
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)

損失関数の重みをどのように理想的に選択するかについて、科学的なリファレンスはありますか?私はあなたを信じていないわけではありませんが、あなたは他の誰かから非常に刺激を受けたと思いましたか?
Gerhard Hagerer 2017

そしてdavidparks21がすでに尋ねたように、あなたのアプローチの結果は非常に興味深いでしょう:)。
Gerhard Hagerer 2017

回答:


4

これは損失関数の良い解決策のようです。私は最近同様のアプローチで成功しましたが、で乗算する場所を並べ替えたいと思いますclass_weight

論理的に考えるclass_weightと、は出力に対して定数になるため、コスト関数に適用されているのと同じ方法で運ばれ、勾配に適用されます。ただし、問題が1つあります。

あなたがそれを持っている方法、それclass_weightは予測値に影響を与えます。ただし、グラデーションのスケールに影響を与える必要があります。私が間違っていなければ、操作の順序を逆にしたいと思うでしょう:

# Take the cost like normal
error = tf.nn.softmax_cross_entropy_with_logits(pred, y)

# Scale the cost by the class weights
scaled_error = tf.mul(error, class_weight)

# Reduce
cost = tf.reduce_mean(scaled_error)

典型的ではない、十分に表現されていないクラスを単にオーバーサンプリングするのと比較して、これがどのように機能するかを知りたいと思います。ですから、洞察を得たら、それについて投稿してください!:)

興味深いことに、私は最近、別の問題領域で非常によく似た手法を使用して成功しました(その結果、この投稿に移動しました)。

マルチタスク学習、特定のサンプルを「無視」する損失関数を見つける


2

チェックアウトtf.nn.weighted_cross_entropy_with_logits()

加重クロスエントロピーを計算します。

これは、pos_weightが、負のエラーと比較して正のエラーのコストをアップまたはダウンウェイトすることによって再現率と精度をトレードオフできることを除いて、sigmoid_cross_entropy_with_logits()に似ています。

これにより、必要な操作を実行できます。


0

私は2つの異なる実装があります:

  1. ロジット付きの「通常の」ソフトマックス: tf.nn.softmax_cross_entropy_with_logits

class_weightは、evereyバッチ反復で入力するプレースホルダーです。

self.class_weight  = tf.placeholder(tf.float32, shape=self.batch_size,self._num_classes], name='class_weight')    
self._final_output = tf.matmul(self._states,self._weights["linear_layer"]) + self._biases["linear_layer"] 
self.scaled_logits = tf.multiply(self._final_output, self.class_weight)
self.softmax = tf.nn.softmax_cross_entropy_with_logits(logits=self.scaled_logits,labels= self._labels)
  1. tf.nn.softmax_cross_entropy_with_logits

実装されているテンソルフロー関数を使用しているが、バッチの重みを計算する必要がある場合。ドキュメントはそれについて少し混乱しています。tf.gatherなどでこれを行うには2つの方法があります。

self.scaled_class_weights=tf.reduce_sum(tf.multiply(self._labels,self.class_weight),1)
self.softmax = tf.losses.softmax_cross_entropy(logits=self._final_output,
                                                   onehot_labels=self._labels,weights=self.scaled_class_weights)

ここでそれについていい議論があります

最後に、どの実装にも永続的に結婚したくなかったので、少しtf.caseを追加して、使用したい戦略をトレーニング時間に渡しました。

self.sensitive_learning_strategy = tf.placeholder(tf.int32 , name='sensitive_learning_strategy')
self.softmax =tf.case([
            (tf.equal(self.sensitive_learning_strategy, 0), lambda: self.softmax_0),
            (tf.equal(self.sensitive_learning_strategy, 1), lambda: self.softmax_1),
            (tf.equal(self.sensitive_learning_strategy, 2), lambda: self.softmax_2)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.