Ask Your Question

Revision history [back]

You can't do like that. You must give two output. Try

    vector<int> layerSizes = { 2, 4, 2 };
    vector<float> inputTrainingData = {
        0.0, 0.0,
        0.0, 1.0,
        1.0, 0.0,
        1.0, 1.0
    };
    Mat inputTrainingMat(Size(2, 4), CV_32FC1, inputTrainingData.data());
    vector<float> outputTrainingData = {
        1.0,0,
        0.0,1,
        0.0,1,
        1.0,0
    };
    Mat outputTrainingMat(Size(2, 4), CV_32FC1, outputTrainingData.data());

    Ptr<TrainData> trainingData = TrainData::create(
        inputTrainingMat,
        ROW_SAMPLE,
        outputTrainingMat
    );
    TermCriteria termCrit = TermCriteria(
        TermCriteria::Type::COUNT + TermCriteria::Type::EPS,
        220,
        0.00000001
    );

    Ptr<ANN_MLP> mlp = ANN_MLP::create();
    mlp->setLayerSizes(layerSizes);
    mlp->setActivationFunction(ml::ANN_MLP::LEAKYRELU, 0.5);
    mlp->setTrainMethod(ml::ANN_MLP::RPROP);
    mlp->setTermCriteria(TermCriteria(TermCriteria::COUNT, 10000, 0.00001));
    mlp->train(trainingData, ml::ANN_MLP::NO_OUTPUT_SCALE + ml::ANN_MLP::NO_INPUT_SCALE);

You can't do like that. You must should give two output. outputs. Try

    vector<int> layerSizes = { 2, 4, 2 };
    vector<float> inputTrainingData = {
        0.0, 0.0,
        0.0, 1.0,
        1.0, 0.0,
        1.0, 1.0
    };
    Mat inputTrainingMat(Size(2, 4), CV_32FC1, inputTrainingData.data());
    vector<float> outputTrainingData = {
        1.0,0,
        0.0,1,
        0.0,1,
        1.0,0
    };
    Mat outputTrainingMat(Size(2, 4), CV_32FC1, outputTrainingData.data());

    Ptr<TrainData> trainingData = TrainData::create(
        inputTrainingMat,
        ROW_SAMPLE,
        outputTrainingMat
    );
    TermCriteria termCrit = TermCriteria(
        TermCriteria::Type::COUNT + TermCriteria::Type::EPS,
        220,
        0.00000001
    );

    Ptr<ANN_MLP> mlp = ANN_MLP::create();
    mlp->setLayerSizes(layerSizes);
    mlp->setActivationFunction(ml::ANN_MLP::LEAKYRELU, 0.5);
    mlp->setTrainMethod(ml::ANN_MLP::RPROP);
    mlp->setTermCriteria(TermCriteria(TermCriteria::COUNT, 10000, 0.00001));
    mlp->train(trainingData, ml::ANN_MLP::NO_OUTPUT_SCALE + ml::ANN_MLP::NO_INPUT_SCALE);

I use two column to encode because opencv is used for classification not for regression so you should use one-hot

Now if you want to use your initiall code. There is a problem with initial condition for the network and I need time to investigate. I use LEAKYRELU first (10 iteration) and RELU (ml::ANN_MLP::UPDATE_WEIGHTS) :

void main() {
    vector<int> layerSizes = { 2, 2, 1 };
    vector<float> inputTrainingData;
    vector<float> outputTrainingData;
    RNG rng;
    for (int i = 0; i < 10; i++)
    {
        int in1 = rng.uniform(0, 2);
        int in2 = rng.uniform(0, 2);
        inputTrainingData.push_back(in1);
        inputTrainingData.push_back(in2);
        if (in1 == in2)
            outputTrainingData.push_back(0);
        else
            outputTrainingData.push_back(1);
    }

    Mat inputTrainingMat(Size(2, inputTrainingData.size()/2), CV_32FC1, inputTrainingData.data());
     Mat outputTrainingMat(Size(1, outputTrainingData.size()), CV_32FC1, outputTrainingData.data());

    Ptr<TrainData> trainingData = TrainData::create(
        inputTrainingMat,
        ROW_SAMPLE,
        outputTrainingMat
    );

    Ptr<ANN_MLP> mlp = ANN_MLP::create();
    mlp->setLayerSizes(layerSizes);
    mlp->setActivationFunction(ml::ANN_MLP::LEAKYRELU);
    mlp->setTrainMethod(ANN_MLP::BACKPROP, 0.1, 0.1);
    mlp->setTermCriteria(TermCriteria(TermCriteria::COUNT, 10, 0.1));
    mlp->train(trainingData, ml::ANN_MLP::NO_OUTPUT_SCALE + ml::ANN_MLP::NO_INPUT_SCALE);
    cout << "LEAKYRELU\n";
    if (mlp->isTrained()) {
        for (int i = 0; i < 10; i++) {
            Mat sample = inputTrainingMat.row(i);
            Mat result;
            mlp->predict(sample, result);
            cout << sample << " -> " << result << endl;
        }
    }

    mlp->setActivationFunction(ml::ANN_MLP::RELU);
    mlp->setTrainMethod(ANN_MLP::BACKPROP, 0.1, 0.1);
    mlp->setTermCriteria(TermCriteria(TermCriteria::COUNT, 1000, 0.001));
    mlp->train(trainingData, ml::ANN_MLP::NO_OUTPUT_SCALE + ml::ANN_MLP::NO_INPUT_SCALE+ ml::ANN_MLP::UPDATE_WEIGHTS);

    cout << "RELU\n";

    if (mlp->isTrained()) {
        for (int i = 0; i < 10; i++) {
            Mat sample = inputTrainingMat.row(i);
            Mat result;
            mlp->predict(sample, result);
            cout << sample << " -> " << result << endl;
        }
    }
    system("pause");
}

