Приближение синусоидальной функции с нейронной сетью
В целях обучения я реализовал простую структуру нейронной сети, которая поддерживает только многослойные персептроны и простое обратное распространение. Он работает нормально для линейной классификации и обычной задачи XOR, но для приближения синусоидальной функции результаты не такие удовлетворительные.
Я в основном пытаюсь приблизить один период синусоидальной функции одним скрытым слоем, состоящим из 6-10 нейронов. Сеть использует гиперболический тангенс в качестве функции активации для скрытого слоя и линейную функцию для вывода. Результат остается довольно грубой оценкой синусоиды и требует много времени для расчета.
Я посмотрел на encog для справки, но даже при этом мне не удается заставить его работать с простым обратным распространением (при переключении на устойчивое распространение оно начинает улучшаться, но все еще намного хуже, чем сценарий super slick R, представленный в этом похожем вопросе). Так я на самом деле пытаюсь сделать что-то, что невозможно? Разве невозможно аппроксимировать синус простым обратным распространением (без импульса, без динамической скорости обучения)? Какой метод используется библиотекой нейронных сетей в R?
РЕДАКТИРОВАТЬ: Я знаю, что определенно возможно найти достаточно хорошее приближение даже с простым обратным распространением (если вам невероятно повезло с вашими начальными весами), но на самом деле мне было более интересно узнать, является ли это осуществимым подходом. Сценарий R, с которым я связан, кажется, сходится так невероятно быстро и надежно (в 40 эпохах с небольшим количеством обучающих примеров) по сравнению с моей реализацией или даже поддерживает устойчивое распространение. Мне просто интересно, могу ли я что-то сделать, чтобы улучшить алгоритм обратного распространения, чтобы добиться такой же производительности, или мне нужно искать какой-нибудь более продвинутый метод обучения?
Ответы
Ответ 1
Это может быть довольно легко реализовано с использованием современных сред для нейронных сетей, таких как TensorFlow.
Например, двухслойная нейронная сеть, использующая 100 нейронов на слой, обучается за несколько секунд на моем компьютере и дает хорошее приближение:
![enter image description here]()
Код также довольно прост:
import tensorflow as tf
import numpy as np
with tf.name_scope('placeholders'):
x = tf.placeholder('float', [None, 1])
y = tf.placeholder('float', [None, 1])
with tf.name_scope('neural_network'):
x1 = tf.contrib.layers.fully_connected(x, 100)
x2 = tf.contrib.layers.fully_connected(x1, 100)
result = tf.contrib.layers.fully_connected(x2, 1,
activation_fn=None)
loss = tf.nn.l2_loss(result - y)
with tf.name_scope('optimizer'):
train_op = tf.train.AdamOptimizer().minimize(loss)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
# Train the network
for i in range(10000):
xpts = np.random.rand(100) * 10
ypts = np.sin(xpts)
_, loss_result = sess.run([train_op, loss],
feed_dict={x: xpts[:, None],
y: ypts[:, None]})
print('iteration {}, loss={}'.format(i, loss_result))
Ответ 2
Ты определенно не пытаешься сделать невозможное. Нейронные сети универсальные аппроксиматоры - это означает, что для любой функции F и ошибки E существует некоторая нейронная сеть (требуется только один скрытый слой), который может приблизительный F с ошибкой меньше E.
Конечно, обнаружение того, что (те) сеть (сети) - совершенно другое дело. И самое лучшее, что я могу вам сказать, это проб и ошибок... Вот основная процедура:
- Разделите свои данные на две части: обучающий набор (~ 2/3) и набор тестов (~ 1/3).
- Обучите свою сеть всем элементам учебного набора.
- Протестируйте (но не тренируйте) свою сеть по всем элементам набора тестов и запишите среднюю ошибку.
- Повторяйте шаги 2 и 3 до тех пор, пока вы не достигнете минимальной ошибки тестирования (это происходит при "переобучении", когда ваша сеть начинает получать хорошие результаты обучения в ущерб всему остальному) или до тех пор, пока ваша общая ошибка не прекратится заметно уменьшая (подразумевая, что сеть так же хороша, как и она).
- Если ошибка на этом этапе приемлемо низкая, все готово. Если нет, ваша сеть не является достаточно сложной для обработки функции, для которой вы ее тренируете; добавьте более скрытые нейроны и вернитесь к началу...
Иногда изменение вашей функции активации также может иметь значение (просто не используйте линейный, поскольку это отрицает возможность добавления большего количества слоев). Но опять же, это будет проб и ошибок, чтобы увидеть, что лучше всего работает.
Надеюсь, что это поможет (и жаль, что я не могу быть более полезным)!
PS: Я также знаю, что это возможно, так как я видел, что кто-то приблизился к сети с сетью. Я хочу сказать, что она не использовала функцию активации сигмоида, но я не могу гарантировать свою память на этом счету...
Ответ 3
Один очень важный шаг, это рандомизировать данные обучения. Если вы тренируете его последовательно, то сетка забудет верхнюю часть кривой к тому времени, как она достигнет дна, и наоборот.