Skip to content

Commit

Permalink
final touches
Browse files Browse the repository at this point in the history
  • Loading branch information
mateogianolio committed May 26, 2016
1 parent f77852f commit 3e25dcc
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 90 deletions.
48 changes: 26 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ console.log('prediction:', prediction.indexOf(Math.max.apply(null, prediction)))

## Performance

All runs below were performed with an i5 MacBook Air 13" Mid 2012 with 4GB RAM.
All runs below were performed with a MacBook Pro Retina 13" Early 2015 with 8GB RAM.

### [MNIST [0-9]](https://yann.lecun.com/exdb/mnist/)

Expand All @@ -61,12 +61,12 @@ To test with the MNIST dataset: click on the title above, download the 4 data fi
* **Neurons**
* ```400``` input
* ```160``` hidden
* ```4``` output
* ```10``` output
* **Learning rate:** ```0.03```
* **Training set:** ```60000``` digits
* **Testing set:** ```10000``` digits
* **Training time:** ```36 min 22 s 50 ms```
* **Success rate:** ```90.14%```
* **Training time:** ```21 min 53 s 753 ms```
* **Success rate:** ```95.16%```

### [A-Za-z0-9]

Expand All @@ -84,23 +84,24 @@ To test with the MNIST dataset: click on the title above, download the 4 data fi
"image_size": 16,
"threshold": 400,
"network": {
"hidden": 40,
"learning_rate": 0.03
"hidden": 60,
"learning_rate": 0.1,
"output": 62
}
}
```

* **Neurons**
* ```256``` input
* ```40``` hidden
* ```8``` output
* ```60``` hidden
* ```62``` output
* **Learning rate:** ```0.03```
* **Training set**
* **Size:** ```124000``` characters
* **Sample:** ![abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789](https://raw.github.com/mateogianolio/mlp-character-recognition/master/examples/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.png)
* **Testing set:** ```62000``` characters
* **Training time:** ```4 min 8 s 2 ms```
* **Success rate:** ```78.60322580645162%```
* **Training time:** ```8 min 18 s 560 ms```
* **Success rate:** ```93.58225806451614%```

### [a-z]

Expand All @@ -119,22 +120,23 @@ To test with the MNIST dataset: click on the title above, download the 4 data fi
"threshold": 400,
"network": {
"hidden": 40,
"learning_rate": 0.1
"learning_rate": 0.1,
"output": 26
}
}
```

