basic neural network in C
Framework/.DS_Store
__MACOSX/Framework/._.DS_Store
Framework/data_loading.cpp
#include "header_file.h" 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; } //Load MNIST images function void Loading_Mnist_images(string filename, vector<cv::Mat> &images) { ifstream file(filename, ios::in | ios::binary); if (file.is_open() == false) { cout << "open mnist image file error!" << endl; return; } else if (file.is_open() == true) { int magic_number = 0; int number_of_images = 0; int n_rows = 0; int n_cols = 0; //load sizeof(magic_number) to magic_number file.read((char*)&magic_number, sizeof(magic_number)); magic_number = ReverseInt(magic_number); //load number_of_images file.read((char*)&number_of_images, sizeof(number_of_images)); number_of_images = ReverseInt(number_of_images); //Find image Height file.read((char*)&n_rows, sizeof(n_rows)); n_rows = ReverseInt(n_rows); //Find image Width file.read((char*)&n_cols, sizeof(n_cols)); n_cols = ReverseInt(n_cols); cout << "Total number of images are: " << number_of_images << endl; // read image and save to images for (int i = 0; i < number_of_images; ++i) { //cv::Mat current_image = cv::Mat::zeros(n_rows, n_cols, CV_8UC1); cv::Mat current_image = cv::Mat::zeros(1,n_rows* n_cols, CV_8UC1); int current_index = 0; 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)); /*current_image.at<uchar>(r, c) = (int)temp;*/ current_image.at<uchar>(current_index) = (int)temp; current_index++; } } images.push_back(current_image); } } } // Load Mnist label function void Load_Mnist_Label(string filename, vector<int> &labels) { ifstream file(filename, ios::in | ios::binary); if (file.is_open()) { int magic_number = 0; int number_of_labels = 0; file.read((char*)&magic_number, sizeof(magic_number)); magic_number = ReverseInt(magic_number); file.read((char*)&number_of_labels, sizeof(number_of_labels)); number_of_labels = ReverseInt(number_of_labels); cout << "Total number of labels are: " << number_of_labels << endl; for (int i = 0; i < number_of_labels; ++i) { unsigned char current_label = 0; file.read((char*)¤t_label, sizeof(current_label)); labels.push_back(current_label); } } } // Give a name for each images function string GetImageName(int number, int arr[]) { string str1, str2; for (int i = 0; i < 10; i++) { if (number == i) { arr[i]++; char ch1[10]; sprintf(ch1, "%d", arr[i]); str1 = std::string(ch1); if (arr[i] < 10) { str1 = "0000" + str1; } else if (arr[i] < 100) { str1 = "000" + str1; } else if (arr[i] < 1000) { str1 = "00" + str1; } else if (arr[i] < 10000) { str1 = "0" + str1; } break; } } char ch2[10]; sprintf(ch2, "%d", number); str2 = std::string(ch2); str2 = str2 + "_" + str1; return str2; } // writing training images to train image folder void WritingTrainingIimage(vector<cv::Mat> &train_images_vector, vector<int> &train_labels_vector) { /******************************* writing training images to train image folder **************************************/ int train_count_digits[10]; for (int i = 0; i < 10; i++) train_count_digits[i] = 0; string save_train_images_path = "train_images/"; //path for train images for (int i = 0; i < train_images_vector.size(); i++) { int number = train_labels_vector[i]; string image_name = GetImageName(number, train_count_digits); image_name = save_train_images_path + image_name + ".jpg"; cv::imwrite(image_name, train_images_vector[i].reshape(0,28)); if (i % 5000 == 0) { cout << "Saving " << i << " images" << endl; } if (i == 10) { cout << "10 images are written into train images folder. If you want to continuou to write image, click Y then click Enter. Else click N then click Enter. " << std::endl; char training_button; cin >> training_button; if (training_button == 'y') { cout << "Continue to write image" << endl; continue; } else { cout << "Stop to write image" << endl; break; } } } } // writing testing images to test image folder void WritingTestingIimage(vector<cv::Mat> &test_images_vector, vector<int> &test_labels_vector) { /******************************* writing testinging image to test image folder **************************************/ int test_count_digits[10]; for (int i = 0; i < 10; i++) test_count_digits[i] = 0; string save_test_images_path = "test_images/"; //path for test images for (int i = 0; i < test_images_vector.size(); i++) { int number = test_labels_vector[i]; string image_name = GetImageName(number, test_count_digits); image_name = save_test_images_path + image_name + ".jpg"; cv::imwrite(image_name, test_images_vector[i].reshape(0, 28)); if (i % 5000 == 0) { cout << "Saving " << i << " images" << endl; } if (i == 10) { cout << "10 images are written into test images folder. If you want to continuou to write image, click Y then click Enter. Else click N then click Enter. " << std::endl; char testing_button; cin >> testing_button; if (testing_button == 'y') { cout << "Continue to write image" << endl; continue; } else { cout << "Stop to write image" << endl; break; } } } }
__MACOSX/Framework/._data_loading.cpp
Framework/header_file.h
#include <iostream> #include <fstream> #include <vector> #include <string> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> using namespace std; using namespace cv; int ReverseInt(int i); //Load MNIST images function void Loading_Mnist_images(string filename, vector<cv::Mat> &images); // Load Mnist label function void Load_Mnist_Label(string filename, vector<int> &labels); // Give a name for each images function string GetImageName(int number, int arr[]); // writing training images to train image folder void WritingTrainingIimage(vector<cv::Mat> &train_images_vector, vector<int> &train_labels_vector); // writing testing images to test image folder void WritingTestingIimage(vector<cv::Mat> &test_images_vector, vector<int> &test_labels_vector);
__MACOSX/Framework/._header_file.h
Framework/main.cpp
Framework/main.cpp
#include
"header_file.h"
#include
"Net.h"
#include
"utilis.h"
#define
MODE
1
// 0 - training mode; 1 - testing mode
#define
IMAGE_NUMBER
3000
#define
LOSS_THRESHOLD
50
using
namespace
std
;
using
namespace
cv
;
/************************** Implementation Here *******************/
/********** Function 1: Backpropogation for training use *************************/
//apply the back-propogation algorithm as described in the class
//Hint: use loop to update the parameraters interatively. The number of interations should be equal to the number of samples. In this case, it should be "image_used_to_train"
void
backPropogation
(
const
Mat
&
traing_img
,
const
Mat
&
training_label
,
Mat
&
theta_1
,
Mat
&
theta_2
,
Mat
&
bias_1
,
Mat
&
bias_2
)
{
//Input Parameters
//traing_img: the images use for training, it has 784 rows and IMAGE_NUMBER columns. Each column represents an image.
//training_label: the corresponding labels for "training_img". It has 10 rows and IMAGE_NUMBER column.
//theta_1 and theta_2: they are actually the output. You need to use the training data to iteratively update the these two matrices.
//bias_1 and bias_2: simlilary, they are the output. You need to use the training data to iteratively update the these two matrices.
}
/********** Function 2: Prediction for testing use *************************/
//Use the parameters learned (theta_1, theta_2) to compute the input sample "sample_image"
//Hint: You can use the matrix based multiplication to compute the last layer's values. Then pick up the maximum one as the final output.
void
numPrediction
(
const
Mat
&
sample_img
,
const
Mat
&
theta_1
,
const
Mat
&
theta_2
,
const
Mat
&
bias_1
,
const
Mat
&
bias_2
,
int
&
predicted_number
)
{
//Input Parameters
//sample_img: the input image for number prediction. Its dimension is 784x1
//theta_1 and theta_2 are the learned parameters
//bias_1 and bias_2 are the learned parameters
//predicted_number: the output result. You need to find the neuron with the maximum output from the last layer. So the predicted_number will be the index of that neuron
}
/********************* End of Implementation *********************/
int
main
(
int
argc
,
char
**
argv
)
{
/******************** Parameters to be learned ******************/
Mat
theta_1
;
//The matrix between layer 1 and layer 2
Mat
theta_2
;
//The matrix between layer 2 and layer 3
Mat
bias_1
;
//The vector for layer 1
Mat
bias_2
;
//The vector for layer 2
theta_1
.
create
(
100
,
784
,
CV_32FC1
);
//initialize the matrix with 100x784 dimension
theta_2
.
create
(
10
,
100
,
CV_32FC1
);
//initialize the matrix with 10x100 dimension
bias_1
.
create
(
100
,
1
,
CV_32FC1
);
//initialize the bias matrix with 100x1
bias_2
.
create
(
10
,
1
,
CV_32FC1
);
//initialize the bias matrix with 10x1
/************************* Load training data *************************/
//train_images 784 x 60000
vector
<
cv
::
Mat
>
train_images_vector
;
Loading_Mnist_images
(
"train-images.idx3-ubyte"
,
train_images_vector
);
//train_labels = 10 x 60000;
vector
<
int
>
train_labels_vector
;
Load_Mnist_Label
(
"train-labels.idx1-ubyte"
,
train_labels_vector
);
///************************* Load testing data *************************/
// //test_images 784 x 10000;
vector
<
cv
::
Mat
>
test_images_vector
;
Loading_Mnist_images
(
"t10k-images.idx3-ubyte"
,
test_images_vector
);
//train_labels 10 x 10000;
vector
<
int
>
test_labels_vector
;
Load_Mnist_Label
(
"t10k-labels.idx1-ubyte"
,
test_labels_vector
);
// Check
if
(
test_images_vector
.
size
()
!=
test_labels_vector
.
size
())
{
cout
<<
"parse MNIST test file error"
<<
endl
;
}
if
(
MODE
==
0
)
{
/************************* Prepare for training data *************************/
int
image_used_to_train
=
IMAGE_NUMBER
;
Mat
training_data_mat
=
Mat
::
zeros
(
784
,
image_used_to_train
,
CV_32FC1
);
Mat
training_data_label
=
Mat
::
zeros
(
10
,
image_used_to_train
,
CV_32FC1
);
// initialize image matrix and label matrix
for
(
int
i
=
0
;
i
<
image_used_to_train
;
i
++
)
{
Mat
GrayImage
,
BinaryImage
;
//Get the data
train_images_vector
[
i
].
copyTo
(
GrayImage
);
//Convert the data to BinaryImage
threshold
(
GrayImage
,
BinaryImage
,
1
,
1
,
CV_THRESH_BINARY
);
cv
::
transpose
(
BinaryImage
,
BinaryImage
);
BinaryImage
.
copyTo
(
training_data_mat
.
col
(
i
));
training_data_label
.
at
<
float
>
(
train_labels_vector
[
i
],
i
)
=
1
;
}
/************************* training ****************************/
//Randomly assign values to initialize the two matrices: theta_1, theta_2
cv
::
randu
(
theta_1
,
0.0
,
1.0
);
//initial all the parameters between [0, 1]
cv
::
randu
(
theta_2
,
0.0
,
1.0
);
//call the back-propogation to get the paraterms update
backPropogation
(
training_data_mat
,
training_data_label
,
theta_1
,
theta_2
,
bias_1
,
bias_2
);
/***************** Save the matrices to local files ****************/
FileStorage
fs1
(
"theta_1.xml"
,
FileStorage
::
WRITE
);
FileStorage
fs2
(
"theta_2.xml"
,
FileStorage
::
WRITE
);
fs1
<<
"theta_1"
<<
theta_1
;
fs2
<<
"theta_2"
<<
theta_2
;
fs1
.
release
();
fs2
.
release
();
}
else
{
///************************* Prepare for testing data *************************/
int
image_used_to_test
=
1
;
Mat
testing_data_mat
=
Mat
::
zeros
(
784
,
image_used_to_test
,
CV_32FC1
);
Mat
testing_data_label
=
Mat
::
zeros
(
10
,
image_used_to_test
,
CV_32FC1
);
// load the model from files
FileStorage
fs1
(
"theta_1.xml"
,
FileStorage
::
READ
);
FileStorage
fs2
(
"theta_2.xml"
,
FileStorage
::
READ
);
fs1
[
"theta_1"
]
>>
theta_1
;
fs2
[
"theta_2"
]
>>
theta_2
;
fs1
.
release
();
fs2
.
release
();
// Using mouse to get image
Draw_number
();
Mat
Draw_image
=
imread
(
"MouseDraw.jpg"
);
resize
(
Draw_image
,
Draw_image
,
Size
(
28
,
28
),
0
,
0
,
INTER_LINEAR
);
cvtColor
(
Draw_image
,
Draw_image
,
CV_BGR2GRAY
);
threshold
(
Draw_image
,
Draw_image
,
150
,
1
,
THRESH_BINARY_INV
);
//cout << Draw_image << endl;
Mat
sample_image
;
Draw_image
.
reshape
(
0
,
784
).
copyTo
(
sample_image
);
sample_image
.
convertTo
(
sample_image
,
CV_32FC1
);
/********************* Forward Prediction: *********************/
int
number
=
0
;
//Initially set to 0, you will update during the forward prediction
numPrediction
(
sample_image
,
theta_1
,
theta_2
,
bias_1
,
bias_2
,
number
);
printf
(
"Output the predicted number: \n"
);
cout
<<
number
<<
endl
;
}
char
a
;
//cin >> a;
return
0
;
}
__MACOSX/Framework/._main.cpp
Framework/t10k-images.idx3-ubyte
__MACOSX/Framework/._t10k-images.idx3-ubyte
Framework/t10k-labels.idx1-ubyte
__MACOSX/Framework/._t10k-labels.idx1-ubyte
Framework/train-images.idx3-ubyte
__MACOSX/Framework/._train-images.idx3-ubyte
Framework/train-labels.idx1-ubyte
__MACOSX/Framework/._train-labels.idx1-ubyte
Framework/utilis.h
#include "header_file.h" // Mouse callback function void on_mouse(int event, int x, int y, int flags, void* param) { static bool s_bMouseLButtonDown = false; static CvPoint s_cvPrePoint = cvPoint(0, 0);//set the orignal switch (event)// call event { case CV_EVENT_LBUTTONDOWN:// left button down s_bMouseLButtonDown = true; s_cvPrePoint = cvPoint(x, y); break; case CV_EVENT_LBUTTONUP://left button on s_bMouseLButtonDown = false; break; case CV_EVENT_MOUSEMOVE:// mouse is moving if (s_bMouseLButtonDown) { CvPoint cvCurrPoint = cvPoint(x, y);// save the point cvLine((IplImage*)param, s_cvPrePoint, cvCurrPoint, CV_RGB(0, 200, 0), 8);// connect two points s_cvPrePoint = cvCurrPoint;// set current point as the orignal point cvShowImage("Draw_Board", (IplImage*)param); } break; } } void Draw_number() { const int MAX_WIDTH = 140, MAX_HEIGHT = 140; const char *pstrSaveImageName = "MouseDraw.jpg"; IplImage *pSrcImage = cvCreateImage(cvSize(MAX_WIDTH, MAX_HEIGHT), IPL_DEPTH_8U, 3); cvSet(pSrcImage, CV_RGB(255, 255, 255)); // set the image as wight cvNamedWindow("Draw_Board", CV_WINDOW_AUTOSIZE); cvShowImage("Draw_Board", pSrcImage); cvSetMouseCallback("Draw_Board", on_mouse, (void*)pSrcImage); int c; do { c = cvWaitKey(0); if(c == 'd' || c == 'D') break; switch ((char)c) { case 'r': cvSet(pSrcImage, CV_RGB(255, 255, 255)); cvShowImage("Draw_Board", pSrcImage); break; case 's': cvSaveImage(pstrSaveImageName, pSrcImage); cout << "Image saved. Please click ESC to close the window." << endl; break; } } while (c > 0 && c != 27); cvDestroyWindow("Draw_Board"); cvReleaseImage(&pSrcImage); }