Классификация нескольких этикеток с TENSORFLOW --- NaN в стоимости и весах - PullRequest
0 голосов
/ 04 мая 2018

Контекстуализация
Я строю нейронную сеть для классификации по нескольким меткам: идентификация меток на изображении (какую одежду носит человек, ее цвет и т. Я хотел использовать чистый тензорный поток (вместо API, таких как kears), чтобы иметь больше гибкости в отношении моих метрик.
P.S .: Данные, использованные для этой модели тензорного потока, были протестированы с помощью построенной модели Keras и не выявили проблем, которые я собираюсь здесь раскрыть.

Данные
Мои входные данные (X, Y): X имеет форму (1814,204,204,3), а Y имеет форму (1814,39). Таким образом, в основном X - это набор изображений, а Y - метки, связанные с каждым изображением, которые будут использоваться в процессе обучения под наблюдением.
Всего имеется 39 меток, поэтому для каждого изображения размером (1,204,204,3) мы связываем вектор формы (1,39): 39 значений могут быть 0 или 1,1, если соответствующая метка идентифицирована на этом изображении О, еще. Одновременно могут быть идентифицированы многие метки, что означает, что мы не используем одно горячее кодирование, и это не ситуация классификации с несколькими классами! PS: я уже нормализовал свои данные, чтобы их можно было вставить в [0,1]

Что я сделал
1. Первое, что я сделал, это построил абстрактную версию моего классификатора (который является CNN): вот структура моего CNN:

# Convolutional Layer 1
# Dropout layer 1
# Convolutional Layer 2
# Pooling Layer 2
# Dense layer 3  
# Dropout layer 3   
# Dense layer 4

для данного набора данных размером (?, 204,204,3): здесь поток данных через различные слои:

conv1 OUTPUT shape:  (?, 204, 204, 32)  
drop1 OUTPUT shape:  (?, 204, 204, 32)  
conv2 OUTPUT shape:  (?, 204, 204, 32)  
pool2 OUTPUT shape:  (?, 102, 102, 32)  
dense3 OUTPUT shape:  (?, 512)  
drop3 OUTPUT shape:  (?, 512)  
dense4 OUTPUT shape:  (?, 39)  

Вот код для построения структуры CNN

   def create_model(X,Y):
        # Convolutional Layer #1
        conv1 = tf.layers.conv2d(
          inputs=X,
          filters=32,
          kernel_size=[3, 3],
          padding="same",
          activation=tf.nn.relu)
        print('conv1 OUTPUT shape: ',conv1.shape)

        # Dropout layer #1
        dropout1 = tf.layers.dropout(
          inputs=conv1, rate=0.2, training='TRAIN' == tf.estimator.ModeKeys.TRAIN)
        print('drop1 OUTPUT shape: ',dropout1.shape)

        # Convolutional Layer #2
        conv2 = tf.layers.conv2d(
          inputs=dropout1,
          filters=32,
          kernel_size=[3, 3],
          padding="same",
          activation=tf.nn.relu)
        print('conv2 OUTPUT shape: ',conv2.shape)

        # Pooling Layer #2
        pool2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2],strides=2)
        print('pool2 OUTPUT shape: ',pool2.shape)
        pool2_flat = tf.reshape(pool2, [-1, pool2.shape[1]*pool2.shape[2]*pool2.shape[3]])

        # Dense layer #3
        dense3 = tf.layers.dense(inputs=pool2_flat, units=512, activation=tf.nn.relu)
        print('dense3 OUTPUT shape: ',dense3.shape)

        # Dropout layer #3
        dropout3 = tf.layers.dropout(
          inputs=dense3, rate=0.5, training='TRAIN' == tf.estimator.ModeKeys.TRAIN)
        print('drop3 OUTPUT shape: ',dropout3.shape)

        # Dense layer #4
        Z = tf.layers.dense(inputs=dropout3, units=39, activation=tf.nn.sigmoid)
        print('dense4 OUTPUT shape: ',Z.shape)

        return Z  

2. Теперь я определяю свою функцию стоимости и мой оптимизатор .

  • Для функции стоимости Я использую cross_entropy_with_logits и независимо вычисляю среднее значение для всех моих выходных компонентов в пакетном образце. Например, если у меня есть партия размером 10, результат модели будет иметь форму (10,39), поэтому для стоимости у нас будет вектор формы (1,39) (для каждого ярлыка мы рассчитываем среднее значение для разных образцов в партии)
  • Для оптимизатора Я использую Adam Optimizer.

Вот код для расчета стоимости и оптимизатор.