You can't do like that. You should give two outputs. Try

    vector<int> layerSizes = { 2, 4, 2 };
    vector<float> inputTrainingData = {
        0.0, 0.0,
        0.0, 1.0,
        1.0, 0.0,
        1.0, 1.0
    };
    Mat inputTrainingMat(Size(2, 4), CV_32FC1, inputTrainingData.data());
    vector<float> outputTrainingData = {
        1.0,0,
        0.0,1,
        0.0,1,
        1.0,0
    };
    Mat outputTrainingMat(Size(2, 4), CV_32FC1, outputTrainingData.data());

    Ptr<TrainData> trainingData = TrainData::create(
        inputTrainingMat,
        ROW_SAMPLE,
        outputTrainingMat
    );
    TermCriteria termCrit = TermCriteria(
        TermCriteria::Type::COUNT + TermCriteria::Type::EPS,
        220,
        0.00000001
    );

    Ptr<ANN_MLP> mlp = ANN_MLP::create();
    mlp->setLayerSizes(layerSizes);
    mlp->setActivationFunction(ml::ANN_MLP::LEAKYRELU, 0.5);
    mlp->setTrainMethod(ml::ANN_MLP::RPROP);
    mlp->setTermCriteria(TermCriteria(TermCriteria::COUNT, 10000, 0.00001));
    mlp->train(trainingData, ml::ANN_MLP::NO_OUTPUT_SCALE + ml::ANN_MLP::NO_INPUT_SCALE);

I use two column to encode because opencv is used for classification not for regression so you should use one-hot

Now if you want to use your initiall code. There is a problem with initial condition for the network and I need time to investigate. I use LEAKYRELU first (10 iteration) and RELU (ml::ANN_MLP::UPDATE_WEIGHTS) :

void main() {
    vector<int> layerSizes = { 2, 2, 1 };
    vector<float> inputTrainingData;
    vector<float> outputTrainingData;
    RNG rng;
    for (int i = 0; i < 10; i++)
    {
        int in1 = rng.uniform(0, 2);
        int in2 = rng.uniform(0, 2);
        inputTrainingData.push_back(in1);
        inputTrainingData.push_back(in2);
        if (in1 == in2)
            outputTrainingData.push_back(0);
        else
            outputTrainingData.push_back(1);
    }

    Mat inputTrainingMat(Size(2, inputTrainingData.size()/2), CV_32FC1, inputTrainingData.data());
     Mat outputTrainingMat(Size(1, outputTrainingData.size()), CV_32FC1, outputTrainingData.data());

    Ptr<TrainData> trainingData = TrainData::create(
        inputTrainingMat,
        ROW_SAMPLE,
        outputTrainingMat
    );

    Ptr<ANN_MLP> mlp = ANN_MLP::create();
    mlp->setLayerSizes(layerSizes);
    mlp->setActivationFunction(ml::ANN_MLP::LEAKYRELU);
    mlp->setTrainMethod(ANN_MLP::BACKPROP, 0.1, 0.1);
    mlp->setTermCriteria(TermCriteria(TermCriteria::COUNT, 10, 0.1));
    mlp->train(trainingData, ml::ANN_MLP::NO_OUTPUT_SCALE + ml::ANN_MLP::NO_INPUT_SCALE);
    cout << "LEAKYRELU\n";
    if (mlp->isTrained()) {
        for (int i = 0; i < 10; i++) {
            Mat sample = inputTrainingMat.row(i);
            Mat result;
            mlp->predict(sample, result);
            cout << sample << " -> " << result << endl;
        }
    }

    mlp->setActivationFunction(ml::ANN_MLP::RELU);
    mlp->setTrainMethod(ANN_MLP::BACKPROP, 0.1, 0.1);
    mlp->setTermCriteria(TermCriteria(TermCriteria::COUNT, 1000, 0.001));
    mlp->train(trainingData, ml::ANN_MLP::NO_OUTPUT_SCALE + ml::ANN_MLP::NO_INPUT_SCALE+ ml::ANN_MLP::UPDATE_WEIGHTS);

    cout << "RELU\n";

    if (mlp->isTrained()) {
        for (int i = 0; i < 10; i++) {
            Mat sample = inputTrainingMat.row(i);
            Mat result;
            mlp->predict(sample, result);
            cout << sample << " -> " << result << endl;
        }
    }
    system("pause");
}

Sometimes good network is found with only relu

    mlp->setActivationFunction(ml::ANN_MLP::RELU);
    mlp->setTrainMethod(ANN_MLP::BACKPROP, 0.1, 0.1);
    mlp->setTermCriteria(TermCriteria(TermCriteria::COUNT, 1000, 0.001));
    for (int i = 0; i < 10; i++)
    {
        mlp->train(trainingData, ml::ANN_MLP::NO_OUTPUT_SCALE + ml::ANN_MLP::NO_INPUT_SCALE);

        cout << "RELU\n";

        if (mlp->isTrained()) {
            for (int i = 0; i < 10; i++) {
                Mat sample = inputTrainingMat.row(i);
                Mat result;
                mlp->predict(sample, result);
                cout << sample << " -> " << result << endl;
            }
        }

}
    system("pause");