MNIST-3LNN  1.0
A simple 3-layer neural network to recognize handwritten single digit numbers from the MNIST image files.
main.c
Go to the documentation of this file.
1 /**
2  * @file main.c
3  *
4  * @mainpage MNIST 3-Layer Neural Network
5  *
6  * @brief Simple feed-forward neural network with 3 layers of nodes (input, hidden, output)
7  * using Sigmoid or Tanh activation function and back propagation to classify MNIST handwritten digit images.
8  *
9  * @details Simple feed-forward neural network with 3 layers of nodes (input, hidden, output)
10  * using Sigmoid or Tanh activation function and back propagation to classify MNIST handwritten digit images.
11  *
12  * @see [Simple 3-Layer Neural Network for MNIST Handwriting Recognition](http://mmlind.github.io/Simple_3-Layer_Neural_Network_for_MNIST_Handwriting_Recognition/)
13  * @see http://yann.lecun.com/exdb/mnist/
14  * @version [Github Project Page](http://github.com/mmlind/mnist-3lnn/)
15  * @author [Matt Lind](http://mmlind.github.io)
16  * @date August 2015
17  *
18  */
19 
20 
21 #include <stdlib.h>
22 #include <time.h>
23 
24 #include "util/screen.h"
25 #include "util/mnist-utils.h"
26 #include "util/mnist-stats.h"
27 #include "3lnn.h"
28 
29 
30 
31 /**
32  * @brief Returns a Vector holding the image pixels of a given MNIST image
33  * @param img A pointer to a MNIST image
34  */
35 
37 
38  Vector *v = (Vector*)malloc(sizeof(Vector) + (MNIST_IMG_WIDTH*MNIST_IMG_HEIGHT * sizeof(double)));
39 
41 
42  for (int i=0;i<v->size;i++)
43  v->vals[i] = img->pixel[i] ? 1 : 0;
44 
45  return v;
46 }
47 
48 
49 
50 
51 /**
52  * @brief Training the network by processing the MNIST training set and updating the weights
53  * @param nn A pointer to the NN
54  */
55 
57 
58  // open MNIST files
59  FILE *imageFile, *labelFile;
62 
63  int errCount = 0;
64 
65  // Loop through all images in the file
66  for (int imgCount=0; imgCount<MNIST_MAX_TRAINING_IMAGES; imgCount++){
67 
68  // Reading next image and its corresponding label
69  MNIST_Image img = getImage(imageFile);
70  MNIST_Label lbl = getLabel(labelFile);
71 
72  // Convert the MNIST image to a standardized vector format and feed into the network
73  Vector *inpVector = getVectorFromImage(&img);
74  feedInput(nn, inpVector);
75 
76  // Feed forward all layers (from input to hidden to output) calculating all nodes' output
78 
79  // Back propagate the error and adjust weights in all layers accordingly
80  backPropagateNetwork(nn, lbl);
81 
82  // Classify image by choosing output cell with highest output
83  int classification = getNetworkClassification(nn);
84  if (classification!=lbl) errCount++;
85 
86  // Display progress during training
87  displayTrainingProgress(imgCount, errCount, 3,5);
88 // displayImage(&img, lbl, classification, 7,6);
89 
90  }
91 
92  // Close files
93  fclose(imageFile);
94  fclose(labelFile);
95 
96 }
97 
98 
99 
100 
101 /**
102  * @brief Testing the trained network by processing the MNIST testing set WITHOUT updating weights
103  * @param nn A pointer to the NN
104  */
105 
107 
108  // open MNIST files
109  FILE *imageFile, *labelFile;
112 
113  int errCount = 0;
114 
115  // Loop through all images in the file
116  for (int imgCount=0; imgCount<MNIST_MAX_TESTING_IMAGES; imgCount++){
117 
118  // Reading next image and its corresponding label
119  MNIST_Image img = getImage(imageFile);
120  MNIST_Label lbl = getLabel(labelFile);
121 
122  // Convert the MNIST image to a standardized vector format and feed into the network
123  Vector *inpVector = getVectorFromImage(&img);
124  feedInput(nn, inpVector);
125 
126  // Feed forward all layers (from input to hidden to output) calculating all nodes' output
127  feedForwardNetwork(nn);
128 
129  // Classify image by choosing output cell with highest output
130  int classification = getNetworkClassification(nn);
131  if (classification!=lbl) errCount++;
132 
133  // Display progress during testing
134  displayTestingProgress(imgCount, errCount, 5,5);
135 // displayImage(&img, lbl, classification, 7,6);
136 
137  }
138 
139  // Close files
140  fclose(imageFile);
141  fclose(labelFile);
142 
143 }
144 
145 
146 
147 
148 
149 /**
150  * @details Main function to run MNIST-1LNN
151  */
152 
153 int main(int argc, const char * argv[]) {
154 
155  // remember the time in order to calculate processing time at the end
156  time_t startTime = time(NULL);
157 
158  // clear screen of terminal window
159  clearScreen();
160  printf(" MNIST-3LNN: a simple 3-layer neural network processing the MNIST handwritten digit images\n\n");
161 
162  // Create neural network using a manually allocated memory space
164 
165  // Training the network by adjusting the weights based on error using the TRAINING dataset
166  trainNetwork(nn);
167 
168  // Testing the during training derived network using the TESTING dataset
169  testNetwork(nn);
170 
171  // Free the manually allocated memory for this network
172  free(nn);
173 
174  locateCursor(36, 5);
175 
176  // Calculate and print the program's total execution time
177  time_t endTime = time(NULL);
178  double executionTime = difftime(endTime, startTime);
179  printf("\n DONE! Total execution time: %.1f sec\n\n",executionTime);
180 
181  return 0;
182 }
183 
184 
Dynamic data structure containing defined number of values.
Definition: 3lnn.h:27
#define MNIST_TRAINING_SET_IMAGE_FILE_NAME
MNIST image training file in the data folder.
Definition: mnist-utils.h:13
Utitlies for displaying processing details in the terminal.
FILE * openMNISTImageFile(char *fileName)
Read MNIST IMAGE file header.
Definition: mnist-utils.c:93
uint8_t pixel[MNIST_IMG_WIDTH *MNIST_IMG_HEIGHT]
Definition: mnist-utils.h:41
int main(int argc, const char *argv[])
Definition: main.c:153
Neural network functionality for a 3-layer (INPUT, HIDDEN, OUTPUT) feed-forward, back-prop NN...
void trainNetwork(Network *nn)
Training the network by processing the MNIST training set and updating the weights.
Definition: main.c:56
void displayTrainingProgress(int imgCount, int errCount, int y, int x)
Outputs reading progress while processing MNIST training images.
Definition: mnist-stats.c:74
#define MNIST_TESTING_SET_LABEL_FILE_NAME
MNIST label testing file in the data folder.
Definition: mnist-utils.h:17
Utitlies for advanced input and output to terminal screen.
void feedForwardNetwork(Network *nn)
Feeds input layer values forward to hidden to output layer (calculation and activation fct) ...
Definition: 3lnn.c:306
void backPropagateNetwork(Network *nn, int targetClassification)
Back propagates network error from output layer to hidden layer.
Definition: 3lnn.c:206
FILE * openMNISTLabelFile(char *fileName)
Read MNIST label file header.
Definition: mnist-utils.c:117
MNIST_Label getLabel(FILE *labelFile)
Returns the next label in given MNIST label file.
Definition: mnist-utils.c:159
#define MNIST_TRAINING_SET_LABEL_FILE_NAME
MNIST label training file in the data folder.
Definition: mnist-utils.h:14
#define MNIST_MAX_TESTING_IMAGES
number of images+labels in the TEST file/s
Definition: mnist-utils.h:22
double vals[]
Definition: 3lnn.h:29
int getNetworkClassification(Network *nn)
Returns the network's classification using the ID of teh node with the hightest output.
Definition: 3lnn.c:553
void locateCursor(const int row, const int col)
Set cursor position to given coordinates in the terminal window.
Definition: screen.c:57
#define MNIST_IMG_HEIGHT
image height in pixel
Definition: mnist-utils.h:24
void feedInput(Network *nn, Vector *v)
Feeds some Vector data into the INPUT layer of the NN.
Definition: 3lnn.c:320
void clearScreen()
Clear terminal screen by printing an escape sequence.
Definition: screen.c:19
#define MNIST_IMG_WIDTH
image width in pixel
Definition: mnist-utils.h:23
int size
Definition: 3lnn.h:28
#define MNIST_TESTING_SET_IMAGE_FILE_NAME
MNIST image testing file in the data folder.
Definition: mnist-utils.h:16
Network * createNetwork(int inpCount, int hidCount, int outCount)
Creates a dynamically-sized, 3-layer (INTPUT, HIDDEN, OUTPUT) neural network.
Definition: 3lnn.c:505
Vector * getVectorFromImage(MNIST_Image *img)
Returns a Vector holding the image pixels of a given MNIST image.
Definition: main.c:36
Utitlies for handling the MNIST files.
MNIST_Image getImage(FILE *imageFile)
Returns the next image in given MNIST image file.
Definition: mnist-utils.c:139
void displayTestingProgress(int imgCount, int errCount, int y, int x)
Definition: mnist-stats.c:91
Data block defining a MNIST image.
Definition: mnist-utils.h:40
#define MNIST_MAX_TRAINING_IMAGES
number of images+labels in the TRAIN file/s
Definition: mnist-utils.h:21
uint8_t MNIST_Label
Definition: mnist-utils.h:32
Dynamic data structure holding the whole network.
Definition: 3lnn.h:63
void testNetwork(Network *nn)
Testing the trained network by processing the MNIST testing set WITHOUT updating weights.
Definition: main.c:106