Многослойный перцептрон не сходится.

Вопрос или проблема

Я написал свой многослойный перцептрон на MATLAB, и он компилируется без ошибок. Мои обучающие данные, x, имеют значения от 1 до 360, а выходные данные, y, имеют значение $\sin(x)$.

Дело в том, что мой MLP уменьшает стоимость только в первые несколько итераций и затем застывает на уровне 0.5. Я пробовал использовать момент, но это не помогло, а увеличение слоев или увеличение нейронов вообще не дало результата. Я не понимаю, почему это происходит.

Я загрузил файлы для вашего ознакомления здесь.

Краткое содержание моего кода:

  1. Я нормализую свои входные данные, используя либо min-max, либо zscore

  2. Инициализирую случайные веса и смещение в диапазоне от -1 до 1

    for i = 1:length(nodesateachlayer)-1    
     weights{i} = 2*rand(nodesateachlayer(i),nodesateachlayer(i+1))-1; 
     bias{i} = 2*rand(nodesateachlayer(i+1),1)-1; 
    end
    
  3. Затем я делаю прямой проход, где вход умножается на веса, добавляется смещение и затем активируется с помощью функции активации (сигмоиды)

    for i = 2:length(nodesateachlayer)
         stored{i} = nactivate(bsxfun(@plus,(weights{i-1}'*stored{i-1}),bias{i-1}),activation);    
     end
    
  4. Затем рассчитываю ошибку и выполняю обратный проход

    dedp = 1/length(normy)*error;
     for i = length(stored)-1:-1:1
         dpds = derivative(stored{i+1},activation);
         deds = dpds'.*dedp;
         dedw = stored{i}*deds; 
         dedb = ones(1,rowno)*deds;
         dedp = (weights{i}*deds')';
         weights{i}=weights{i}-rate.*dedw;
         bias{i}=bsxfun(@minus,bias{i},rate.*dedb');
     end
    
  5. Я выводил стоимость на каждой итерации, чтобы увидеть снижение

Я предполагаю, что в коде что-то не так, так где может находиться ошибка?

Мое мнение по вашему вопросу заключается в том, что крошечные сети редко работают. Приведенный выше метод использует нейронную сеть для обучения функции $y=\sin(x)$. Хотя эта проблема кажется простой, нельзя ожидать, что она будет решена действительно крошечной сетью (вышеупомянутая модель использует 5-слойный MLP с скрытым размером [5,6,7], что мало).

Даже если обратное распространение реализовано правильно, будет ли модель чему-то учиться? Нет. Я предполагаю, что Tensorflow реализовал обратное распространение правильно, вот результат с использованием Tensorflow:
fig1

Видите, она почти не учится ничему. На самом деле, потери MSE очень близки к 0.5, как было указано выше.

Мое предложение — попробовать 3-слойный MLP с скрытым размером 256. Вот результат:

fig2

Вы можете видеть, что это намного лучше. Теперь MSE<0.1.

——————код———————

x_ =np.atleast_2d(np.arange(0,360,1)).T
y_ = np.atleast_2d(np.sin(x_/180*np.pi))
g = tf.Graph()
with g.as_default():
    with tf.variable_scope("mlp"):
        input_x = tf.placeholder(shape=[None, 1], dtype=tf.float32)
        input_y = tf.placeholder(shape=[None,1], dtype=tf.float32)
        layer1 = tf.layers.dense(inputs=input_x, units=256, activation=tf.nn.sigmoid)
        #layer2 = tf.layers.dense(inputs=input_x, units=6, activation=tf.nn.sigmoid)
        #layer3 = tf.layers.dense(inputs=input_x, units=7, activation=tf.nn.sigmoid)
        output_y = tf.layers.dense(inputs=layer1, units=1) # inputs=layer1
        loss = tf.losses.mean_squared_error(input_y, output_y)
        train_op = tf.train.AdagradOptimizer(0.01).minimize(loss)
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        for epoch in range(300):
            _, loss_ = sess.run((train_op, loss), feed_dict={input_x:x_, input_y:y_})
        y_hat_ = sess.run(output_y, feed_dict={input_x:x_, input_y:y_})
        print(loss_, end='\t')
plt.plot(x_,y_, 'g', x_,y_hat_,'b')
plt.legend(['ground truth', 'predicted'])

Ответ или решение

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

1. Поиск причин неполной сходимости

  1. Размер сети: Как правильно отметил один из комментаторов, размер сети может иметь значение. Вы упомянули, что используете 5 слоев с постепенным увеличением нейронов (5, 6, 7). Это может оказаться недостаточным для освоения функции ( y = \sin(x) ). Простая функция синуса требует большей выразительности модели. Попробуйте увеличить количество нейронов в скрытых слоях до 256 или больше. Простые сети, как правило, не справляются с более сложными задачами.

  2. Инициализация весов: Вы инициализируете веса и смещения в диапазоне от -1 до 1. Это может не давать хороших стартовых значений, особенно для функций активации, таких как сигмоида. Попробуйте использовать другие методы инициализации, такие как инициализация He или Xavier, которые более адаптированы к различным функциям активации.

  3. Функция активации: Использование сигмоиды может приводить к исчезающим градиентам, что делает обучение медленным и иногда невозможным. Рассмотрите возможность использования ReLU или leaky ReLU, что может помочь улучшить поток градиентов во время обратного распространения ошибки.

2. Метод обратного распространения ошибки

  1. Корректность реализации: Убедитесь, что вы корректно реализовали обратное распространение ошибки. Необходимо правильно вычислять производные и обновлять веса и смещения. Это особенно важно для многослойной сети, где ошибка должна корректно "ползти" назад через слои. В вашем коде метод вычисления градиентов может быть нарушен, особенно в части, где вы обновляете веса и смещения:

    dedw = stored{i}*deds; 
    dedb = ones(1,rowno)*deds;
    dedp = (weights{i}*deds')';

    Проверьте, правильно ли получаете градиенты по каждому параметру и корректность передачи ошибок в предыдущий слой. Также стоит добавить некоторую регуляризацию для борьбы с переобучением, если вы используете большое количество нейронов.

3. Параметры обучения

  1. Скорость обучения: Изменение скорости обучения (learning rate) может значительно повлиять на результат. Если она слишком велика, ваш алгоритм оптимизации может не сойтись, выбрасываясь из минимально возможных ошибок в процессе обучения. Возможно, стоит попробовать уменьшить скорость и оценить сходимость.

  2. Моментум: Вы уже указали, что пробовали использовать моментум, но это должно быть сделано с умом. Убедитесь, что значение моментума правильно настроено и что его использование не разгоняет ошибку.

4. Нормализация данных

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

Заключение

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

Оцените материал
Добавить комментарий

Капча загружается...