Нейронная сеть выводит nan, если задано слишком много скрытых слоев - PullRequest
0 голосов
/ 25 августа 2018

В настоящее время я создаю библиотеку машинного обучения.

Суть проблемы: когда я добавляю слишком много (и слишком больших) скрытых слоев в NN, он выводит NAN или -NAN. Почему это происходит? Могу ли я сделать так, чтобы этого не произошло? Если я не могу, что я могу / должен сделать, чтобы библиотека профессионально с этим справилась?

Один из модульных тестов библиотеки (полная шкала) выглядит следующим образом:

struct testTrainWithMultipleLayers : public ZNN::NeuralNetwork<double>
{
    ZNN::NeuralNetwork<double> b;
    std::vector<std::vector<double>> input{{1, 0}, {0, 1}, {0, 0}, {1, 1}};
    std::vector<std::vector<double>> target{{1}, {1}, {0}, {0}};
    testTrainWithMultipleLayers()
    {
        withNeuralNetwork();
        trainForNIterations(1000);
        requireCorrectOutputs();
    }

    void withNeuralNetwork()
    {
        b.setInputLayerSize(2);
        b.addHiddenLayer(50);
        b.setOutputLayerSize(1);
        b.setLearningRate(0.7);
        b.setNormalization(ZNN::Fermi<double>());
    }

    void trainForNIterations(size_t iterations)
    {
         /////train the neural networks for so and so many iterations
    }

    void requireCorrectOutputs()
    {
        ///check the expected values were correctly approximated
    }
};

Тест проходит хорошо! Но когда я изменяю withNeuralNetwork на это:

    void withNeuralNetwork()
    {
        b.setInputLayerSize(2);
        b.addHiddenLayer(50);
        b.addHiddenLayer(50);
        b.addHiddenLayer(50);
        b.addHiddenLayer(50);
        b.addHiddenLayer(50);
        b.addHiddenLayer(50);
        b.addHiddenLayer(50);
        b.addHiddenLayer(50);
        b.addHiddenLayer(50);
        b.addHiddenLayer(50);
        b.addHiddenLayer(50);
        b.setOutputLayerSize(1);
        b.setLearningRate(0.7);
        b.setNormalization(ZNN::Fermi<double>());
    }

Вывод моего модульного теста выглядит следующим образом:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test is a Catch v2.3.0 host application.
Run with -? for options

-------------------------------------------------------------------------------
Neural Network
-------------------------------------------------------------------------------
test_NN.hpp:9
...............................................................................

test_NN.hpp:263: FAILED:
  CHECK( Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION )
with expansion:
  Approx( nan ) == 2.0

test_NN.hpp:264: FAILED:
  CHECK( Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION )
with expansion:
  Approx( nan ) == 2.0

test_NN.hpp:265: FAILED:
  CHECK( Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION )
with expansion:
  Approx( nan ) == 1.0

test_NN.hpp:266: FAILED:
  CHECK( Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION )
with expansion:
  Approx( nan ) == 1.0

===============================================================================
test cases:  5 |  4 passed | 1 failed
assertions: 50 | 46 passed | 4 failed

NN выводит NAN или -NAN (в зависимости от настройки)


Возможно, стоит отметить, что это происходит не только с моим конкретным модульным тестом, но и с каждым NN-приложением, которое я создал с использованием этой библиотеки (что до сих пор не было слишком большим делом, как я мог уменьшить размер NN, пока он не заработает).


Я обнаружил, где это происходит в первый раз: это происходит в функции, которая изменяет веса нейрона, алгоритм получает производную, равную nan, что превращает весь NN-каскад в выходной NAN.

Я убедился, что деление на 0 не производится. Единственное деление во всем коде NN - это 1/2 * error, используемое для вычисления ошибки NN и деления в нормализации, но я убедился, что там тоже нет деления на 0. Или скорее: при решении для exp (x) = 0, х не определено


Код юнит теста здесь: https://github.com/Wittmaxi/ZENeural/blob/master/library/tests/test_NN.cpp#L220


Редактировать

Это также происходит, когда я изменяю withNeuralNetwork на это:

    void withNeuralNetwork()
    {
        b.setInputLayerSize(2);
        b.addHiddenLayer(5000);
        b.setOutputLayerSize(1);
        b.setLearningRate(0.7);
        b.setNormalization(ZNN::Fermi<double>());
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...