def optimizer_and_cost(output,labels):
    # Calculating cost
    cost= tf.reduce_mean(labels * - tf.log(output) + (1 - labels) * - tf.log(1 - output),axis=0)
    print('cost: shape of cost: ',cost.shape)
    cost= tf.reshape(cost, [1, 39])
    print('cost reshaped: shape of cost reshaped: ',cost.shape)

    #Optimizer
    optimizer = tf.train.AdamOptimizer(learning_rate=0.001).minimize(cost)
    return optimizer,cost  

PS: 'axis = 0' в tf.reduce_mean - это то, что позволяет мне рассчитывать для каждой метки независимо, среднее значение для примеров партий!

3. Определение заполнителей, инициализация модели и обучение.
После того, как моя абстрактная модель с различными параметрами определена, я создал заполнители и построил вычислительные графики, затем я инициализировал веса и начал обучение. Проблемы: Я начал получать значения NaN для весов в разных слоях и NaN в функции стоимости в процессе оптимизации. Поэтому сначала Reflexe пытался отладить и понять, что происходит.
Я попытался проверить простой случай, который выглядит следующим образом:
инициализация весов ---> рассчитать стоимость и распечатать ее (напечатать весовые коэффициенты) ---> выполнить одну оптимизацию ---> рассчитать стоимость и распечатать ее (распечатать весовые коэффициенты) .
Результат:
Первый отпечаток в порядке, у меня есть реальные значения (довольно очевидно). Однако после первой оптимизации: я получил значения NaNs для стоимости. Почему мой оптимизатор переводит стоимость в NaN после одного шага оптимизации!
вот код для теста! (X_train и Y_train имеют форму (1269, 204, 204, 3) и (1269,39): я беру только 4 элемента каждого из них)

#clearing the graph
ops.reset_default_graph()

#defining placeholders
X = tf.placeholder(tf.float32, [None, X_train.shape[1],X_train.shape[2],X_train.shape[3]])
Y = tf.placeholder(tf.float32, [None, Y_train.shape[1]])
optimizer, cost=optimizer_and_cost(create_model(X,Y),Y)

# Initialize all the variables globally
init = tf.global_variables_initializer()

# Start the session to compute the tensorflow graph
sess=tf.Session()
sess.run(init)

#printing cost and first layers weights
print('first layer weights ',sess.run(tf.trainable_variables()[0]) )
print('cost: ',sess.run(cost,feed_dict={X:X_train[0:4,:], Y:Y_train[0:4,:]}))

#doing one optimization step
_ ,OK=sess.run([optimizer, cost], feed_dict={X:X_train[0:4,:], Y:Y_train[0:4,:]})


#printing cost and first layers weights
print('first layer weights ',sess.run(tf.trainable_variables()[0]) )
print('cost :',sess.run(cost,feed_dict={X:X_train[0:4,:], Y:Y_train[0:4,:]}))

#closing session
sess.close()

Любая помощь приветствуется.

Ответы [ 2 ]

0 голосов
/ 04 мая 2018

Эта ссылка решила мою проблему: Ошибка Tensorflow NaN?

в основном, при вычислении y * log (y), как правило, 0 log (0), поэтому решение находится в предоставленной ссылке. В любом случае, ребята, спасибо за помощь.

Замена

  cost= tf.reduce_mean(labels * - tf.log(output) + (1 - labels) * - tf.log(1 - output),axis=0)

С этим

cost= tf.reduce_mean(labels * - tf.log(tf.clip_by_value(output,1e-10,1.0)) + (1 - labels) * - tf.log(tf.clip_by_value(1 - output,1e-10,1.0)),axis=0)
0 голосов
/ 04 мая 2018

Рекомендуется использовать tf.nn.softmax_cross_entropy_with_logits_v2 вместо того, чтобы реализовывать его самостоятельно, поскольку он охватывает множество угловых случаев, которые обычно приводят к nan потерям.

Способ, которым вы используете tf.nn.softmax_cross_entropy_with_logits_v2, заключается в том, чтобы активировать Dense Layer 4 равным linear вместо softmax. Таким образом, выходы вашего Dense Layer 4 будут logits, которые затем могут быть напрямую переданы в tf.nn.softmax_cross_entropy_with_logits_v2.

Наконец, внимательно прочитайте следующее:

РЕДАКТИРОВАТЬ : Плохо, я недостаточно внимательно прочитал вопрос, поэтому я упустил тот факт, что вы сказали, что это не проблема multi-class classification. Если это не проблема multi-class classification, то это может быть за пределами моего текущего опыта. Поэтому я оставлю вас с другой ссылкой, которую вы и я оба можем внимательно прочитать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...