1 | initial version |
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);
2 | No.2 Revision |
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");
}
3 | No.3 Revision |
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");