MNIST-1LNN  1.0
A simple 1-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 1-Layer Neural Network
5  *
6  * @brief Main characteristics: Only 1 layer (= input layer), no hidden layer. Feed-forward only.
7  * No Sigmoid activation function. No back propagation.\n
8  *
9  * @details Learning is achieved simply by incrementally updating the connection weights based on the comparison
10  * with the desired target output (supervised learning).\n
11  *
12  * Its performance (success rate) of 85% is far off the state-of-the-art techniques (surprise, surprise)
13  * but close the Yann Lecun's 88% when using only a linear classifier.
14  *
15  * @see [Simple 1-Layer Neural Network for MNIST Handwriting Recognition](http://mmlind.github.io/Simple_1-Layer_Neural_Network_for_MNIST_Handwriting_Recognition/)
16  * @see http://yann.lecun.com/exdb/mnist/
17  * @version [Github Project Page](http://github.com/mmlind/mnist-1lnn/)
18  * @author [Matt Lind](http://mmlind.github.io)
19  * @date July 2015
20  *
21  */
22 
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <math.h>
28 #include <time.h>
29 
30 #include "screen.h"
31 #include "mnist-utils.h"
32 #include "mnist-stats.h"
33 #include "1lnn.h"
34 
35 
36 
37 
38 
39 
40 
41 /**
42  * @details Trains a layer by looping through and training its cells
43  * @param l A pointer to the layer that is to be training
44  */
45 
46 void trainLayer(Layer *l){
47 
48  // open MNIST files
49  FILE *imageFile, *labelFile;
52 
53 
54  // screen output for monitoring progress
55  displayImageFrame(5,5);
56 
57  int errCount = 0;
58 
59  // Loop through all images in the file
60  for (int imgCount=0; imgCount<MNIST_MAX_TRAINING_IMAGES; imgCount++){
61 
62  // display progress
63  displayLoadingProgressTraining(imgCount,3,5);
64 
65  // Reading next image and corresponding label
66  MNIST_Image img = getImage(imageFile);
67  MNIST_Label lbl = getLabel(labelFile);
68 
69  // set target ouput of the number displayed in the current image (=label) to 1, all others to 0
70  Vector targetOutput;
71  targetOutput = getTargetOutput(lbl);
72 
73  displayImage(&img, 6,6);
74 
75  // loop through all output cells for the given image
76  for (int i=0; i < NUMBER_OF_OUTPUT_CELLS; i++){
77  trainCell(&l->cell[i], &img, targetOutput.val[i]);
78  }
79 
80  int predictedNum = getLayerPrediction(l);
81  if (predictedNum!=lbl) errCount++;
82 
83  printf("\n Prediction: %d Actual: %d ",predictedNum, lbl);
84 
85  displayProgress(imgCount, errCount, 3, 66);
86 
87  }
88 
89  // Close files
90  fclose(imageFile);
91  fclose(labelFile);
92 
93 }
94 
95 
96 
97 
98 /**
99  * @details Tests a layer by looping through and testing its cells
100  * Exactly the same as TrainLayer() but WITHOUT LEARNING.
101  * @param l A pointer to the layer that is to be training
102  */
103 
104 void testLayer(Layer *l){
105 
106  // open MNIST files
107  FILE *imageFile, *labelFile;
110 
111 
112  // screen output for monitoring progress
113  displayImageFrame(7,5);
114 
115  int errCount = 0;
116 
117  // Loop through all images in the file
118  for (int imgCount=0; imgCount<MNIST_MAX_TESTING_IMAGES; imgCount++){
119 
120  // display progress
121  displayLoadingProgressTesting(imgCount,5,5);
122 
123  // Reading next image and corresponding label
124  MNIST_Image img = getImage(imageFile);
125  MNIST_Label lbl = getLabel(labelFile);
126 
127  // set target ouput of the number displayed in the current image (=label) to 1, all others to 0
128  Vector targetOutput;
129  targetOutput = getTargetOutput(lbl);
130 
131  displayImage(&img, 8,6);
132 
133  // loop through all output cells for the given image
134  for (int i=0; i < NUMBER_OF_OUTPUT_CELLS; i++){
135  testCell(&l->cell[i], &img, targetOutput.val[i]);
136  }
137 
138  int predictedNum = getLayerPrediction(l);
139  if (predictedNum!=lbl) errCount++;
140 
141  printf("\n Prediction: %d Actual: %d ",predictedNum, lbl);
142 
143  displayProgress(imgCount, errCount, 5, 66);
144 
145  }
146 
147  // Close files
148  fclose(imageFile);
149  fclose(labelFile);
150 
151 }
152 
153 
154 
155 
156 
157 /**
158  * @details Main function to run MNIST-1LNN
159  */
160 
161 int main(int argc, const char * argv[]) {
162 
163  // remember the time in order to calculate processing time at the end
164  time_t startTime = time(NULL);
165 
166  // clear screen of terminal window
167  clearScreen();
168  printf(" MNIST-1LNN: a simple 1-layer neural network processing the MNIST handwriting images\n");
169 
170  // initialize all connection weights to random values between 0 and 1
171  Layer outputLayer;
172  initLayer(&outputLayer);
173  trainLayer(&outputLayer);
174 
175  testLayer(&outputLayer);
176 
177  locateCursor(38, 5);
178 
179  // Calculate and print the program's total execution time
180  time_t endTime = time(NULL);
181  double executionTime = difftime(endTime, startTime);
182  printf("\n DONE! Total execution time: %.1f sec\n\n",executionTime);
183 
184  return 0;
185 }
186 
187 
void displayProgress(int imgCount, int errCount, int y, int x)
Outputs image recognition progress and error count.
Definition: mnist-stats.c:105
Cell cell[NUMBER_OF_OUTPUT_CELLS]
Definition: 1lnn.h:44
Data structure containing defined number of integer values (the output vector contains values for 0-9...
Definition: 1lnn.h:54
#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.
Vector getTargetOutput(int targetIndex)
Returns an output vector with targetIndex set to 1, all others to 0.
Definition: 1lnn.c:22
FILE * openMNISTImageFile(char *fileName)
Read MNIST IMAGE file header.
Definition: mnist-utils.c:94
int main(int argc, const char *argv[])
Definition: main.c:161
void displayLoadingProgressTesting(int imgCount, int y, int x)
Outputs reading progress while processing MNIST testing images.
Definition: mnist-stats.c:88
#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 displayLoadingProgressTraining(int imgCount, int y, int x)
Outputs reading progress while processing MNIST training images.
Definition: mnist-stats.c:71
void trainLayer(Layer *l)
Definition: main.c:46
void testCell(Cell *c, MNIST_Image *img, int target)
Performs the testing of the trained network.
Definition: 1lnn.c:169
FILE * openMNISTLabelFile(char *fileName)
Read MNIST label file header.
Definition: mnist-utils.c:118
MNIST_Label getLabel(FILE *labelFile)
Returns the next label in given MNIST label file.
Definition: mnist-utils.c:160
#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
void locateCursor(const int row, const int col)
Set cursor position to given coordinates in the terminal window.
Definition: screen.c:57
#define NUMBER_OF_OUTPUT_CELLS
use 10 output cells to model 10 digits (0-9)
Definition: 1lnn.h:12
Machine learning functionality for a 1-layer neural network.
void clearScreen()
Clear terminal screen by printing an escape sequence.
Definition: screen.c:19
The single (output) layer of this network (a layer is number cells)
Definition: 1lnn.h:43
void testLayer(Layer *l)
Definition: main.c:104
void displayImageFrame(int row, int col)
Outputs a 28x28 text frame at a defined screen position.
Definition: mnist-stats.c:21
#define MNIST_TESTING_SET_IMAGE_FILE_NAME
MNIST image testing file in the data folder.
Definition: mnist-utils.h:16
int val[NUMBER_OF_OUTPUT_CELLS]
Definition: 1lnn.h:55
void displayImage(MNIST_Image *img, int row, int col)
Outputs a 28x28 MNIST image as charachters ("."s and "X"s)
Definition: mnist-stats.c:44
void trainCell(Cell *c, MNIST_Image *img, int target)
Performs the training algorithm.
Definition: 1lnn.c:151
void initLayer(Layer *l)
Initialize layer by setting all weights to random values [0-1].
Definition: 1lnn.c:40
Utitlies for handling the MNIST files.
MNIST_Image getImage(FILE *imageFile)
Returns the next image in given MNIST image file.
Definition: mnist-utils.c:140
int getLayerPrediction(Layer *l)
Returns the index of the cell with the hightest output.
Definition: 1lnn.c:62
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