2009-10-14 33 views
18

Próbuję przybliżyć funkcję sinus() za pomocą sieci neuronowej, którą sam napisałem. Przetestowałem moją sieć neuronową na prostym problemie OCR i zadziałało, ale mam problem z zastosowaniem go do przybliżonego sinusa(). Mój problem polega na tym, że podczas treningu mój błąd zbiega się dokładnie na 50%, więc domyślam się, że jest całkowicie losowy.Funkcja aproksymująca z siecią neuronową

Używam jednego neuronu wejściowego dla danych wejściowych (od 0 do PI) i jednego neuronu wyjściowego dla wyniku. Mam jedną ukrytą warstwę, w której mogę zmieniać liczbę neuronów, ale obecnie próbuję około 6-10.

Mam wrażenie, że problem polega na tym, że używam funkcji transferu sigmoidowego (która jest wymagana w mojej aplikacji), która wyprowadza tylko od 0 do 1, podczas gdy wynik dla sinusa() wynosi od -1 do 1. Aby spróbować rozwiązać ten problem, próbowałem pomnożyć wynik przez 2, a następnie odjąć 1, ale to nie rozwiązało problemu. Myślę, że muszę przeprowadzić jakąś konwersję gdzieś, żeby to zadziałało.

Wszelkie pomysły?

+0

Osoby zainteresowane zapoznaniem się z wdrożeniami badawczymi aproksymacji opartej na NN, zobacz mój [artykuł badawczy na temat obliczeń przybliżonych] (https://www.academia.edu/20201007/A_Survey_Of_Techniques_for_Approximate_Computing), które mogą szczegółowo odpowiedzieć na twoje pytanie. – user984260

Odpowiedz

16

Użyj liniowej jednostki wyjściowej .

Oto prosty przykład za pomocą 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

+0

Według liniowej jednostki wyjściowej, masz na myśli obliczanie f (netto) = netto dla jednostki wyjściowej? Ponieważ próbowałem tego i nadal mam ten sam problem. – MahlerFive

+0

Dokładnie, funkcja liniowa f (x) = a * x – rcs

+0

Drobne szczegóły, ale hiperłącze r-project.org nie działa bez poprzedzania "www". –

11

Kiedy pociąg do sieci, należy unormować cel (funkcja sin) na przedziale [0,1], a następnie możesz zachować funkcję transferu sigmoidalnego.

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 
    ... 

Uwaga że mamy odwzorowane cel przed szkolenia. Po szkoleniu i symulacji sieci można odwzorować dane wyjściowe sieci.


Poniżej znajduje się kod MATLAB do zilustrowania:

%% 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

0

Nie ma powodu sieć nie powinny pracować, chociaż 6 jest zdecydowanie zaniżone dla przybliżając falę sinusoidalną. Spróbowałbym przynajmniej 10 może nawet 20.

Jeśli to nie działa, to myślę, że musisz podać więcej szczegółów na temat swojego systemu. tj. algorytm uczenia się (propagacja wsteczna?), szybkość uczenia się itd.

0

To samo zachowanie zachowuję, jeśli używam gradientu wanilii. Spróbuj użyć innego algorytmu szkoleniowego.

Jeśli chodzi o aplet Javy, zauważyłem coś interesującego: zbiegają się, gdy używam "bipolarnego sigmoidu" i zaczynam od kilku nielosowych ciężarów (takich jak wyniki z poprzedniego treningu za pomocą kwadratu funkcjonować).