Аппроксимирующая функция с нейронной сетью
Я пытаюсь аппроксимировать функцию sine() с помощью нейронной сети, которую я написал сам. Я уже тестировал свою нейронную сеть по простой проблеме OCR, и это сработало, но у меня возникли проблемы с ее применением для аппроксимации синуса(). Моя проблема заключается в том, что во время обучения моя ошибка сходится ровно на 50%, поэтому я предполагаю, что она полностью случайна.
Я использую один входной нейрон для ввода (от 0 до PI) и один выходной нейрон для результата. У меня есть один скрытый слой, в котором я могу варьировать количество нейронов, но в настоящее время я пытаюсь использовать 6-10.
У меня такое чувство, потому что я использую функцию передачи сигмоида (которая является требованием в моем приложении), которая выводит только от 0 до 1, тогда как выход для синуса() находится между -1 и 1. Для попробуйте исправить это, я попытался умножить результат на 2, а затем вычесть 1, но это не устранило проблему. Я думаю, что я должен кое-что сделать, чтобы сделать эту работу.
Любые идеи?
Ответы
Ответ 1
Используйте линейный выходной блок.
Вот простой пример: R:
set.seed(1405)
x <- sort(10*runif(50))
y <- sin(x) + 0.2*rnorm(x)
library(nnet)
nn <- nnet(x, y, size=6, maxit=40, linout=TRUE)
plot(x, y)
plot(sin, 0, 10, add=TRUE)
x1 <- seq(0, 10, by=0.1)
lines(x1, predict(nn, data.frame(x=x1)), col="green")
![neural net prediction]()
Ответ 2
Когда вы тренируете сеть, вы должны нормализовать цель (функцию sin) до диапазона [0,1], тогда вы можете сохранить функцию передачи сигмоида.
sin(x) in [-1,1] => 0.5*(sin(x)+1) in [0,1]
Train data:
input target target_normalized
------------------------------------
0 0 0.5
pi/4 0.70711 0.85355
pi/2 1 1
...
Обратите внимание, что мы сопоставили цель перед обучением. Как только вы тренируете и имитируете сеть, вы можете отобразить выходные данные сети.
Ниже приведен код MATLAB для иллюстрации:
%% input and target
input = linspace(0,4*pi,200);
target = sin(input) + 0.2*randn(size(input));
% mapping
[targetMinMax,mapping] = mapminmax(target,0,1);
%% create network (one hidden layer with 6 nodes)
net = newfit(input, targetMinMax, [6], {'tansig' 'tansig'});
net.trainParam.epochs = 50;
view(net)
%% training
net = init(net); % init
[net,tr] = train(net, input, targetMinMax); % train
output = sim(net, input); % predict
%% view prediction
plot(input, mapminmax('reverse', output, mapping), 'r', 'linewidth',2), hold on
plot(input, target, 'o')
plot(input, sin(input), 'g')
hold off
legend({'predicted' 'target' 'sin()'})
![network]()
![output]()
Ответ 3
Нет причин, по которым ваша сеть не должна работать, хотя 6 определенно находится на нижней стороне для приближения синусоидальной волны. Я попробую хотя бы 10, может быть, даже 20.
Если это не сработает, я думаю, вам нужно больше узнать о вашей системе. т.е. алгоритм обучения (обратное распространение?), скорость обучения и т.д.
Ответ 4
Я получаю такое же поведение, если использую ванильный градиентный спуск. Попробуйте использовать другой алгоритм обучения.
Что касается апплета Java, я заметил что-то интересное: он сходится, если я использую "биполярный сигмоид", и я начинаю с некоторых неслучайных весов (например, результаты предыдущего обучения с использованием функции Quadratic).