Многослойные персептроны в 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
является линейно отделимым, т.е. это может быть выполнено с использованием одного перцептрона.