Многослойные персептроны в EmguCV

Я пытаюсь реализовать нейронные сети Multi-Layer Perceptrons (MLP), используя EmguCV 3.1 (оболочка dot NET для библиотеки OpenCV) в C#(форма Windows). Чтобы попрактиковаться с этой библиотекой, я решил реализовать OR операция с использованием MLP.

Я создаю MLP методом "Initialize" и изучаю его методом "Train", как показано ниже:

private void Initialize()
{
    NETWORK.SetActivationFunction(
    ANN_MLP.AnnMlpActivationFunction.SigmoidSym);

    NETWORK.SetTrainMethod(ANN_MLP.AnnMlpTrainMethod.Backprop);

    Matrix<double> layers = new Matrix<double>(new Size(4, 1));
    layers[0, 0] = 2;
    layers[0, 1] = 2;
    layers[0, 2] = 2;
    layers[0, 3] = 1;
    NETWORK.SetLayerSizes(layers);
}

private void Train()
{
    // providing data for input

    Matrix<float> input = new Matrix<float>(4, 2);
    input[0, 0] = MIN_ACTIVATION_FUNCTION; input[0, 1] = MIN_ACTIVATION_FUNCTION;
    input[1, 0] = MIN_ACTIVATION_FUNCTION; input[1, 1] = MAX_ACTIVATION_FUNCTION;
    input[2, 0] = MAX_ACTIVATION_FUNCTION; input[2, 1] = MIN_ACTIVATION_FUNCTION;
    input[3, 0] = MAX_ACTIVATION_FUNCTION; input[3, 1] = MAX_ACTIVATION_FUNCTION;

    //providing data for output
    Matrix<float> output = new Matrix<float>(4, 1);
    output[0, 0] = MIN_ACTIVATION_FUNCTION;
    output[1, 0] = MAX_ACTIVATION_FUNCTION;
    output[2, 0] = MAX_ACTIVATION_FUNCTION;
    output[3, 0] = MAX_ACTIVATION_FUNCTION;


    // mixing input and output for training
    TrainData mixedData = new TrainData(
        input,
        Emgu.CV.ML.MlEnum.DataLayoutType.RowSample,
        output);

    // stop condition = 1 million iterations
    NETWORK.TermCriteria = new MCvTermCriteria(1000000);

    // training
    NETWORK.Train(mixedData);
}

куда MIN_ACTIVATION_FUNCTION, а также MAX_ACTIVATION_FUNCTION равны -1,7159 и 1,7159 соответственно ( согласно документации OpenCV). После 1000000 итераций (как вы видите в моем коде в состоянии остановки) я проверяю свою сеть на прогнозирование с использованием метода Predict, как показано ниже:

private void Predict()
{
    Matrix<float> input = new Matrix<float>(1, 2);
    input[0, 0] = MIN_ACTIVATION_FUNCTION;
    input[0, 1] = MIN_ACTIVATION_FUNCTION;

    Matrix<float> output = new Matrix<float>(1, 1);

    NETWORK.Predict(input, output);
    MessageBox.Show(output[0, 0].ToString());

    //////////////////////////////////////////////

    input[0, 0] = MIN_ACTIVATION_FUNCTION;
    input[0, 1] = MAX_ACTIVATION_FUNCTION;

    NETWORK.Predict(input, output);
    MessageBox.Show(output[0, 0].ToString());

    //////////////////////////////////////////////

    input[0, 0] = MAX_ACTIVATION_FUNCTION;
    input[0, 1] = MIN_ACTIVATION_FUNCTION;

    NETWORK.Predict(input, output);
    MessageBox.Show(output[0, 0].ToString());

    ////////////////////////////////////////////////

    input[0, 0] = MAX_ACTIVATION_FUNCTION;
    input[0, 1] = MAX_ACTIVATION_FUNCTION;

    NETWORK.Predict(input, output);
    MessageBox.Show(output[0, 0].ToString());
}

Вот пример того, что предсказывает NETWORK:
-0,00734469
-0,03184918
0.02080269
-0,006674092

Я ожидаю что-то вроде этого:
-1,7
+1,7
+1,7
+1,7


Что не так среди моих кодов?

Обратите внимание, что я также использую 0, 1 для MIN_ACTIVATION_FUNCTION а также MAX_ACTIVATION_FUNCTION значения, но я до сих пор не дает никаких хороших результатов.

Обновление 1: я редактирую свои коды, поскольку первый ответ направляет меня (даже я проверяю свой код с идеей, на которую ссылаются в комментариях) Теперь я получаю NaN когда звоните predict метод.

2 ответа

Решение

Согласно новой версии EmguCV ( Emgu.CV-3.1.0-r16.12) проблема заключалась в ошибке в версии 3.1.0. Теперь она исправлена ​​в Emgu.CV-3.1.0-r16.12. Загружая эту версию, я получаю правильные ответы из своей сети.

Кажется, у вас есть ошибка в предоставлении данных для вывода. использование output массив вместо input,

Я думаю, что ваши выходные ответы должны быть 2D-матрица (с 2 столбцами). Последний слой должен иметь 2 выходных нейрона, потому что у вас есть 2 класса, например (1, 0) is class "True" а также (0, 1) is class "False", Также попробуйте изменить архитектуру вашей сети. Логический оператор OR является линейно отделимым, т.е. это может быть выполнено с использованием одного перцептрона.

Другие вопросы по тегам