Tensorflow Коригування функції витрат для незбалансованих даних


12

У мене є проблема класифікації сильно незбалансованих даних. Я читав, що надмірне зменшення розміру, а також зміна вартості для недостатньо представлених категоричних результатів призведе до кращого пристосування. Перш ніж це зробити, tensorflow би класифікував кожну інформацію як групу більшості (і набирав би точність понад 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воля буде постійною wrt результатом, тому вона буде переноситися і застосовуватися до градієнта так само, як це застосовується до функції витрат. Однак є одна проблема.

Як ви це зробите, це 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 (), за винятком того, що ця вага має позицію, дозволяє торгувати відкликанням та точністю шляхом збільшення або зменшення ваги вартості позитивної помилки щодо негативної помилки.

Це повинно дозволяти вам робити те, що ви хочете.


0

У мене є дві різні реалізації:

  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

Де я використовую реалізовану функцію tensorflow, але мені потрібно обчислити ваги для партії. Документи з цим трохи заплутані. Є два способи зробити це за допомогою 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.