数据不平衡的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)

你们对于理想地选择损失函数权重的方法有任何科学参考吗?不是说我不相信你,而是我觉得你受到别人的启发吗?
Gerhard Hagerer '17

正如davidparks21已经问过的那样,您的方法的结果将非常有趣:)。
Gerhard Hagerer '17

Answers:


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)

与仅对代表性不足的类进行过度采样相比,我会非常感兴趣地知道它的性能,这是比较典型的。因此,如果您获得一些见解,请发表有关它的信息!:)

有趣的是,最近我在另一个问题域中成功使用了一种非常类似的技术(这使我进入了这篇文章):

多任务学习,找到“忽略”某些样本的损失函数



0

我有2种不同的实现:

  1. 带有logits的“常规” softmax: 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函数,但需要计算批次的权重。该文档对此有点困惑。有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)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.