35

文本数据组织为具有 20,000 个元素的向量,例如 [2, 1, 0, 0, 5, ...., 0]。第 i 个元素表示文本中第 i 个单词的频率。

地面实况标签数据也表示为具有 4,000 个元素的向量,例如 [0, 0, 1, 0, 1, ...., 0]。第 i 个元素指示第 i 个标签是否是文本的正标签。文本的标签数量因文本而异。

我有一个用于单标签文本分类的代码。

如何编辑以下代码以进行多标签文本分类?

特别是,我想知道以下几点。

  • 如何使用 TensorFlow 计算准确度。
  • 如何设置判断标签是正面还是负面的阈值。例如,如果输出为 [0.80, 0.43, 0.21, 0.01, 0.32],ground truth 为 [1, 1, 0, 0, 1],则得分超过 0.25 的标签应被判断为正。

谢谢你。

import tensorflow as tf

# hidden Layer
class HiddenLayer(object):
    def __init__(self, input, n_in, n_out):
        self.input = input

        w_h = tf.Variable(tf.random_normal([n_in, n_out],mean = 0.0,stddev = 0.05))
        b_h = tf.Variable(tf.zeros([n_out]))

        self.w = w_h
        self.b = b_h
        self.params = [self.w, self.b]

    def output(self):
        linarg = tf.matmul(self.input, self.w) + self.b
        self.output = tf.nn.relu(linarg)

        return self.output

# output Layer
class OutputLayer(object):
    def __init__(self, input, n_in, n_out):
        self.input = input

        w_o = tf.Variable(tf.random_normal([n_in, n_out], mean = 0.0, stddev = 0.05))
        b_o = tf.Variable(tf.zeros([n_out]))

        self.w = w_o
        self.b = b_o
        self.params = [self.w, self.b]

    def output(self):
        linarg = tf.matmul(self.input, self.w) + self.b
        self.output = tf.nn.relu(linarg)

        return self.output

# model
def model():
    h_layer = HiddenLayer(input = x, n_in = 20000, n_out = 1000)
    o_layer = OutputLayer(input = h_layer.output(), n_in = 1000, n_out = 4000)

    # loss function
    out = o_layer.output()
    cross_entropy = -tf.reduce_sum(y_*tf.log(out + 1e-9), name='xentropy')    

    # regularization
    l2 = (tf.nn.l2_loss(h_layer.w) + tf.nn.l2_loss(o_layer.w))
    lambda_2 = 0.01

    # compute loss
    loss = cross_entropy + lambda_2 * l2

    # compute accuracy for single label classification task
    correct_pred = tf.equal(tf.argmax(out, 1), tf.argmax(y, 1))
    accuracy = tf.reduce_mean(tf.cast(correct_pred, "float"))

    return loss, accuracy
4

2 回答 2

19

将 relu 更改为输出层的 sigmoid。将交叉熵损失修改为 sigmoid 交叉熵损失的显式数学公式(显式损失在我的案例/张量流版本中有效)

import tensorflow as tf

# hidden Layer
class HiddenLayer(object):
    def __init__(self, input, n_in, n_out):
        self.input = input

        w_h = tf.Variable(tf.random_normal([n_in, n_out],mean = 0.0,stddev = 0.05))
        b_h = tf.Variable(tf.zeros([n_out]))

        self.w = w_h
        self.b = b_h
        self.params = [self.w, self.b]

    def output(self):
        linarg = tf.matmul(self.input, self.w) + self.b
        self.output = tf.nn.relu(linarg)

        return self.output

# output Layer
class OutputLayer(object):
    def __init__(self, input, n_in, n_out):
        self.input = input

        w_o = tf.Variable(tf.random_normal([n_in, n_out], mean = 0.0, stddev = 0.05))
        b_o = tf.Variable(tf.zeros([n_out]))

        self.w = w_o
        self.b = b_o
        self.params = [self.w, self.b]

    def output(self):
        linarg = tf.matmul(self.input, self.w) + self.b
        #changed relu to sigmoid
        self.output = tf.nn.sigmoid(linarg)

        return self.output

# model
def model():
    h_layer = HiddenLayer(input = x, n_in = 20000, n_out = 1000)
    o_layer = OutputLayer(input = h_layer.output(), n_in = 1000, n_out = 4000)

    # loss function
    out = o_layer.output()
    # modified cross entropy to explicit mathematical formula of sigmoid cross entropy loss
    cross_entropy = -tf.reduce_sum( (  (y_*tf.log(out + 1e-9)) + ((1-y_) * tf.log(1 - out + 1e-9)) )  , name='xentropy' )    

    # regularization
    l2 = (tf.nn.l2_loss(h_layer.w) + tf.nn.l2_loss(o_layer.w))
    lambda_2 = 0.01

    # compute loss
    loss = cross_entropy + lambda_2 * l2

    # compute accuracy for single label classification task
    correct_pred = tf.equal(tf.argmax(out, 1), tf.argmax(y, 1))
    accuracy = tf.reduce_mean(tf.cast(correct_pred, "float"))

    return loss, accuracy
于 2016-09-13T14:47:17.330 回答
14

您必须使用其他交叉熵函数的变体来支持多标签分类。如果您的输出少于一千个,您应该使用sigmoid_cross_entropy_with_logits,如果您有 4000 个输出,您可以考虑候选采样,因为它比以前更快。

如何使用 TensorFlow 计算准确度。

这取决于您的问题以及您想要实现的目标。如果您不想错过图像中的任何对象,那么如果分类器除了一个对象之外没有问题,那么您应该将整个图像视为错误。您还可以认为错过或未分类的对象是错误。后者我认为它由 sigmoid_cross_entropy_with_logits 支持。

如何设置判断标签是正面还是负面的阈值。例如,如果输出为 [0.80, 0.43, 0.21, 0.01, 0.32],ground truth 为 [1, 1, 0, 0, 1],则得分超过 0.25 的标签应被判断为正。

门槛是一种方法,你必须决定哪一种。但这是某种 hack,而不是真正的多标签分类。为此,您需要我之前所说的先前功能。

于 2016-05-05T13:22:48.517 回答