Функция корректировки ценового потока для несбалансированных данных


12

У меня проблема классификации с сильно несбалансированными данными. Я прочитал, что снова и Undersampling, а также изменения стоимости на недостаточно категоричные результаты приведут к лучшей подгонке. До того, как это было сделано, тензорный поток классифицировал бы каждый вход как группу большинства (и получал бы точность более 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)

У вас, ребята, есть научный справочник о том, как вы в идеале выбираете веса для функции потерь? Не то чтобы я тебе не верил, но я думал, что ты очень вдохновлен кем-то другим?
Герхард Хагерер

И, как уже спросил davidparks21, результаты вашего подхода были бы очень интересными :).
Герхард Хагерер

Ответы:


4

Это похоже на хорошее решение для функции потерь. Недавно у меня был успех с подобным подходом, но я думаю, что вы хотите изменить порядок, где вы умножаете в class_weight.

Размышляя об этом логически, class_weightон будет постоянным по отношению к выходным данным, поэтому он будет переноситься и применяться к градиенту таким же образом, как он применяется к функции стоимости. Хотя есть одна проблема.

То, как вы это сделаете, 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():

Вычисляет взвешенную перекрестную энтропию.

Это похоже на sigmoid_cross_entropy_with_logits (), за исключением того, что pos_weight позволяет компенсировать отзыв и точность путем увеличения или уменьшения стоимости положительной ошибки по сравнению с отрицательной ошибкой.

Это должно позволить вам делать то, что вы хотите.


0

У меня есть 2 разные реализации:

  1. с «обычным» softmax с логитами: tf.nn.softmax_cross_entropy_with_logits

Где class_weight - это заполнитель, который я заполняю при каждой итерации пакета.

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

Где я использую реализованную функцию тензорного потока, но мне нужно вычислить весовые коэффициенты для партии. Документы немного сбивают с толку. Есть 2 способа сделать это с помощью tf.gather или вот так:

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)
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.