오늘은 OpenCV에서 제공하는 ANN_MLP 함수에 대해서 알아보고자 한다. OpenCV의 버전은 2.4.12 버전이다. 

 MLP(다중 레이어 퍼샙트론)에 대한 설명은 나중에 기회가 된다면 설명하도록 하고 어떻게 함수가 작동하는지 살펴보자.

  ML에서 모든 뉴런은 학습 알고리즘에 영향을 받지 않는 활성 함수를 가지게 되는데, 맨처음 "알파와 베타값"을 설정하게 된다. 시그모이드 함수의 경우 (1,1)이 기본값이다.

1. 시그모이드 함수 : f(x)=\beta*(1-e^{-\alpha x})/(1+e^{-\alpha x})

2. 가우시안 함수 : f(x)=\beta e^{-\alpha x*x}


  훈련된 네트워크는 다음과 같이 작동한다.

1. 특징 벡터를 input으로 받는다. 벡터의 사이즈는 input layer의 값과 동일하다.

2. input의 값을 첫번째 hidden layer로 보낸다.

3. 가중치와 활성함수를 사용하여 hidden layer의 출력을 계산한다.

4. 출력을 다음 layer로 보내며 최종 output layer까지 이를 반복하여 계산한다.

  그러므로, network를 계산하기 위해서는, 모든 레이어의 가중치 값을 알아야 한다. 이때 가중치는 훈련 알고리즘에 의해서 계산된다. 훈련알고리즘은 training set(훈련데이터)를 받고, 입력 값(훈련데이터)이 최종 값(레이블)과 같도록 가중치를 조절한다. 

  더 큰 network 크기(hidden layer의 숫자와 크기)는 network가 좀더 유연하도록 한다. 

  ML은 다중 레이어 퍼셉트론을 훈련하는 두가지 알고리즘을 가지고 있다. 첫번째는 classical random sequential back-propagation algorithm 이고, 두번째는(기본값) bath RPROP algorithm이다. 해당 알고리즘에 대한 논문은 아까 사이트에서 확인하기 바란다.

  1. 생성함수 

 생성함수는 다음과 예와 같이 생성하면된다.

CvANN_MLP bpn(layer_size, CvANN_MLP::SIGMOID_SYM, 1, 1);

파라미터 설명

1. LayerSizes : 정수 벡터로써, input, hidden, output layer의 각각의 neurons 숫자를 의미

2. activateFunc : 활성함수 선택

3. fparam1 : 활성함수의 알파 값

4. fparam2 : 활성함수의 베타 값

이 함수를 통해 MLP network with the specified topology를 만들고 모든 neuron에 같은 활성함수를 할당한다.


2. 파라미터 생성


파라미터 생성은 위와 같이 한다. 다음은 예이다.

CvTermCriteria term = cvTermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 5000, 0.001);

CvANN_MLP_TrainParams train_params = CvANN_MLP_TrainParams(term, CvANN_MLP_TrainParams::BACKPROP, 0.1, 0.1);

파라미터 설명 :

1. term_crit : 훈련 알고리즘의 종료 기준이다. 최대 반복 수 또는, 얼마나 많이 변화시킬 건지(훈련시 조정 값)를 정한다.

2. train_Method : back-propagation, RPROP 두가지 방식을 사용한다

3. param1 : RPROP에 대해서는 rp_dw0 // BACKPROP에 대해서는 bp_dw_scale

4. param2 : RPROP에 대해서는 rp_dw_min // BACKPROP에 대해서는 bp_moment_scale

3, 4번 파라미터에 대해서는 논문을 읽어야 하지만, 안읽었기에 간단히 설명하면,

* RPROP 의 파라미터

rp_dw0 : 최초의 가중치 값

rp_dw_plus : 가중치 조정시 얼마나 더할건지?

rp_dw_minus : 가중치 조정시 얼마나 뺄건지?

rp_dw_min : 가중치의 최소 한계

rp_dw_max : 가중치의 최대 한계

Back-Propagation의 파라미터

bp_dw_scale : 가중치의 세기, 추천 값은 0.1

bp_moment_scale : 잘모르겟는데 추천값은 0.1 (0~1사이의 값을 가짐)


3. 훈련





----------------------------------------------------------------------------

아직 미완성된 글입니다. 오류가 있을 수 있어요. 아니 분명 있을 거에요

'프로그래밍 > OpenCV' 카테고리의 다른 글

Mnist with OpenCV (1)  (7) 2016.04.29


Mnist 시작하기 (1)

 C++과 OpenCV를 활용하여 Mnist를 하려고 하니, 자료 찾기가 너무 힘들어서 공유하고자 만들었다.

