Как изменить функцию активации, используемую в выходном слое нейронной сети, с softmax на sigmoid? - PullRequest
0 голосов
/ 19 июня 2020

При выполнении задач классификации изображений я хочу изменить функцию активации, используемую в выходном слое нейронной сети, с softmax на sigmoid, но после использования этого метода я получил сообщение об ошибке (информация об ошибке следующая. Ошибка не будет сообщать при использовании функции softmax).

Код Softmax до изменения:

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')
        # logits = slim.fully_connected(flatten, FLAGS.charset_size, activation_fn=None, reuse=reuse, scope='fc')
    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)

Сигмоидальный код после изменения:

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')
        # logits = slim.fully_connected(flatten, FLAGS.charset_size, activation_fn=None, reuse=reuse, scope='fc')
    # loss = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=labels))
    loss = tf.reduce_mean(tf.nn.sigmoid_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)
    probabilities = tf.sigmoid(logits)

Сообщение об ошибке кода:

Instructions for updating:
Please use `rate` instead of `keep_prob`. Rate should be set to `rate = 1 - keep_prob`.
Traceback (most recent call last):
  File "/usr/local/python3/lib/python3.6/site-packages/tensorflow/python/framework/tensor_shape.py", line 846, in merge_with
    self.assert_same_rank(other)
  File "/usr/local/python3/lib/python3.6/site-packages/tensorflow/python/framework/tensor_shape.py", line 891, in assert_same_rank
    other))
ValueError: Shapes (?,) and (?, 600) must have the same rank

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/python3/lib/python3.6/site-packages/tensorflow/python/ops/nn_impl.py", line 164, in sigmoid_cross_entropy_with_logits
    labels.get_shape().merge_with(logits.get_shape())
  File "/usr/local/python3/lib/python3.6/site-packages/tensorflow/python/framework/tensor_shape.py", line 852, in merge_with
    raise ValueError("Shapes %s and %s are not compatible" % (self, other))
ValueError: Shapes (?,) and (?, 600) are not compatible

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "chinese_rec_my_sigmoid.py", line 379, in <module>
    tf.app.run()
  File "/usr/local/python3/lib/python3.6/site-packages/tensorflow/python/platform/app.py", line 125, in run
    _sys.exit(main(argv))
  File "chinese_rec_my_sigmoid.py", line 346, in main
    train()
  File "chinese_rec_my_sigmoid.py", line 160, in train
    graph = build_graph(top_k=1)
  File "chinese_rec_my_sigmoid.py", line 116, in build_graph
    loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=logits, labels=labels))
  File "/usr/local/python3/lib/python3.6/site-packages/tensorflow/python/ops/nn_impl.py", line 167, in sigmoid_cross_entropy_with_logits
    (logits.get_shape(), labels.get_shape()))
ValueError: logits and labels must have the same shape ((?, 600) vs (?,))

Примечание. (1) При использовании функции softmax сообщение об ошибке не выводится. (2) Число 600 - это количество категорий классификации изображений.

1 Ответ

0 голосов
/ 19 июня 2020

Проблема в строке, которая вычисляет убыток с помощью sigmoid_cross_entropy_with_logits. В отличие от sparse_softmax_cross_entropy_with_logits, sigmoid_cross_entropy_with_logits ожидает, что тензор логитов и тензор меток будут иметь одинаковую форму и тип. В вашем случае логиты имеют форму BatchSize x 600 , но тензор меток имеет форму BatchSize x 1 .

Я думаю, вам следует закодировать метки в форму BatchSize x 600 используйте одно горячее кодирование, если ваши значения меток 1-600 (или 0-599) перед использованием сигмоида.

Однако я верю, что использование softmax даст вам лучшие результаты, чем сигмоид для мультиклассовой классификации.

...