2012-12-15 11 views
11

Dla celów edukacyjnych zaimplementowałem prostą strukturę sieci neuronowej, która obsługuje tylko wielowarstwowe perceptrony i prostą propagację wsteczną. Działa dobrze w przypadku klasyfikacji liniowej i zwykle problemu XOR, ale w przypadku aproksymacji funkcji sinusa wyniki nie są zadowalające.Przybliżenie funkcji sinusoidalnej za pomocą sieci neuronowej

Zasadniczo próbuję zbliżyć się do jednego okresu funkcji sinusoidalnej z jedną ukrytą warstwą składającą się z 6-10 neuronów. Sieć wykorzystuje styczną hiperboliczną jako funkcję aktywacji ukrytej warstwy i liniową funkcję wyjścia. Wynik pozostaje dość przybliżoną oceną fali sinusoidalnej i wymaga dużo czasu, aby ją obliczyć.

Spojrzałem na encog odsyłającego ale nawet, że nie uda mi się dostać pracę z prostego wstecznej propagacji błędów (poprzez włączenie do sprężystego rozmnażania zaczyna się lepiej, ale nadal jest gorszy niż super śliskiego skryptu R przewidzianego in this similar question). Czy naprawdę próbuję zrobić coś, co nie jest możliwe? Czy nie jest możliwe przybliżenie sinusa za pomocą prostej propagacji wstecznej (bez pędu, bez dynamicznej szybkości uczenia się)? Jaka jest rzeczywista metoda używana przez bibliotekę sieci neuronowej w R?

EDIT: Wiem, że jest to zdecydowanie możliwe znaleźć dobre-wystarczająco zbliżenia nawet z prostego wstecznej propagacji błędów (jeśli jesteś bardzo szczęśliwy ze swoimi początkowymi ciężarami), ale faktycznie był bardziej zainteresowany, aby wiedzieć, czy jest to podejście jest możliwe. Skrypt R, do którego się połączyłem, wydaje się zbiegać tak niesamowicie szybko i niezawodnie (w 40 epokach z zaledwie kilkoma próbkami do nauki) w porównaniu do mojej implementacji lub nawet do propagacji sprężystości encog. Zastanawiam się tylko, czy jest coś, co mogę zrobić, aby poprawić algorytm wstecznej propagacji, aby uzyskać taką samą wydajność, czy muszę zajrzeć do bardziej zaawansowanej metody uczenia?

+0

Czy zdarzyło Ci się, że to działa? Wobec tego samego problemu. –

+0

Nie sądzę, ale nie pamiętam już wszystkich szczegółów, ponieważ to było 4 lata temu. Wspomniany wyżej pakiet nnet jest zaimplementowany w C i ma tylko 700 linii kodu, a następnie trochę zawijania R na nim. Być może zaglądanie w to da ci kilka pomysłów. – Muton

Odpowiedz

1

Zdecydowanie nie próbujesz tego, co niemożliwe. Sieci neuronowe są universal approximators - co oznacza, że ​​dla każdej funkcji F i błędu E, istnieje pewne sieci neuronowej (wymagałoby tylko jeden ukryty Layer), która może zbliżania F z błędem mniejszym niż E.

Oczywiście, stwierdzając, że (te) sieć (s) to zupełnie inna sprawa. A najlepsze, co mogę powiedzieć, to próba i błąd ... Oto podstawowa procedura:

  1. Podziel twoje dane na dwie części: zestaw treningowy (~ 2/3) i zestaw testowy (~ 1/3).
  2. Trenuj swoją sieć na wszystkich przedmiotach w zbiorze treningowym.
  3. Sprawdź (ale nie trenuj) swoją sieć we wszystkich elementach zestawu testowego i zanotuj błąd średni.
  4. Powtarzaj kroki 2 i 3, aż osiągniesz minimalny błąd testowania (dzieje się tak w przypadku "nadmiernego dopasowania", gdy twoja sieć zaczyna osiągać super dobre wyniki w danych treningowych ze szkodą dla wszystkich innych elementów) lub do momentu całkowitego ustąpienia błędu wyraźnie maleje (co oznacza, że ​​sieć jest tak dobra, jak się da).
  5. Jeśli błąd w tym miejscu jest akceptowalnie niski, skończysz. Jeśli nie, twoja sieć nie jest wystarczająco złożona, aby obsłużyć funkcję, dla której ją szkolisz; dodaj więcej ukrytych neuronów i wróć do początku ...

Czasami zmiana funkcji aktywacji może również spowodować różnicę (po prostu nie używaj liniowych, ponieważ neguje to siłę dodawania kolejnych warstw). Ale znowu, będzie próbą i błędem, aby zobaczyć, co działa najlepiej.

Nadzieja, która pomaga (i przykro mi, nie mogę być bardziej przydatna)!

PS: Wiem też, że jest to możliwe, ponieważ widziałem kogoś w przybliżeniu sinus z siecią. Chcę powiedzieć, że nie była przy użyciu sigmoid funkcji aktywacji, ale nie mogę zagwarantować mojej pamięci na ten rachunek ...

+0

Dzięki! To jest to, co już robię i przepraszam, jeśli byłem trochę niejasny. Wiem, że to możliwe *, ale czy próbowałem dowiedzieć się, czy prosta metoda nauki, której używam, jest * wykonalna * dla tego konkretnego problemu? – Muton

+0

@Muton - Gotcha. Moją jedyną wskazówką w tym przypadku byłoby dodanie terminu do obecnej konfiguracji. Powinien pomóc na dwóch frontach: Przyspieszy to nieco naukę i pozwoli ci uciec z miejscowych minimów. Nie mogę sobie jednak wyobrazić, że spowodowałoby to ogromną różnicę w wydajności. –

3

To może być raczej łatwo zaimplementowane przy użyciu nowoczesnych frameworków dla sieci neuronowych, takich jak TensorFlow.

Na przykład, dwuwarstwowy sieci neuronowych przy użyciu 100 neuronów na pociągach warstwowych w ciągu kilku sekund na moim komputerze i daje dobre przybliżenie:

enter image description here

kod jest dość prosty:

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

Twój kod faktycznie implementuje 3-warstwową sieć neuronową, a nie dwuwarstwową. Schemat nazewnictwa obejmuje ukryte warstwy i warstwę wyjściową, więc twoje trzy warstwy to 'x1',' x2' i 'result'. – stackoverflowuser2010