Как тензор потока softmax добавить неизвестный класс? - PullRequest
0 голосов
/ 27 декабря 2018

Я настроил систему классификации ocr, используя Tensorflow.

Вот график:

def build_graph(top_k):
    # with tf.device('/cpu:0'):
    keep_prob = tf.placeholder(dtype=tf.float32, shape=[], name='keep_prob')
    images = tf.placeholder(dtype=tf.float32, shape=[None, 64, 64, 1], name='image_batch')
    labels = tf.placeholder(dtype=tf.int64, shape=[None], name='label_batch')

    conv_1 = slim.conv2d(images, 64, [3, 3], 1, padding='SAME', scope='conv1')
    max_pool_1 = slim.max_pool2d(conv_1, [2, 2], [2, 2], padding='SAME')
    conv_2 = slim.conv2d(max_pool_1, 128, [3, 3], padding='SAME', scope='conv2')
    max_pool_2 = slim.max_pool2d(conv_2, [2, 2], [2, 2], padding='SAME')
    conv_3 = slim.conv2d(max_pool_2, 256, [3, 3], padding='SAME', scope='conv3')
    max_pool_3 = slim.max_pool2d(conv_3, [2, 2], [2, 2], padding='SAME')

    flatten = slim.flatten(max_pool_3)
    fc1 = slim.fully_connected(slim.dropout(flatten, keep_prob), 1024, activation_fn=tf.nn.tanh, scope='fc1')
    logits = slim.fully_connected(slim.dropout(fc1, keep_prob), FLAGS.charset_size, activation_fn=None, scope='fc2')
    loss = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=labels))
    accuracy = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(logits, 1), labels), tf.float32))

    global_step = tf.get_variable("step", [], initializer=tf.constant_initializer(0.0), trainable=False)
    rate = tf.train.exponential_decay(2e-4, global_step, decay_steps=2000, decay_rate=0.97, staircase=True)
    train_op = tf.train.AdamOptimizer(learning_rate=rate).minimize(loss, global_step=global_step)
    probabilities = tf.nn.softmax(logits)

    tf.summary.scalar('loss', loss)
    tf.summary.scalar('accuracy', accuracy)
    merged_summary_op = tf.summary.merge_all()
    predicted_val_top_k, predicted_index_top_k = tf.nn.top_k(probabilities, k=top_k, name="predicted_top_k")
    accuracy_in_top_k = tf.reduce_mean(tf.cast(tf.nn.in_top_k(probabilities, labels, top_k), tf.float32))

    return {'images': images,
            'labels': labels,
            'keep_prob': keep_prob,
            'top_k': top_k,
            'global_step': global_step,
            'train_op': train_op,
            'loss': loss,
            'accuracy': accuracy,
            'accuracy_top_k': accuracy_in_top_k,
            'merged_summary_op': merged_summary_op,
            'predicted_distribution': probabilities,
            'predicted_index_top_k': predicted_index_top_k,
            'predicted_val_top_k': predicted_val_top_k}

Вот функция вывода:

def inference(images, pbfile="pb/ocr.pb"):
    print('inference')
    start = time.time()
    predicted_val_top_k = graph.get_tensor_by_name('ocr/predicted_top_k:0')
    predicted_index_top_k = graph.get_tensor_by_name('ocr/predicted_top_k:1')
    tensor_image = graph.get_tensor_by_name('ocr/image_batch:0')
    keep_prob = graph.get_tensor_by_name('ocr/keep_prob:0')
    probabilities = graph.get_tensor_by_name('ocr/Softmax:0')
    logits = graph.get_tensor_by_name('ocr/fc2/BiasAdd:0')
    end = time.time()
    print('takes %s second to get tensor' % (start - end))
    result = []
    for image in images:
        temp_image = Image.open(image).convert('L')
        temp_image = temp_image.resize((IMAGE_SIZE, IMAGE_SIZE), Image.ANTIALIAS)
        temp_image = np.asarray(temp_image) / 255.0
        temp_image = temp_image.reshape([-1, 64, 64, 1])
        start = time.time()
        logit, prob, predict_val, predict_index = sess.run([logits, probabilities, predicted_val_top_k, predicted_index_top_k],
                                              feed_dict={tensor_image: temp_image, keep_prob: 1.0})
        end = time.time()
        print('takes %s second to run tensor' % (start - end))
        result.append({'image': image, 'val': predict_val, 'index': predict_index})
        document_dict = {
                            0: 'V',
                            1: 'X',
                            2: 'U'
        }
        image_name = image.split('/')[-1]
    return result

У нас всего триклассы теперь, то есть 'V', 'X', 'U', и все в порядке, если цель, которую мы хотим обнаружить, принадлежит к трем типам.

Однако проблема возникает, когда мы обнаруживаем, что цель не принадлежитк кандидату там вводятся, например, мы теперь ставим «А» для вывода, проблема в том, что мы также получили класс «Х» для «А», что, очевидно, неверно.

Затем я хочу выделить другиеустановив порог оценки.

Мы знаем, что tf.nn.softmax возвращает что-то вроде результатов, и, когда я отлаживаю, я обнаруживаю, что результат (предикат_val в функции логического вывода) для класса «X» для цели »A 'почти равен 1 (на самом деле 0.9999 ..).

Затем, я думаю, что это разумно после поиска в softmax:

  softmax = tf.exp(logits) / tf.reduce_sum(tf.exp(logits), axis)

Он выполняет операции только с текущими логами классов.

Итак, есть ли способ добавить неизвестный класс для softmaxс участием всех других целей?

Env: Python3.6.5;Tensorflow 1.8.0

Спасибо.

Уэсли

1 Ответ

0 голосов
/ 27 декабря 2018

Я бы добавил дополнительный выходной класс Unknown, поскольку это должно позволить вашей модели научиться классифицировать предметы в обучающем наборе, а также иметь выходные данные для сброса любых предметов, которые близко не соответствуют одной из целей.

Догадываясь о своем коде, так как вы не предоставили рабочий пример, я думаю, что следующее изменение поможет:

logits = slim.fully_connected(slim.dropout(fc1, keep_prob), FLAGS.charset_size+1, activation_fn=None, scope='fc2')

Теперь ваш вывод будет иметь 4 вероятности, так что document_dict может выглядеть следующим образом:

document_dict = {
                            0: 'V',
                            1: 'X',
                            2: 'U',
                            3: 'Unknown'
        }

Вам нужно будет посмотреть, как это тренируется, но я ожидаю, что теперь вы увидите гораздо более низкие оценки для значений, которые вас интересуют (V, X, U) при столкновении с неизвестным вводом.

...