модель тензорного потока не обновляет веса - PullRequest
0 голосов
/ 07 декабря 2018

У меня есть модель, которая тренируется (она проходит через этапы и эпохи и оценивает потери), но веса не тренируются.

Я пытаюсь обучить дискриминатору, который бы различал, является ли изображение синтетическим или реальным.Это часть модели GAN, которую я пытаюсь построить.

Базовая структура выглядит следующим образом: model structure

У меня есть два входа: 1. изображение (может быть реальным или синтетическим) 2. метки (0 для реального,1 для синтетического)

В Source Estimator я извлекаю элементы из изображений.Я уже обучил модель и восстановил вес и уклоны.Эти слои заморожены (не обучаемы).

def SourceEstimator(eye, name, trainable = True):
  # source estimator and target representer shares the same structure.
  # SE is not trainable, while TR is.
  net = tf.layers.conv2d(eye, 32, 3, (1,1), padding='same', activation=tf.nn.leaky_relu, trainable=trainable, name=name+'_conv2d_1')
  net = tf.layers.conv2d(net, 32, 3, (1,1), padding='same', activation=tf.nn.leaky_relu, trainable=trainable, name=name+'_conv2d_2')
  net = tf.layers.conv2d(net, 64, 3, (1,1), padding='same', activation=tf.nn.leaky_relu, trainable=trainable, name=name+'_conv2d_3')
  c3 = net
  net = tf.layers.max_pooling2d(net, 3, (2,2), padding='same', name=name+'_maxpool_4')
  net = tf.layers.conv2d(net, 80, 3, (1,1), padding='same', activation=tf.nn.leaky_relu, trainable=trainable, name=name+'_conv2d_5')
  net = tf.layers.conv2d(net, 192, 3, (1,1), padding='same', activation=tf.nn.leaky_relu, trainable=trainable, name=name+'_conv2d_6')
  c5 = net
  return (c3, c5)

Дискриминатор выглядит следующим образом:

def DiscriminatorModel(features, reuse=False):
  with tf.variable_scope('discriminator', reuse=tf.AUTO_REUSE):
    net = tf.layers.conv2d(features, 64, 3, 2, padding='same', kernel_initializer='truncated_normal', activation=tf.nn.leaky_relu, trainable=True, name='discriminator_c1')
    net = tf.layers.conv2d(net, 128, 3, 2, padding='same', kernel_initializer='truncated_normal', activation=tf.nn.leaky_relu, trainable=True, name='discriminator_c2')
    net = tf.layers.conv2d(net, 256, 3, 2, padding='same', kernel_initializer='truncated_normal', activation=tf.nn.leaky_relu, trainable=True, name='discriminator_c3')

    net = tf.contrib.layers.flatten(net)
    net = tf.layers.dense(net, units=1, activation=tf.nn.softmax, name='descriminator_out', trainable=True)
    return net

Ввод идет в модель SourceEstimator и извлекает функции (c3, c5).

Затем c3 и c5 объединяются вдоль оси канала и передаются в модель дискриминатора.

c3, c5 = CommonModel(self.left_eye, 'el', trainable=False)
c5 = tf.image.resize_images(c5, size=(self.config.img_size,self.config.img_size))
features = tf.concat([c3, c5], axis=3)
##---------------------------------------- DISCRIMINATOR ------------------------------------------##
with tf.variable_scope('discriminator'):
    logit = DiscriminatorModel(features)

Наконец, потери и train_ops

##---------------------------------------- LOSSES ------------------------------------------##
with tf.variable_scope("discriminator_losses"):
  self.loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=logit, labels=self.label))

##---------------------------------------- TRAIN ------------------------------------------##
# optimizers
update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
with tf.control_dependencies(update_ops):
    disc_optimizer = tf.train.AdamOptimizer(learning_rate = learning_rate)
    self.disc_op = disc_optimizer.minimize(self.loss, global_step=self.global_step_tensor, name='disc_op')

Шаги и эпохи поезда.Я использую 32 размера партии.И класс генератора данных, чтобы получить изображение каждого шага.

def train_epoch(self):
    num_iter_per_epoch = self.train_data.get_size() // self.config.get('batch_size')
    loop = tqdm(range(num_iter_per_epoch))
    for i in loop:
        dloss = self.train_step(i)
        loop.set_postfix(loss='{:05.3f}'.format(dloss))

def train_step(self, i):
    el, label = self.train_data.get_batch(i)

    ## ------------------- train discriminator -------------------##
    feed_dict = {
            self.model.left_eye: el,
            self.model.label: label
    }
    _, dloss = self.sess.run([self.model.disc_op, self.model.loss], feed_dict=feed_dict)
    return dloss

Пока модель проходит этапы и эпохи, вес остается неизменным.

Потери колеблются на этапах обучения, но потери для каждой эпохи одинаковы.Например, если я не буду перетасовывать набор данных каждую эпоху, потери на графике будут следовать одной и той же схеме в каждую эпоху.

Что, я думаю, означает, что модель распознает различные потери, но не обновляет параметры в соответствии с потерями.

Вот еще несколько вещей, которые я пробовал и не помогло:

  1. пробовал малую и большую скорость обучения (0,1 и 1e-8)
  2. пробовал с обучаемыми слоями SourceEstimator == True
  3. перевернутые метки (0 == синтетическая, 1 == реальная)
  4. увеличены размеры ядра и фильтра в дискриминаторе.

Я застрял на этой проблеме некоторое время, мне действительно нужны некоторые идеи.Заранее спасибо.

------ РЕДАКТИРОВАТЬ 1 -----

def initialize_uninitialized(sess):
    global_vars = tf.global_variables()
    is_initialized= sess.run([tf.is_variable_initialized(var) for var in global_vars])
    not_initialized_vars = [v for (v, f) in zip(global_vars, is_initialized) if not f]

    # for var in not_initialized_vars: # only for testing
    #    print(var.name)

    if len(not_initialized_vars):
        sess.run(tf.variables_initializer(not_initialized_vars))

self.sess = tf.Session()
## inbetween here I create data generator, model and restore pretrained model.
self.initilize_uninitialized(self.sess) 

for current_epoch in range(self.model.current_epoch_tensor.eval(self.sess), self.config.num_epochs, 1)
    self.train_epoch() # included above
    self.sess.run(self.model.increment_current_epoch_tensor)

Ответы [ 2 ]

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

Мне так и не удалось выяснить, что не так с кодом.

Мой коллега предложил попробовать ту же модель в другой изолированной среде, поэтому я переписал код с помощью библиотеки Keras.

А теперь работает.: /

Мы до сих пор не знаем, что именно не так с кодом выше - я ничего не менял.Я даже использовал один и тот же код для переноса веса и инициализации переменной.

Если кто-нибудь сталкивается с подобной проблемой, я бы предложил попробовать ту же модель в другой среде.

Или, если кто-то знает, что не так с кодом выше, поделитесь!

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

Я вижу, что вы вызываете функцию minime, а также функцию loss в session.run ().Вы должны вызывать только функцию minimal ().т.е. только self.model.disc_op, который будет внутренне вызывать функцию потерь.Кроме того, я нигде не вижу ваш вызов инициализации сеанса.Следите за тем, чтобы он вызывался только один раз.

Глядя на ваш обновленный код, я вижу, что вы приравниваете вызов tf.is_variable_initialized () к is_not_initialized.Таким образом, он инициализирует те переменные, которые уже инициализированы.

...