Tensorflow中对成本敏感的学习

时间:2016-09-20 21:08:08

标签: machine-learning tensorflow

我正在尝试在TensorFlow中设置一个对成本敏感的二进制分类学习,这会对误报和漏报进行不同的处罚。有没有人知道如何从一组惩罚权重$(w_1,w_2,w_3,w_4)$中创建一个损失函数(真阳性,假阳性,假阴性,真阴性)。

我查看了所提供的标准成本函数,但无法弄清楚如何将它们组合起来以获得与上述相似的内容。

3 个答案:

答案 0 :(得分:3)

我不知道有谁构建了成本敏感的神经网络分类器,但Alejandro Correa Bahnsen已发布cost sensitive logistic regressioncost sensitive decision trees的学术论文以及记录良好的python {{3} }。如果您熟悉scikit-learn,则CostCla非常易于使用。

您应该能够将库中的cost sensitive classification library named CostCla用于神经网络的Bayes minimum risk model,因为它符合成本模型,可以输出任何分类器的预测概率。

请注意,CostCla旨在为每个样本处理可能不同的成本。您为训练和测试样本提供成本矩阵。但是,如果适用于您的问题,您可以使成本矩阵中的所有行都相同。

以下是关于该主题的另外两篇学术论文:

答案 1 :(得分:2)

按照@Cauchyzhou的回答,如果您有logits,稀疏标签以及形状为[L,L](其中L是唯一标签的数量)的cost_matrix,则只需使用以下函数即可计算损失

curl -X PUT -L "http://mymuchlongerurl.com/hostedfile" --upload-file PUT.csv

答案 2 :(得分:0)

cost_matrix:

[[0,1,100],
[1,0,1],
[1,20,0]]

标签:

[1,2]

Y *:

[[0,1,0],
[0,0,1]]

Y(预测):

[[0.2,0.3,0.5],
[0.1,0.2,0.7]]

标签,cost_matrix - > cost_embedding:

[[1,0,1],
[1,20,0]]

显然[0.2,0.3,0.5]中的0.3表示[0,1,0]的正确标准,因此它不应该归于损失。

<0.1,0.2,0.7]中的0.7是相同的。换句话说,y *中值为1的pos不会导致丢失。

所以我有(1-y *):

[[1,0,1],
[1,1,0]]

然后熵是目标* log(预测)+(1目标)* log(1预测),y *中的值0,应该使用(1-target)* log(1-predict),所以我用(1-predict)说(1-y)

1-Y:

[[0.8,*0.7*,0.5],
[0.9,0.8,*0.3*]]

(斜体数字无用)

自定义损失

[[1,0,1], [1,20,0]]   *   log([[0.8,0.7,0.5],[0.9,0.8,0.3]])    *  
[[1,0,1],[1,1,0]]

你可以看到(1-y *)可以放在这里

所以损失是-tf.reduce_mean(cost_embedding * log(1-y)) ,为了使其适用,应该是:

-tf.reduce_mean(cost_embedding*log(tf.clip((1-y),1e-10)))

演示在下面

import tensorflow as tf
import numpy as np
hidden_units = 50
num_class = 3
class Model():
    def __init__(self,name_scope,is_custom):
        self.name_scope = name_scope
        self.is_custom = is_custom
        self.input_x = tf.placeholder(tf.float32,[None,hidden_units])
        self.input_y = tf.placeholder(tf.int32,[None])

        self.instantiate_weights()
        self.logits = self.inference()
        self.predictions = tf.argmax(self.logits,axis=1)
        self.losses,self.train_op = self.opitmizer()

    def instantiate_weights(self):
        with tf.variable_scope(self.name_scope + 'FC'):
            self.W = tf.get_variable('W',[hidden_units,num_class])
            self.b = tf.get_variable('b',[num_class])

            self.cost_matrix = tf.constant(
                np.array([[0,1,100],[1,0,100],[20,5,0]]),
                dtype = tf.float32
            )

    def inference(self):
        return tf.matmul(self.input_x,self.W) + self.b

    def opitmizer(self):
        if not self.is_custom:
            loss = tf.nn.sparse_softmax_cross_entropy_with_logits\
                (labels=self.input_y,logits=self.logits)
        else:
            batch_cost_matrix = tf.nn.embedding_lookup(
                self.cost_matrix,self.input_y
            )
            loss = - tf.log(1 - tf.nn.softmax(self.logits))\
                     * batch_cost_matrix

        train_op = tf.train.AdamOptimizer().minimize(loss)
        return loss,train_op

import random
batch_size = 128
norm_model = Model('norm',False)
custom_model = Model('cost',True)
split_point = int(0.9 * dataset_size)
train_set = datasets[:split_point]
test_set = datasets[split_point:]


with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    for i in range(100):
        batch_index = random.sample(range(split_point),batch_size)
        train_batch = train_set[batch_index]
        train_labels = lables[batch_index]
        _,eval_predict,eval_loss = sess.run([norm_model.train_op,
                  norm_model.predictions,norm_model.losses],
                  feed_dict={
                      norm_model.input_x:train_batch,
                      norm_model.input_y:train_labels
        })
        _,eval_predict1,eval_loss1 = sess.run([custom_model.train_op,
                  custom_model.predictions,custom_model.losses],
                  feed_dict={
                      custom_model.input_x:train_batch,
                      custom_model.input_y:train_labels
        })
        # print '默认',eval_predict,'\n自定义',eval_predict1
        print np.sum(((eval_predict == train_labels)==True).astype(np.int)),\
            np.sum(((eval_predict1 == train_labels)==True).astype(np.int))
        if i%10 == 0:
            print  '默认测试',sess.run(norm_model.predictions,
                  feed_dict={
                      norm_model.input_x:test_set,
                      norm_model.input_y:lables[split_point:]
        })
            print  '自定义测试',sess.run(custom_model.predictions,
                  feed_dict={
                      custom_model.input_x:test_set,
                      custom_model.input_y:lables[split_point:]
        })