우선, Mnist의 데이터 셋은 Yann LeCun 사이트에 있다. 

해당 사이트에서 트레이닝할 이미지인 train-images.idx3-ubyte 파일과 해당 레이블인 train-labels.idx1-ubyte 파일을 받을 수 있다. 

테스트 파일도 있지만 그건 나중에 하기로 하자.


train-images.idx3-ubyte 파일의 구조는 다음과 같다.

: Unsigned char, 28 x 28 매트릭스

 8

 1

 0

 234

96 

시작!

시작! 

앞의 (unsigned char) 8칸이 헤더이며, 그 이후부터는 데이터가 시작된다. 데이터의 내용은 다음과 같다. 

 28 x 28 매트릭스인 것을 감안하여 약간 비슷하게 출력 해보았는데 실제로 제일 위의 글씨와 동일한 순서로 나오는 것을 확인 할 수 있다. 

 소스에 의하면, arr[i][j] : i는 몇번째 숫자 혹은 알파벳 인지? j는 해당 숫자 혹은 알파벳의 픽셀값 이다.

  

train-labels.idx1-ubyte 파일 구조는 다음과 같다.

 8

 1

 0

 234

96 

5

0

 사실 위의 이미지의 파일 구조와 동일하고, 시작 되는 부분부터, 5, 0, 4, 1, 9 와 같은 해당 이미지에 대한 레이블이 등장한다.


 이를 가지고 특징 추출 후에 서로 매칭시켜서 나중에 CNN이나, SVM을 통해 학습 시키면 될 것 같다.


소스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
 
using namespace std;
int ReverseInt(int i);
void ReadMNIST(int NumberOfImages, int DataOfAnImage, vector<vector<double>> &arr);
void ReadMNISTLabel(vector<unsigned char> &arr);
 
int main()
{
    vector<vector<double>> ai;
    vector<unsigned char> al;
    ReadMNIST(10000784, ai);                // 훈련데이터를 불러옴
    ReadMNISTLabel(al);                        // 레이블을 읽어 옴
 
    return 0;
}
 
 
int ReverseInt(int i)
{
    unsigned char ch1, ch2, ch3, ch4;
    ch1 = i & 255;
    ch2 = (i >> 8) & 255;
    ch3 = (i >> 16) & 255;
    ch4 = (i >> 24) & 255;
    return((int)ch1 << 24+ ((int)ch2 << 16+ ((int)ch3 << 8+ ch4;
}
void ReadMNIST(int NumberOfImages, int DataOfAnImage, vector<vector<double>> &arr)   // MNIST데이터를 읽어온다.
{
    arr.resize(NumberOfImages, vector<double>(DataOfAnImage));
    ifstream file("train-images.idx3-ubyte", ios::binary);
    if (file.is_open())
    {
        int magic_number = 0;
        int number_of_images = 0;
        int n_rows = 0;
        int n_cols = 0;
 
        file.read((char*)&magic_number, sizeof(magic_number));
        magic_number = ReverseInt(magic_number);
        file.read((char*)&number_of_images, sizeof(number_of_images));
        number_of_images = ReverseInt(number_of_images);
        file.read((char*)&n_rows, sizeof(n_rows));
        n_rows = ReverseInt(n_rows);
        file.read((char*)&n_cols, sizeof(n_cols));
        n_cols = ReverseInt(n_cols);
 
        char inputstring[1000];
        for (int i = 0; i<10000++i)
        {
            for (int r = 0; r<n_rows; ++r)
            {
                for (int c = 0; c<n_cols; ++c)
                {
                    unsigned char temp = 0;
                    file.read((char*)&temp, sizeof(temp));
                    arr[i][(n_rows*r) + c] = (double)temp;
                }
            }
        }
    }
}
 
void ReadMNISTLabel(vector<unsigned char> &arr){                // 레이블을 읽어온다.
    ifstream file("train-labels.idx1-ubyte");
    for (int i = 0; i<10000++i)
    {
        unsigned char temp = 0;
        file.read((char*)&temp, sizeof(temp));
        if (i > 7)
            arr.push_back((unsigned char)temp);
 
    }
}
 
cs



참고 논문 및 사이트

1. Handwritten digits recognition using OpenCV, Vincent Neiger (2015)

2. https://compvisionlab.wordpress.com/2014/01/01/c-code-for-reading-mnist-data-set/ 

'프로그래밍 > OpenCV' 카테고리의 다른 글

Mnist with OpenCV (2)  (0) 2016.04.30

+ Recent posts