OpenCV MLP UPDATE_WEIGHTS действует вяло? - PullRequest
0 голосов
/ 05 марта 2019

Я столкнулся с этой проблемой, пытаясь построить кривую обучения MLP, которую я использовал, чтобы предсказать 4 выходных значения на 30 000 выборок.Я хотел использовать UPDATE_WEIGHTS для вывода ошибки после каждой эпохи обучения.Таким образом я могу построить график и посмотреть тренды.

При обучении сети и установке критериев завершения COUNT = 1000 сеть получила ошибку ~ 5%.Проблема заключается в том, что когда я использовал UPDATE_WEIGHTS для итеративного обучения эпохи сети 1, ошибка не сходилась ни к одному значению, ни к аналогичной тенденции.

Я предоставил код ниже для простого примера, который иллюстрируетта же проблема UPDATE_WEIGHTS, просто чтобы вы могли ясно увидеть, в чем проблема.В примере используется MLP, чтобы узнать, как добавить два числа, и сравнивается итеративное обучение сети с использованием UPDATE_WEIGHTS nEpoch числа раз (network1) для переобучения сети и использования критериев завершения COUNT = nEpochs (network2).

OpenCV4.0.1
MacBook Pro 64 бит
Eclipse C ++

 // create train data
 int nTrainRows = 1000;
 cv::Mat trainMat(nTrainRows, 2, CV_32F);
 cv::Mat labelsMat(nTrainRows, 1, CV_32F);
 for(int i = 0; i < nTrainRows; i++) {
     double rand1 = rand() % 100;
     double rand2 = rand() % 100;
     trainMat.at<float>(i, 0) = rand1;
     trainMat.at<float>(i, 1) = rand2;
     labelsMat.at<float>(i, 0) = rand1 + rand2;
 }

 // create test data
 int nTestRows = 100;
 cv::Mat testMat(nTestRows, 2, CV_32F);
 cv::Mat truthsMat(nTestRows, 1, CV_32F);
 for(int i = 0; i < nTestRows; i++) {
     double rand1 = rand() % 100;
     double rand2 = rand() % 100;
     testMat.at<float>(i, 0) = rand1;
     testMat.at<float>(i, 1) = rand2;
     truthsMat.at<float>(i, 0) = rand1 + rand2;
 }

 // initialize network1 and set network parameters
 cv::Ptr<cv::ml::ANN_MLP > network1 = cv::ml::ANN_MLP::create();
 cv::Mat layersMat(1, 2, CV_32SC1);
 layersMat.col(0) = cv::Scalar(trainMat.cols);
 layersMat.col(1) = cv::Scalar(labelsMat.cols);
 network1->setLayerSizes(layersMat);
 network1->setActivationFunction(cv::ml::ANN_MLP::ActivationFunctions::SIGMOID_SYM);
 network1->setTermCriteria(cv::TermCriteria(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 1, 0));
 cv::Ptr<cv::ml::TrainData> trainData = cv::ml::TrainData::create(trainMat,cv::ml::ROW_SAMPLE,labelsMat,cv::Mat(),cv::Mat(),cv::Mat(),cv::Mat());
 network1->train(trainData);

 // loop through each epoch, one at a time, and compare error between the two methods
 for(int nEpochs = 2; nEpochs <= 20; nEpochs++) {
      // train network1 with one more epoch
      network1->train(trainData,cv::ml::ANN_MLP::UPDATE_WEIGHTS);
      cv::Mat predictions;
      network1->predict(testMat, predictions);
      double totalError = 0;
      for(int i = 0; i < nTestRows; i++)
          totalError += abs( truthsMat.at<float>(i, 0) - predictions.at<float>(i, 0) );
      double aveError = totalError / (double) nTestRows;

      //recreate network2 
      cv::Ptr<cv::ml::ANN_MLP > network2 = cv::ml::ANN_MLP::create();
      network2->setLayerSizes(layersMat);
      network2->setActivationFunction(cv::ml::ANN_MLP::ActivationFunctions::SIGMOID_SYM);
      network2->setTermCriteria(cv::TermCriteria(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, nEpochs, 0));

      // train network2 from scratch, specifying to train with nEpochs
      network2->train(trainData);
      network2->predict(testMat, predictions);
      totalError = 0;
      for(int i = 0; i < nTestRows; i++) 
          totalError += abs( truthsMat.at<float>(i, 0) - predictions.at<float>(i, 0) );
      aveError = totalError / (double) nTestRows;
 }

Я изобразил среднюю ошибку в сравнении с количеством использованных тренировочных эпох: enter image description here

Вы можете видеть, что сеть1 (с помощью UPDATE_WEIGHTS) и сеть2 (с помощью COUNT) действуют очень по-разному, даже несмотря на то, что количество обучающих эпох одинаково.Ошибка из сети 2 сходится быстрее, а сеть 1 сходится с более высокой ошибкой.Я не могу найти причину, почему это будет так, поскольку они должны быть одинаковыми?

-Tim

...