Tensorflow ReLu не работает? - PullRequest
0 голосов
/ 13 июня 2018

Я написал сверточную сеть в тензорном потоке с relu в качестве функции активации, однако он не обучается (потери постоянны как для набора данных eval, так и для train).Для разных функций активации все работает как надо.

Вот код, в котором создается nn:

def _create_nn(self):
    current = tf.layers.conv2d(self.input, 20, 3, activation=self.activation)
    current = tf.layers.max_pooling2d(current, 2, 2)
    current = tf.layers.conv2d(current, 24, 3, activation=self.activation)
    current = tf.layers.conv2d(current, 24, 3, activation=self.activation)
    current = tf.layers.max_pooling2d(current, 2, 2)
    self.descriptor = current = tf.layers.conv2d(current, 32, 5, activation=self.activation)
    if not self.drop_conv:
        current = tf.layers.conv2d(current, self.layer_7_filters_n, 3, activation=self.activation)
    if self.add_conv:
        current = tf.layers.conv2d(current, 48, 2, activation=self.activation)

    self.descriptor = current

    last_conv_output_shape = current.get_shape().as_list()
    self.descr_size = last_conv_output_shape[1] * last_conv_output_shape[2] * last_conv_output_shape[3]

    current = tf.layers.dense(tf.reshape(current, [-1, self.descr_size]), 100, activation=self.activation)
    current = tf.layers.dense(current, 50, activation=self.last_activation)

    return current

self.activiation имеет значение tf.nn.relu и self.last_activiationздесь установлено значение tf.nn.softmax

Функция потери и оптимизатор:

    self._nn = self._create_nn()

    self._loss_function = tf.reduce_sum(tf.squared_difference(self._nn, self.Y), 1)

    optimizer = tf.train.AdamOptimizer()
    self._train_op = optimizer.minimize(self._loss_function)

Я попытался изменить инициализацию переменных, передав tf.random_normal_initializer(0.1, 0.1) в качестве инициализаторов, однако это не привело к каким-либо изменениям.в функции потерь.

Буду признателен за помощь в работе этой нейронной сети с ReLu.

Редактировать: Leaky ReLu имеет ту же проблему

Редактировать: Небольшой пример, гдеМне удалось повторить ту же ошибку:

x = tf.constant([[3., 211., 123., 78.]])
v = tf.Variable([0.5, 0.5, 0.5, 0.5])
h_d = tf.layers.Dense(4, activation=tf.nn.leaky_relu)
h = h_d(x)
y_d = tf.layers.Dense(4, activation=tf.nn.softmax)
y = y_d(h)
d = tf.constant([[.5, .5, 0, 0]])

Градиенты (рассчитанные с помощью tf.gradients) для ядер и смещений h_d и y_d либо равны, либо близки к 0

Ответы [ 2 ]

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

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

Решение здесь состояло в том, чтобы просто умножить ввод, чтобы изменить его масштаб до 0-1, в случае байтов на 1 / 255.

0 голосов
/ 13 июня 2018

В очень невероятном случае все активации в каком-либо слое могут быть отрицательными для всех образцов.Они устанавливаются в ноль с помощью ReLU, и прогресс в обучении отсутствует, поскольку градиент равен нулю в отрицательной части ReLU.

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

Здесь вы используете random_normal_initializer с mean=0.1, так что, возможно, все ваши входные данные являются отрицательными и, таким образом, отображаются на отрицательные значения.Попробуйте mean=0 или измените масштаб функций ввода.

Вы также можете попробовать Leaky ReLU.Также, возможно, скорость обучения слишком мала или слишком велика.

...