Выполнение примера MNIST с mlpack - PullRequest
0 голосов
/ 18 сентября 2018

Я бы хотел сделать простой пример для ознакомления с mlpack. Простой пример - тренировка ДНК с помощью MNist Digits - классического ml-hello world case: -)

Мне удалось подготовить все изображения с помощью opencv-фильтров - результат одноканальный оттенки серого opencv :: mat matrix.

Мне также удалось преобразовать значения пикселей в матрицу броненосца arma :: mat и маркировать это "картинки". Но где-то в последних двух операциях я допустил ошибку.

Я получил N примеров и М входных нейронов. IN означает «Входной Нейрон»
OL означает «OutputLabel»
Ex означает «Пример»
Структура моих данных поезда такова:

arma::mat TrainSet = {{IN_1/Ex_1,IN_/Ex_2,IN_1/Ex_3,...,IN_1/Ex_N},
                      {IN_2/Ex_1, IN_2/Ex_2, IN_2/Ex_3,...,IN_2/Ex_N},
                      {...},
                      {IN_M/Ex_1, IN_M/Ex_2, IN_M/Ex_3,...,IN_M/Ex_N}}`

arma::mat LabelSet = {OL_Ex_1, OL_Ex_2, ..., OL_Ex_N}

Обучение моей сети приводит к ошибке.

Error training artificial neural network! Error details: Mat::operator(): index out of bounds

Я совершенно уверен, что структура моего поезда и стека этикеток неверна. Кто-нибудь знает, что я сделал не так?

Я попытался последовать этому примеру и перевести его на мой случай: http://www.mlpack.org/docs/mlpack-git/doxygen/cnetutorial.html

Вот изображение визуальной студии, показывающее структуру моего поезда: enter image description here

Вот фотография визуальной студии, показывающая структуру моих этикеток: enter image description here



Спасибо за любую помощь.

С уважением, Jan

Это мой код:

#pragma region Includings
#include <iostream>
#include <stdlib.h>
#include <exception>
#include <string>
#include "opencv2/opencv.hpp"
#include <mlpack\\core.hpp>
#include <mlpack/methods/ann/layer/layer.hpp>
#include <mlpack/methods/ann/ffn.hpp>
#include <mlpack/core/optimizers/cne/cne.hpp>
#pragma endregion

#pragma region Globals
std::string TrainFolder = "C:\\HomeC\\MNist\\MNist\\train-labels\\";
#pragma endregion

#pragma region Structs
typedef struct TInputPair {
    double Value;
    int Index;
};

typedef struct TDigitPairExample {
    TInputPair* InputPairArray;
    int nNonZero;
    char OutputValue;
};
#pragma endregion

#pragma region Identifier
void DisplayImage(cv::Mat* Img, std::string Title = "CV::DefaultForm");
std::vector<TDigitPairExample> GenerateTrainingSet(std::string TrainFolder, int nExamplesPerClass, bool DisplayAtWindow = false);
void DisplayImage(cv::Mat* Img, std::string Title, int Delay = 0);
TInputPair* MatToArray(cv::Mat* img, int* nEntries);
int CharToOutputInt(char c);
void TransferDataToMLPack(std::vector<TDigitPairExample>* ExStack, arma::mat* DataStack, arma::mat* LabelStack, int nInput);
typedef uchar Pixel;
#pragma endregion

int main() {
#pragma region Get training examples from images
std::vector<TDigitPairExample> TrainExamples = GenerateTrainingSet(TrainFolder, 101);
#pragma endregion

#pragma region Convert training vector to armadillo matrix
arma::mat trainset, labels;
TransferDataToMLPack(&TrainExamples, &trainset, &labels, 784);
#pragma endregion

#pragma region Define network
mlpack::ann::FFN<mlpack::ann::NegativeLogLikelihood<> > network;
network.Add<mlpack::ann::Linear<> >(784, 784);
network.Add<mlpack::ann::SigmoidLayer<> >();

network.Add<mlpack::ann::Linear<> >(784, 10);
network.Add<mlpack::ann::LogSoftMax<> >();
#pragma endregion

#pragma region Train network
try {
    network.Train(trainset, labels);
}catch (const std::exception& e) {
    std::cout << "Error training artificial neural network!" << std::endl << "Error details: " << e.what() << std::endl;
}
#pragma endregion

std::cout << "Application finished. Press ENTER to exit..." << std::endl;
std::cin.get();
}

#pragma region Private_regions
void DisplayImage(cv::Mat* Img, std::string Title, int Delay) {

/***************/
/*Define window*/
/***************/
cv:cvNamedWindow(Title.c_str(), cv::WINDOW_AUTOSIZE);
cv::imshow(Title.c_str(), *Img);
cv::waitKey(Delay);
//cv::destroyWindow(Title.c_str());

return;
}

TInputPair* MatToArray(cv::Mat* img, int* nEntries) {
uchar* ptr = nullptr, *dptr = nullptr;
TInputPair* InPairArr = nullptr;
int j = 0;

if (img->isContinuous()) {
    ptr = img->ptr<uchar>();
}else { return nullptr; }

InPairArr = (TInputPair*)malloc((img->cols) * (img->rows) * sizeof(TInputPair));
if (InPairArr == nullptr) { return nullptr; }

for (int i = 0; i < (img->rows)*(img->cols); i++) { 
    //std::cout << "Index_" + std::to_string(i) + "; " + std::to_string(ptr[i]) << std::endl; 
    if (ptr[i] != 255) { InPairArr[j].Index = i; InPairArr[j].Value = (double)(255 - ptr[i]) / 255.0; j++; }
}

InPairArr = (TInputPair*)realloc(InPairArr, j * sizeof(TInputPair));
*nEntries = j;

return InPairArr;
}

std::vector<TDigitPairExample> GenerateTrainingSet(std::string TrainFolder, int nExamplesPerClass, bool DisplayAtWindow) {
/********/
/*Localc*/
/********/
int nEntries = 0;
cv::Mat imgMod, imgGrad, imgInv, ptHull, imgHull, imgResize;
std::vector<std::vector<cv::Point>> contours;
std::vector<TDigitPairExample> TrainExamples;
TDigitPairExample TDPE;

for (int i = 1, j = 0;; i++) {
    /**************/
    /*Reading file*/
    /**************/
    cv::Mat imgOrig = cv::imread(TrainFolder + std::to_string(j) + "_" + std::to_string(i) + ".bmp", cv::IMREAD_GRAYSCALE);
    if (imgOrig.empty() || i > 100) { j++; i = 1; if (j > 9) { break; } continue; }




    /****************/
    /*Build negative*/
    /****************/
    cv::subtract(cv::Scalar::all(255.0), imgOrig, imgMod);





    /*****************/
    /*Cut by treshold*/
    /*****************/
    cv::threshold(imgMod, imgMod, 230.0, 255.0, cv::THRESH_BINARY);





    /**************/
    /*Get contours*/
    /**************/
    //cv::findContours(imgMod, contours, cv::CHAIN_APPROX_NONE, 1);
    //cv::Scalar color = cv::Scalar(255, 0, 0);
    //cv::drawContours(imgMod, contours, -1, color, 1, 8);



    //cv::Laplacian(imgOrig, imgGrad, 16, 1, 1.0, 0.0, cv::BORDER_REFLECT);
    /********************/
    /*Resize and display*/
    /********************/
    cv::resize(imgMod, imgResize, cv::Size(300, 300), .0, .0, cv::INTER_LINEAR);
    TDPE.InputPairArray = MatToArray(&imgMod, &nEntries);
    TDPE.nNonZero = nEntries;
    TDPE.OutputValue = std::to_string(j).c_str()[0];
    TrainExamples.push_back(TDPE);
    if (DisplayAtWindow) { DisplayImage(&imgResize, std::string("After inversion"), 5); }
}

return TrainExamples;
}

int CharToOutputInt(char c) {
switch (c) {
    case '0': return 0;
    case '1': return 1;
    case '2': return 2;
    case '3': return 3;
    case '4': return 4;
    case '5': return 5;
    case '6': return 6;
    case '7': return 7;
    case '8': return 8;
    case '9': return 9;
    default: throw new std::exception();
}
}

void TransferDataToMLPack(std::vector<TDigitPairExample>* ExStack, arma::mat* DataStack, arma::mat* LabelStack, int nInput) {
    *DataStack = arma::zeros(nInput, ExStack->size());
    *LabelStack = arma::zeros(1, ExStack->size()); /*...edit...*/

    TDigitPairExample DPE;
    TInputPair TIP;

    /*Looping all digit examples*/
    for (int i = 0; i < ExStack->size(); i++) {
        DPE = (*ExStack)[i];

        /*Looping all nonZero pixle*/
        for (int j = 0; j < DPE.nNonZero; j++) {
            TIP = DPE.InputPairArray[j];
            try {
                (*DataStack)(TIP.Index, i) = TIP.Value;
            }catch (std::exception& ex) {
                std::cout << "Error adding example[" << std::to_string(j) << "] to training stack!" << std::endl <<
                    "Error details: " << ex.what() << std::endl;
            }
        }

        /*Adding label*/
        try {
            (*LabelStack)(0, i) = CharToOutputInt(DPE.OutputValue); /*...edit...*/
        }catch (std::exception& ex) {
            std::cout << "Error adding example[" << std::to_string(i) << "] to label stack!" << std::endl <<
                "Error details: " << ex.what() << std::endl;
        }
    }

    return;
}
#pragma endregion

Ответы [ 2 ]

0 голосов
/ 19 сентября 2018

Хорошо, спасибо Маркусу, я нашел ошибку.Метка "0" не допускается.Я просто изменил метки на:
1 ==> Ноль
2 ==> Один
3 ==> Два
...
10 => Девять

Это сработало.

0 голосов
/ 19 сентября 2018

Функция потерь NegativeLogLikelihood предполагает, что цель находится в диапазоне [1, N], поэтому вам придется увеличить возвращаемое значение CharToOutputInt.Если вы еще этого не видели, есть интересный пример: mlpack - DigitRecognizerCNN , который также может быть полезен.

...