Классификация многопозиционного текста с использованием TensorFlow

Текстовые данные организованы в виде вектора с 20 000 элементов, например [2, 1, 0, 0, 5, ...., 0]. i-й элемент указывает частоту i-го слова в тексте.

Данные наземной метки также представлены в виде вектора с 4000 элементами, например [0, 0, 1, 0, 1, ...., 0]. i-й элемент указывает, является ли i-я метка положительной меткой для текста. Количество меток для текста различается в зависимости от текста.

У меня есть код для классификации текста по одной метке.

Как я могу отредактировать следующий код для классификации текста с несколькими ярлыками?

Особо хотелось бы отметить следующие моменты.

  • Как вычислить точность с помощью TensorFlow.
  • Как установить порог, определяющий, является ли ярлык положительным или отрицательным. Например, если результат равен [0,80, 0,43, 0,21, 0,01, 0,32], а истинное значение - [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

person Benben    schedule 15.02.2016    source источник
comment
Я думаю, что, помимо кросс-энтропии, может быть лучше использовать функцию потерь.   -  person Aaron    schedule 17.02.2016
comment
Существует множество различных мер точности для задачи классификации с несколькими метками: точность до одной ошибки, потеря ранга, средняя средняя точность и т. Д. Я сам все еще изучаю TensorFlow и пока не смог правильно реализовать ни один из них. Но, возможно, этот документ поможет вам: arxiv.org/pdf/1312.5419v3.pdf Пусть я знаю, если вы добьетесь прогресса!   -  person Eric Galluzzo    schedule 24.02.2016
comment
Для лучшего представления о точности рассмотрите возможность расчета точности и отзыва.   -  person Abhishek Patel    schedule 15.04.2017
comment
@Benben, что такое y_, я не вижу его определения   -  person SumNeuron    schedule 29.08.2018


Ответы (2)


Измените relu на сигмоид выходного слоя. Измените потерю кросс-энтропии на явную математическую формулу сигмовидной перекрестной потери энтропии (явная потеря работала в моем случае / версии тензорного потока)

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
person Alok Nayak    schedule 13.09.2016

Вы должны использовать другие варианты функции перекрестной энтропии для поддержки многозначной классификации. Если у вас меньше тысячи выходов, вы должны использовать sigmoid_cross_entropy_with_logits, в вашем случае, когда у вас 4000 выходов, вы можете рассмотреть выборка кандидатов, так как она быстрее, чем предыдущая.

Как вычислить точность с помощью TensorFlow.

Это зависит от вашей проблемы и того, чего вы хотите достичь. Если вы не хотите пропустить какой-либо объект на изображении, тогда, если классификатор работает нормально, кроме одного, вы должны считать все изображение ошибкой. Вы также можете считать, что объект, пропущенный или не классифицированный, является ошибкой. Последнее, я думаю, поддерживается sigmoid_cross_entropy_with_logits.

Как установить порог, определяющий, является ли ярлык положительным или отрицательным. Например, если результат равен [0,80, 0,43, 0,21, 0,01, 0,32], а истинное значение - [1, 1, 0, 0, 1], метки с оценкой более 0,25 должны быть оценены как положительные.

Порог - это один из способов, вам нужно решить, какой из них. Но это своего рода взлом, а не настоящая многоуровневая классификация. Для этого вам понадобятся предыдущие функции, о которых я говорил ранее.

person jorgemf    schedule 05.05.2016
comment
Я не знаю, почему люди предлагают sigmoid_cross_entropy_with_logits. Если это то, что предполагает его название, то есть -Y * ln (сигмоид (логиты)). Тогда это минимизирует потери, давая высокую вероятность каждому классу и, фактически, это давало это в моем случае. - person Alok Nayak; 13.09.2016
comment
эта функция не возвращает вероятность. И я не понимаю, как это минимизировать потери, давая высокую ценность. Если вы установите для своих классов значение 1 и 0, когда класс отсутствует, тогда сеть дает значения, близкие к 0, когда объекта нет на изображении, и значения, близкие к 1 или больше (даже 2 o 3), если объект находится в изображение. Пользуюсь, работает неплохо. - person jorgemf; 13.09.2016
comment
Это минимизирует потери, давая высокое значение каждому классу, потому что нет штрафа (или потери 0) за присвоение высокого значения классам, которые помечены 0. Таким образом, необходимо изменить потерю перекрестной энтропии с помощью двоичной перекрестной энтропии (y * ln (сигмоид (логит)) + 1-y * ln (сигмоид (1-логит))). sigmoid_cross_entropy_with_logits не реализует внутреннюю двоичную кросс-энтропию. Я удивлен, почему это работает в вашем случае, вы используете theano и т. Д. - person Alok Nayak; 14.09.2016
comment
Я думаю, вы ошибаетесь с математикой. Это: y * ln (сигмоид (логиты)) + (1-y) * ln (1-сигмоид (логиты)) Итак: logits = 0, y = 0 = ›0; logits = 1, y = 1 = ›0; logits = 1, y = 0 = ›1,3; logits = 0, y = 1 = ›1,3; Вы можете построить функцию в Google, играя с числами. Просто найдите y * -ln (1 / (1 + e ^ -x)) + (1-y) * - ln (1-1 / (1 + e ^ -x)) - person jorgemf; 14.09.2016
comment
Мое плохое, игнорируйте приведенную выше математику. Вот что я использовал, что сработало для меня, -tf.reduce_mean (tf.mul (y, tf.log (tf.nn.sigmoid (logits) + 1e-9)) + tf.mul (1-y, tf .log (1 - tf.nn.sigmoid (логиты) + 1e-9))). Это сработало, и то, что вы предложили, не сработало, дайте мне знать, если я ошибаюсь в своих аргументах - person Alok Nayak; 14.09.2016
comment
Это может быть используемая вами версия тензорного потока. Уравнения почти такие же (вы добавили небольшое число, чтобы избежать нулей, а в тензорном потоке они используют функцию max). Ваш аргумент неверен, если вы замените значения в уравнении, вы получите ошибки, когда логиты и y не совпадают, и 0, когда они совпадают. Так что я не знаю, почему это не работает для вас, но уравнения в порядке. - person jorgemf; 14.09.2016
comment
Несомненно, если я заменяю значения в своем уравнении, я получаю ошибки, когда логиты и y не совпадают, и 0, когда они совпадают. Нет сомнений в моем определении потерь. Но в тензорном потоке sigmoid_cross_entropy_with_logits. потеря = -Y * ln (сигмоид (логиты)). Пожалуйста, оправдывайте эту потерю, а не потерю, которую я использовал - person Alok Nayak; 15.09.2016
comment
Я говорил о TF, я написал уравнение и протестировал его. Сделай сам, работает. Я не проверял твои уравнения. Скажите, с какими значениями не работает эквивалент TF - person jorgemf; 15.09.2016
comment
Вы хотите сказать, что это не работает для вас. У меня работает нормально уже пару месяцев. sigmoid_cross_entropy_with_logits не использует уравнение, которое вы сказали, оно использует то, которое я написал ранее (он находится в доках тензорного потока): y * ln (sigmoid (logits)) + (1-y) * ln (1-sigmoid (logits) )) - person jorgemf; 15.09.2016