Tensorflow CNN — плотный слой в качестве входных данных слоя Softmax

Я пытаюсь воспроизвести CNN, описанный в https://pdfs.semanticscholar.org/3b57/85ca3c29c963ae396c2f94ba1a805c787cc8.pdf

и я застрял на последнем слое. Я смоделировал cnn следующим образом

# Model function for CNN
def cnn_model_fn(features, labels, mode):

  # Input Layer
  # Reshape X to 4-D tensor: [batch_size, width, height, channels]
  # Taxes images are 150x150 pixels, and have one color channel
  input_layer = tf.reshape(features, [-1, 150, 150, 1])

  # Convolutional Layer #1
  # Input Tensor Shape: [batch_size, 150, 150, 1]
  # Output Tensor Shape: [batch_size, 144, 144, 20]
  conv1 = tf.layers.conv2d(
      inputs=input_layer,
      filters=20,
      kernel_size=[7, 7],
      padding="valid",
      activation=tf.nn.relu)

  # Pooling Layer #1
  # Input Tensor Shape: [batch_size, 144, 144, 20]
  # Output Tensor Shape: [batch_size, 36, 36, 20]
  pool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[4, 4], strides=4)

  # Convolutional Layer #2
  # Input Tensor Shape: [batch_size, 36, 36, 20]
  # Output Tensor Shape: [batch_size, 32, 32, 50]
  conv2 = tf.layers.conv2d(
      inputs=pool1,
      filters=50,
      kernel_size=[5, 5],
      padding="valid",
      activation=tf.nn.relu)

  # Pooling Layer #2
  # Input Tensor Shape: [batch_size, 32, 32, 50]
  # Output Tensor Shape: [batch_size, 8, 8, 50]
  pool2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[4, 4], strides=4)

  # Flatten tensor into a batch of vectors
  # Input Tensor Shape: [batch_size, 8, 8, 50]
  # Output Tensor Shape: [batch_size, 8 * 8 * 50]
  pool2_flat = tf.reshape(pool2, [-1, 8 * 8 * 50])

  # Dense Layer #1
  # Densely connected layer with 1000 neurons
  # Input Tensor Shape: [batch_size, 8 * 8 * 50]
  # Output Tensor Shape: [batch_size, 1000]
  dense1 = tf.layers.dense(inputs=pool2_flat, units=1000, activation=tf.nn.relu)

  # Dense Layer #2
  # Densely connected layer with 1000 neurons
  # Input Tensor Shape: [batch_size, 1000]
  # Output Tensor Shape: [batch_size, 1000]
  dense2 = tf.layers.dense(inputs=dense1, units=1000, activation=tf.nn.relu)

  # Add dropout operation; 0.5 probability that element will be kept
  dropout = tf.layers.dropout(
      inputs=dense2, rate=0.5, training=mode == learn.ModeKeys.TRAIN)

  # Logits layer
  # Input Tensor Shape: [batch_size, 1000]
  # Output Tensor Shape: [batch_size, 4]
  logits = tf.layers.dense(inputs=dropout, units=nClass)

  loss = None
  train_op = None

  # Calculate Loss (for both TRAIN and EVAL modes)
  if mode != learn.ModeKeys.INFER:
    onehot_labels = tf.one_hot(indices=tf.cast(labels, tf.int32), depth=nClass)
    loss = tf.losses.softmax_cross_entropy(
        onehot_labels=onehot_labels, logits=logits)

  # Configure the Training Op (for TRAIN mode)
  if mode == learn.ModeKeys.TRAIN:
    train_op = tf.contrib.layers.optimize_loss(
        loss=loss,
        global_step=tf.contrib.framework.get_global_step(),
        learning_rate=0.001,
        optimizer="SGD")

  # Generate Predictions
  predictions = {
      "classes": tf.argmax(
          input=logits, axis=1)
  }

  # Return a ModelFnOps object
  return model_fn_lib.ModelFnOps(
      mode=mode, predictions=predictions, loss=loss, train_op=train_op)

но конечная точность действительно плохая (0,25). Итак, я понял, что на самом деле в документе говорится, что последний слой — это слой softmax. Итак, я попытался изменить свой слой логитов на

logits = tf.layers.softmax(dropout)

но когда я запускаю его, он говорит

ValueError: Shapes (?, 1000) and (?, 4) are incompatible

Итак, что мне здесь не хватает?


person dylaniato    schedule 14.06.2017    source источник


Ответы (1)


Оригинал был правильным. Активация softmax применяется при расчете потерь с помощью tf.losses.softmax_cross_entropy. Если вы хотите рассчитать его отдельно, вы должны добавить его после вычисления логита, но не заменяя его, как вы это сделали.

logits = tf.layers.dense(inputs=dropout, units=nClass)
softmax = tf.layers.softmax(logits)

Или можно совместить оба в одном, но я бы не советовал. Софтмакс лучше считать с убытком.

logits = tf.layers.dense(inputs=dropout, units=nClass, activation=tf.layers.softmax)

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

person Manolo Santos    schedule 14.06.2017
comment
вы были абсолютно правы: после нормализации ввода я начал получать правильные результаты. Большое спасибо. - person dylaniato; 14.06.2017