* **Neurons**
* ```256``` input
* ```40``` hidden
* ```8``` output
* ```26``` output
* **Learning rate:** ```0.1```
* **Training set**
* **Size:** ```52000``` characters
* **Sample:** ![abcdefghijklmnopqrstuvwxyz](https://raw.github.com/mateogianolio/mlp-character-recognition/master/examples/abcdefghijklmnopqrstuvwxyz.png)
* **Testing set:** ```26000``` characters
* **Training time:** ```2 min 10 s 752 ms```
* **Success rate:** ```91.77692307692308%```
* **Training time:** ```1 min 55 s 414 ms```
* **Success rate:** ```93.83846153846153%```

### [0-9]

Expand All @@ -161,14 +163,14 @@ To test with the MNIST dataset: click on the title above, download the 4 data fi
* **Neurons**
* ```256``` input
* ```40``` hidden
* ```8``` output
* ```10``` output
* **Learning rate:** ```0.1```
* **Training set**
* **Size:** ```20000``` digits
* **Sample:** ![0123456789](https://raw.github.com/mateogianolio/mlp-character-recognition/master/examples/0123456789.png)
* **Testing set:** ```10000``` digits
* **Training time:** ```1 min 6 s 620 ms```
* **Success rate:** ```99.22%```
* **Training time:** ```0 min 44 s 363 ms```
* **Success rate:** ```99.59%```

## Configuration

Expand All @@ -178,20 +180,21 @@ Tweak the network for your needs by editing the ```config.json``` file located i
// config.json
{
"mnist": false,
"text": "abcdefghijklmnopqrstuvwxyz",
"text": "0123456789",
"fonts": [
"sans-serif",
"serif"
],
"training_set": 2000,
"testing_set": 500,
"image_size": 20,
"testing_set": 1000,
"image_size": 16,
"threshold": 400,
"network": {
"hidden": 40,
"learning_rate": 0.1
}
}

```

* **```mnist```**
Expand All @@ -216,15 +219,16 @@ Tweak the network for your needs by editing the ```config.json``` file located i

## Usage

Clone this repository. The script is using [canvas](https://www.npmjs.com/package/canvas), so you'll need to install the **Cairo** rendering engine. On OSX, this can be done with the following one-liner (copied from canvas README):
Clone this repository. The script is using [canvas](https://www.npmjs.com/package/canvas), so you'll need to install the **Cairo** rendering engine. On OS X, assuming you have Homebrew installed, this can be done with the following (copied from canvas README):

```bash
$ wget https://raw.githubusercontent.com/LearnBoost/node-canvas/master/install -O - | sh
$ brew install cairo jpeg giflib
```

Then install npm dependencies and test it:

```bash
$ npm install
$ node main.js
$ node test.js
```
8 changes: 6 additions & 2 deletions config.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
{
"mnist": false,
"text": "0123456789",
"fonts": [
"sans-serif",
"serif"
],
"training_set": 2000,
"testing_set": 500,
"testing_set": 1000,
"image_size": 16,
"threshold": 400,
"network": {
"hidden": 40,
"output": 10,
"learning_rate": 0.1
}
}
Binary file modified examples/0123456789.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified examples/abcdefghijklmnopqrstuvwxyz.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
129 changes: 63 additions & 66 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
config.fonts = config.fonts || ['serif', 'sans-serif'];
config.distortion = config.distortion === undefined ? true : config.distortion;
config.network.hidden = config.network.hidden || 40;
config.network.output = config.network.output || 8;
config.network.output = config.network.output || 10;
config.network.learning_rate = config.network.learning_rate || 0.1;

console.log('... done');
Expand All @@ -47,75 +47,72 @@
};

// captcha callback
function generate(index) {
return function(text, data) {
var png = new PNG({ filterType: 4 });

png.parse(data, function (text, index) {
return function(error, data) {
if(error)
throw error;

var position,
chunk = [],
pixel = [],
i, j, k, x, y;

for(i = 0; i < config.text.length; i++) {
for(y = 0; y < data.height; y++) {
for(x = i * config.image_size; x < (i * config.image_size + config.image_size); x++) {
position = (data.width * y + x) << 2;

for(j = 0; j < 3; j++)
pixel.push(data.data[position + j]);

chunk.push(
pixel.reduce(function(previous, current) {
return previous + current;
}) > config.threshold ? 0 : 1
);
pixel = [];
}
}

chunk = tools.center(chunk);

var output = Array.apply(null, new Array(config.network.output)).map(Number.prototype.valueOf, 0);
output[i] = 1;

if(index < config.training_set) {
training.push({
input: chunk,
output: output
});
} else {
testing.push({
input: chunk,
output: output
});
}

chunk = [];
var k = 0;
function generate(text, data) {
if (k === 0)
fs.writeFileSync('./examples/' + text + '.png', data, 'base64');

var png = new PNG({ filterType: 4 });

png.parse(data, function(error, data) {
if(error)
throw error;

var position,
chunk = [],
pixel = [],
i, j, x, y;

for(i = 0; i < config.text.length; i++) {
for(y = 0; y < data.height; y++) {
for(x = i * config.image_size; x < (i * config.image_size + config.image_size); x++) {
position = (data.width * y + x) << 2;

for(j = 0; j < 3; j++)
pixel.push(data.data[position + j]);

chunk.push(
pixel.reduce(function(previous, current) {
return previous + current;
}) > config.threshold ? 0 : 1
);
pixel = [];
}

if(index === samples - 1) {
console.log('... done');
console.log();

network.train(perceptron, training, config.network.learning_rate);
fs.writeFileSync('./ocr.js', 'module.exports = ' + perceptron.standalone().toString());
network.test(perceptron, testing);
}
};
});

if(index === 0)
fs.writeFileSync('./examples/' + text + '.png', data, 'base64');
};
}

chunk = tools.center(chunk);

var output = Array.apply(null, new Array(config.network.output)).map(Number.prototype.valueOf, 0);
output[i] = 1;

if(k < config.training_set) {
training.push({
input: chunk,
output: output
});
} else {
testing.push({
input: chunk,
output: output
});
}

chunk = [];
}

if(k++ === samples - 1) {
console.log('... done');
console.log();

network.train(perceptron, training, config.network.learning_rate);
fs.writeFileSync('./ocr.js', 'module.exports = ' + perceptron.standalone().toString());
network.test(perceptron, testing);
}
});
}

console.log('generating images ...');

for(index = 0; index < samples; index++)
captcha.generate(settings, generate(index));
captcha.generate(settings, generate);
})();

0 comments on commit 3e25dcc

Please sign in to comment.