Тензор потока: нулевой градиент - PullRequest
0 голосов
/ 09 мая 2018

По сути, я сталкиваюсь с проблемой, когда при попытке обновить некоторые переменные в области (т. Е. В области discriminator) градиент всегда равен нулю (я могу это проверить, напечатав их после вычисления их).

Это сбивает с толку, потому что я не понимаю, почему потеря не распространяется.

Мои заглушки кода следующие:

    def build_model(self):
    # Process inputs
    self.inputs =  tf.placeholder(tf.float32, shape = self.input_shape, name = "input")
    self.is_training = tf.placeholder(tf.bool, name = "is_training")
    self.targets = tf.placeholder(tf.float32, shape = self.output_shape, name = "targets")
    self.target_p = tf.placeholder(tf.float32, shape = self.patient_shape, name = "targets_patients")
    self.target_s = tf.placeholder(tf.float32, shape = self.sound_shape, name = "targets_sounds")
    # Process outputs
    self.encoded_X = self.encoder(self.inputs)
    self.posteriors = self.predictor(self.encoded_X)
    self.patient_predict, self.sound_predict  = self.discriminator(self.encoded_X, tf.expand_dims(self.posteriors, axis = -1))
    self.patient_predict_id = tf.argmax(tf.nn.softmax(self.patient_predict, axis = -1))
    self.sound_predict_id = tf.argmax(tf.nn.softmax(self.sound_predict, axis = -1))

    # Process losses
    self.segment_loss = tf.losses.mean_squared_error(self.targets, self.posteriors)
    self.patient_loss = tf.nn.softmax_cross_entropy_with_logits_v2(logits = self.patient_predict, labels = self.target_p)
    self.sound_loss = tf.nn.softmax_cross_entropy_with_logits_v2(logits = self.sound_predict, labels = self.target_s)
    self.disc_loss = self.patient_loss + self.sound_loss
    self.combined_loss = self.segment_loss - self.lambda_param*(self.disc_loss)

    self.extra_update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
    with tf.control_dependencies(self.extra_update_ops):
        predictor_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope="predictor")
        encoder_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope="encoder")
        discrim_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope="discriminator")

        self.discrim_train = tf.train.AdamOptimizer(0.001).minimize(tf.reduce_mean(-1*self.combined_loss), var_list=discrim_vars)
        self.predict_train = tf.train.AdamOptimizer(0.001).minimize(tf.reduce_mean(self.combined_loss), var_list=predictor_vars)
        self.encode_train = tf.train.AdamOptimizer(0.001).minimize(tf.reduce_mean(self.combined_loss), var_list=encoder_vars)

Как видите, self.combined_loss должно зависеть от self.patient_loss, найденного из self.discriminator.

Мой код для discriminator() здесь:

    def discriminator(self, encoded_X, posterior, reuse = False):
    with tf.variable_scope("discriminator") as scope:
        if reuse: scope.reuse_variables()
        print('\n############## \nDiscriminator\n')
        print('Discriminator encode input-shape: ', self.encode_shape)
        print('Discriminator posterior input-shape: ', self.output_shape, ' (Expanded to correct size)')
        inputs = tf.concat([encoded_X, posterior], axis = -2)
        tf.stop_gradient(posterior)
        print('Stacked input shape: ', inputs.get_shape())
        h = tf.layers.conv2d(inputs, 10, (5, 2), padding = 'SAME', activation = tf.nn.relu)
        h = tf.layers.max_pooling2d(h, (5, 2), (5, 2))
        print('Layer 1: ', h.get_shape())
        h = tf.layers.conv2d(h, 5, (5, 2), padding = 'SAME', activation = tf.nn.relu)
        h = tf.squeeze(tf.layers.max_pooling2d(h, (3, 2), (3, 2)), axis = -2)
        h = tf.layers.flatten(h)
        print('Layer 2: ', h.get_shape())
        h_p = tf.layers.dense(h, self.patient_shape[-1])
        h_s = tf.layers.dense(h, self.sound_shape[-1])
        print('Discriminator patient o/p shape: ', h_p.get_shape(), ' Expected shape: ', self.patient_shape)
        print('Discriminator sound o/p shape: ', h_s.get_shape(), ' Expected shape: ', self.sound_shape)
        return h_p, h_s

tf.stop_gradient вызван, потому что я не хочу, чтобы градиент протекал от дискриминатора к модели, которая производит постеры.

Наконец, я называю свою модель здесь:

        feed_dict= {
          self.inputs: X, 
          self.targets: y,
          self.target_p: y_p_oh,
          self.target_s: y_s_oh,
          self.is_training: True
    }
    posteriors, cost_loss, disc_loss, patient_id_pred , sound_id_pred, _ , _  = self.sess.run([
            self.posteriors, 
            self.combined_loss, 
            self.disc_loss,
            self.patient_predict_id,
            self.sound_predict_id,
            self.predict_train, 
            self.encode_train,
            ], feed_dict = feed_dict)

    j = 0
    print('Combined-loss: ', np.mean(cost_loss), 'Discriminator-loss: ', np.mean(disc_loss))
    while np.mean(disc_loss) > entropy_cutoff:
        disc_loss, _  = self.sess.run([self.disc_loss, self.discrim_train], feed_dict = feed_dict)
        j+=1
        print(' Inner loop iteration: ', j, ' Loss: ', np.around(np.mean(disc_loss), 5), ' Cutoff: ', np.around(entropy_cutoff, 5), end = '\r')
    print("")

Из моего исследования код застревает в цикле while, поскольку минимизация шага поезда (чтобы эффективно максимизировать комбинированную потерю) просто дает нулевые градиенты для всех переменных в области действия discriminator. Почему это происходит?

РЕДАКТИРОВАТЬ: Я думаю, что я локализовал ошибку:

  self.disc_loss = self.patient_loss + self.sound_loss
  self.combined_loss = self.segment_loss - self.lambda_param * self.disc_loss

Если я применяю минимизацию к self.disc_loss, она работает нормально. Но когда я применяю минимизацию к self.combined_loss, операция прерывается и градиенты равны нулю. Почему это так?

РЕДАКТИРОВАТЬ: Tensorboard Graph

enter image description here

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