Search

Geek Girl Joy

Artificial Intelligence, Simulations & Software

Month

June 2017

Pathfinder Visual Interface

Meet Pathfinder’s New Look!

What is Pathfinder?

I recently wrote a tutorial where I introduce the Pathfinder neural network and cover how it works and I provided fully functional code as well as a training set to get you and Pathfinder working from scratch!

You can find that over here if you are interested: Pathfinding From Scratch Using a Neural Network

8 Direction Stepping
8 Direction Stepping

Pathfinder is an example of a neural network that is capable of plotting an 8 direction step path from a starting position in a 5×5 grid to an ending position in that grid.

I donated the Pathfinder ANN example to the Official FANN PHP Repo and you automatically obtain a copy over there for free when you download the FANN PHP extension. 😉

Pathfinder on YouTube

If you have been following me for a little while you may have even seen my YouTube Pathfinder demonstration video. Go ahead and give it a play, it’s kinda fun to watch! 🙂

Note: The experience of the Pathfinder Visual Interface (PVI) application differs slightly from this video as this video demonstrates the pathfinder neural network operating rather than the PVI, however it is quite similar. The main difference is that this example is automated to execute a series of paths whereas the PVI allows you to manually set the start and stop positions one at a time.

 

Well, now I am announcing the release of a Visual Interface for Pathfinder!

 

What’s the Pathfinder Visual Interface (PVI)?

The PVI is a front-end GUI application for Pathfinder and it comes with a slightly customized and streamlined version of my Pathfinder Neural Network.

Instead of having to manually run the training process, Pathfinder will automatically generate its mind file (pathfinder_float.net) for you from the available (and modifiable) training data on your web server, however I do provide you with a fully trained version from the start to work with to make it even easier to get started!

Additionally, the customized version of Pathfinder comes with basic single user salted & hashed password security with session handling so you could improve and expand Pathfinder as needed without worrying about unauthorized access to your web server running Pathfinder.

The Pathfinder Visual Interface was created using Unity 3D and utilizes C# under the hood.

The Pathfinder Visual Interface is compiled for Windows, Mac and Linux, both 32 bit (x86) & 64 bit (x64) executables are available.

I may make WebAssembly as well as Android and iOS versions available if there is enough interest.

What’s the Difference?

Unlike the PVI version of Pathfinder, the open source version of Pathfinder runs in a browser and is strictly text based (stylized with CSS) which looks like this:


Testing Pathfinder:

10000
00000
00000
00000
00001

Results:

10000
01000
00100
00010
00001


Completely functional, however not very nice to look at, and you have to interact with Pathfinder directly from the source code. :-/

Now here is the same example as above but using the PVI:

 

 

 

 

 

Clearly it’s easier to test and work with your Pathfinder Neural Network and dare I say more fun too! 😛

 

What’s Required?

The Pathfinder ANN relies on PHP so you will need a web server like XAMPP if you will be running it on your local machine or a web hosting account that grants you administrative access via SSH (Secure Shell) and or any other system or implementation that allows you to install PHP extensions as an administrator.

If you want to get started quickly you can use c9.io for free (not a sponsor) and don’t want to or are unable to install a web server on 127.0.0.1.

Pathfinder also requires the free (but very powerful) FANN (Fast Artificial Neural Network) Library to be installed on the machine that is serving and supporting Pathfinder.

I do recommend using secure connections so if you are running Pathfinder from your website you should be encrypting your traffic using SSL Certificates (HTTPS) to make sure that the data exchanged with Pathfinder (as well as your password and other sensitive data) is not exchanged as plain text.

Note that If you are a Developer level supporter on Patreon and want to modify the PVI app you will also need to obtain a free copy of Unity 3D however it is not needed if you only want to to use or modify the neural network which is written in PHP.

 

What could you actually do with with the PVI?

The PVI exchanges it’s grid data with the Neural Network running on your web server so you are not limited by local resources and as such Pathfinder and the PVI make excellent starting points to build games as well as robotics & IOT projects.

If you are the kind of person asking questions like how can I deploy a neural network to interface with my game or web capable Arduino or Raspberry Pi project, and you also have some basic web server knowledge, this might be the right project for you! 😉

 

What do I actually get?

If you are looking to bypass the development of an extensible web based pathfinder neural network and would like a cross-platform (Win, Mac, Linux) tool to interface with the ANN for testing you should support me over on Patreon at the User level which is perfect for teachers and students looking to study PHP, Unity 3D or pathfinding using neural networks.

User

For only $5 Users Get:

  • Access to the open source customized PHP based Pathfinder UI edition and the closed source Cross-Platform (Win, Mac, Linux) executable of the Pathfinder Visual Interface application.

 

If you also want to be able to modify the PVI application so that it is customized to your project needs you should support me over on Patreon at the Developer level.

For only $25 Developers Get:

  • Access to the open source customized PHP based Pathfinder UI edition and the closed source Unity 3D project used to create the Cross-Platform Pathfinder Visual Interface application that you can freely modify to meet your project needs.
  • Additionally developers receive a commercially permissible reuse license!

Users may use the Pathfinder Visual Interface (as is) in a private or commercial setting but you may not redistribute resell it or reverse engineer or decompile it unless you are a Developer level supporter Patreon.

If you would like to get yourself a copy of the Pathfinder Visual Interface it is available now on Patreon!

Next week I will be releasing another tutorial so please Like, Comment & Share this post with your friends and followers on your social media platforms and don’t forget to click the follow button to get notified when I post something new.

If would like to suggest a topic or project for an upcoming post feel free to contact me.

Much Love,

~Joy

The Impending Death of the Programmer

Programming WILL NOT be the last job automated

EndangeredSpecies

If you are a programmer your days are numbered and I am not talking about the coming bootcamp tech bubble bursting!

I suspect the next tech bubble (the “tech-pocalyps” if you will) will be brought on by all the programming bootcamps which are selling an unsustainable idea, “everyone needs to be a programmer!”, I honestly don’t disagree in principal as having some coding skills are REQUIRED going into the coming decade, no argument there!

Yet, if you ask just about anyone what is the hot tech career path right now and the answer is almost always “coding, coding, CODING!!!”.

But is that right? There is this sense that if you know how to code you will be employed until we succeed as a species in establishing a technological singularity.

I suspect that many junior dev’s imagine quite literally that it will be their job’s that go down in the history books with their image along with a caption that reads “John or Jane Smith, the last employed person…”smiley-1914523_640

That dubious honor will almost certainly NOT go to a programmer, perhaps a mathematics PhD, but probably a politician. 😛

Yet, it’s hard to miss all the automation happening around us that is rapidly supplanting “unskilled labor” jobs with robots (currently on the market): plumber robots, window washing robots , robotic vacuums & mops & pool cleaners, even a robotic chef:

It’s only the beginning! The “Age of the Robot” is upon us!

So, logically you’d think we would need a ton of programmers right? Even if its just to write minor changes to behavior routines and bug fixes…. think again!

New methodologies allow industry manufacturing / warehouse automatons like Baxter to learn from unskilled personnel (sans programming) just by watching them perform the desired action.

You might think “that’s real cute Joy” but you can’t really code software by teaching a computer! Even Wix and WordPress require a coder to build the template first. Surely the the data is too complex, there is too much subtle variance to model… perhaps that isn’t the case.

What if, you could employ machine learning to take a description in plain English… (or insert your native tongue here)… of a function, method, class, application, website etc…

Then have another neural network draw a set of images of what it should look like? Perhaps like thumbnails or rough sketches for the user to pick from. This would also allow the user skip the description phase and simply supply their own sketches and drawings for the next step.

What if, you then took those images and fed them into another set of neural networks which could convolve (yes that’s a word :-P) over them to identify the parts of the image as “components” such as an input field, a button, a menu etc… and then use that data to generate the appropriate code (not just the visual code but the linking and processing back-end code as well).

Further still, what if that code was cross language, domain and platform?

Ok now I start to sound like I’m way off in the weeds talking about the future right? Such a feat sounds too good to be true! Until very recently I would have agreed with you… but I’ve seen it, it exists! Or rather, the pieces of the puzzle now exist and its time to start putting it together!

First lets address the subject cross language, domain and platform. You may already be aware that we have effectively solved the cross language, domain and platform challenge via tools like KikAppTools (PHP to Android (Java) or iOS (Objective C)) and Unity3D (C# & JavaScript) which literally transpiles to run on every platform.

So we can already take one programming language and convert it to another depending on whatever the situation requires… mostly.

As an aside, there is actually a need for more of these Language X to Language Y converters which will finally end the epic flame wars (fan-boy/girl-ism) among programmers over the best language and usher in a period of true “language agnosticism” among developers as you can use multiple languages concurrently on any product and then munge (think git merge) them into the final product!

What about the other stuff? Well I’m glad you asked!

Using predictive text this Char-RNN this will write paragraphs about the subject and style of the material it is trained on: http://karpathy.github.io/2015/05/21/rnn-effectiveness/

Here is an RNN that takes an image and writes a little story about it: https://github.com/ryankiros/neural-storyteller

This GAN (Generative Adversarial Networks) learned to turn stills into animations:

What if, we trained something like these neural networks to receive software descriptions and generate software layouts as well as vice versa?

Still, that is far cry from producing actual compilable code.

Well take a look at this article on “how to train a neural network to code by itself” by Thibault Neveu. He demonstrates training an LSTM RNN using TensorFlow to write C code!

It is NOT a perfect push button example, none of the examples are perfect, however they work well enough that they foreshadow things that are coming sooner than you think!

Now imagine if you could build an API around the systems I describe in this article, it would generate trillions in profit and end the career of the typical programmer!

Once I complete my current dev cycle I will begin experimenting with implementing the system I describe above for myself and my followers. Anyone who wants to help or fund me, please support me on Patreon or contact me directly.

Programmers you are on notice, my bots are coming for your jobs!

Please note that the statements and thoughts in this post are my own, none of the brands or companies I mention have payed me or offered me anything for this blog post. Having said that, I would love to have them and all of you as sponsors over on Patreon!

Much Love,

~Joy

Machine Learning from a Database

At some point it will cross your mind…

“I want to train my Neural network from data stored in my database…”

Fear not! because that’s what this post is about!

This post will include actual functional (cut and paste) code so rather than a long series of tutorials I will keep things simple and brief so you can see how easy it is.

You might recall reviewing the XOR function when I wrote about it over in Getting started with Neural Networks Part 2

In that post I trained a neural network to perform the XOR operation.

XOR is frequently used as a sort of “hello world” example and the training data required is short and simple so we will use XOR again here, however you could easily extend the code so that it meets your project needs.

As for the database, MySQL (or MariaDB) is wildly popular, especially for web based projects and it also offers ACID compliance so it stands to reason that any important data you want to train your Neural Network on will likely already be stored in MySQL and as such I will be using it in this tutorial but you could do this with MongoDB or some other storage resource if you prefer.

Step 1 – Setup the Database

So to get started, go create an empty database, you can call it whatever you like but in this example my database will simply be called ‘test‘. There is a function bellow called “CreateTable” that will put the XOR training data in the database for you or you can use this SQL query:



CREATE TABLE `TrainingSets` (
  `ID` int(11) NOT NULL,
  `Name` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
  `TrainingData` text COLLATE utf8mb4_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
ALTER TABLE `TrainingSets` ADD PRIMARY KEY (`ID`);
 
INSERT INTO `TrainingSets` (`ID`, `Name`, `TrainingData`) VALUES(1, 'XOR', '-1 -1\n-1\n-1 1\n1\n1 -1\n1\n1 1\n-1');
ALTER TABLE `TrainingSets` MODIFY `ID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;


 

Step 2 – The Functions

Here are the functions you will need. You will need to modify them to meet your needs or write your own versions as the code here is written with the XOR example in mind.



// This function will setup the $table table in your database and
// then insert the XOR Training Data
function CreateTable($host, $user, $pass, $database, $table, $field){
    
    $result = false;
    
    // Create connection
    $connection = new mysqli($host, $user, $pass, $database);
    // Check connection
    if ($connection->connect_error) {
        die('Connection failed: ' . $connection->connect_error);
    }
    // sql to create $table table
    $sql = "CREATE TABLE `$table` (
  `ID` int(11) NOT NULL,
  `Name` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
  `$field` text COLLATE utf8mb4_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci";
    if ($connection->query($sql) === TRUE) {
        echo "Table $table created successfully.<br>";
        
        // sql to set the ID field as the PRIMARY KEY
        $sql = "ALTER TABLE `$table` ADD PRIMARY KEY (`ID`)";
        if ($connection->query($sql) === TRUE) {
            echo "PRIMARY KEY set to ID.<br>";
            
            // sql to insert XOR into DB
            $sql = "INSERT INTO `$table` (`ID`, `Name`, `$field`) VALUES(1, 'XOR', '-1 -1\n-1\n-1 1\n1\n1 -1\n1\n1 1\n-1')";
            if ($connection->query($sql) === TRUE) {
                echo "XOR inserted into DB.<br>";
                // sql to "auto increment" ID when new $table are added
                $sql = "ALTER TABLE `$table` MODIFY `ID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2";
                if ($connection->query($sql) === TRUE) {
                    echo 'ID will AUTO_INCREMENT.<br>';
                    $result = TRUE;
                } else {
                    echo 'Error altering ID: ' . $connection->error . '<br>';
                }
            } else {
                echo 'Error inserting XOR into DB: ' . $connection->error . '<br>';
            }
        } else {
            echo 'Error setting PRIMARY KEY to ID: ' . $connection->error . '<br>';
        }
    } else {
        echo "Error creating $table table: " . $connection->error . '<br>';
    }
    $connection->close();
    
    return $result;
}

// This function calls/pulls the TrainingData from MySQL
function GetTrainingDataFromDB($host, $user, $password, $database, $table_name, $field, $id) {
    $connection=mysqli_connect($host, $user, $password, $database); // open db connection
    $result=mysqli_query($connection,"SELECT $field FROM $table_name WHERE ID=$id"); // query the db
    $data=mysqli_fetch_assoc($result); // pull training data
    mysqli_close($connection); // close connection
    return $data[$field]; // return training data
}

// This function prepares the newline delimited data to be handed off to FANN
/*
Example of "newline delimited data" (like XOR in a Plain Text File) stored in MySQL:
-1 -1
-1
-1 1
1
1 1
-1
1 -1
1
*/
function PrepareDataFromDB($training_data) {
    $training_data = explode("\n", $training_data); // convert training data rows to array
    $num_data = count($training_data);
	   
    // Sift the data and split inputs and outputs
    for($i=0;$i<$num_data;$i++) {
      if($i % 2) { // $training_data[$i] is Output
       $training_data['outputs'][] = explode(' ', $training_data[$i]);
      }else{ // $training_data[$i] is Input
       $training_data['inputs'][] = explode(' ', $training_data[$i]);
      }
    }
    // remove the unsifted data
    foreach ($training_data as $key => $value) {
        if (is_numeric($key)) {
            unset($training_data[$key]);
        }
    }
    return $training_data; // returned the prepared associative array
}

// This function hands the prepared data over to FANN
function create_train_callback($num_data, $num_input, $num_output) {
    global $training_data;
    global $current_dataset;
  
    $dataset = array('input' => $training_data['inputs'][$current_dataset],
                    'output' => $training_data['outputs'][$current_dataset]);
    $current_dataset++;
	
    return $dataset;
}


Step 3 – The Code

Great, now here is the code that demonstrates how to read the data from your database and then train an FANN Neural Network.




// Change to your DB credentials
$host = '127.0.0.1';
$user = 'username';
$password = 'password';
$database = 'test';
$table = 'TrainingSets';
$field = 'TrainingData';

// Insert training data into the database
CreateTable($host, $user, $password, $database, $table, $field); 



// Initialize the program variables
$record_id = 1; // the 'ID' for the training data in MySQL
$current_dataset = 0;
$num_input = 2;
$num_output = 1;
$num_layers = 3;
$num_neurons = 3;
$desired_error = 0.001;
$max_epochs = 500000;
$epochs_between_reports = 1000;

// Get the Training Data from MySQL
$training_data = GetTrainingDataFromDB($host, $user, $password, $database, $table, $field, $record_id);

// Prepare the data
$training_data = PrepareDataFromDB($training_data); 


// How many sets are there?
$num_data = count($training_data['inputs']); 

// Hand the data over to FANN
$train_data = fann_create_train_from_callback($num_data, $num_input, $num_output, "create_train_callback");



// Test for $train_data
if ($train_data) {

    // Create $ann
    $ann = fann_create_standard($num_layers, $num_input, $num_neurons, $num_output);
	
	 

    // Test for $ann
    if ($ann) {
        fann_set_activation_function_hidden($ann, FANN_SIGMOID_SYMMETRIC);
        fann_set_activation_function_output($ann, FANN_SIGMOID_SYMMETRIC);
		
		$result = fann_train_on_data($ann, $train_data, $max_epochs, $epochs_between_reports, $desired_error);

		
		// Train XOR ANN with training data obtained from MySQL
        if (fann_train_on_data($ann, $train_data, $max_epochs, $epochs_between_reports, $desired_error))
		{
           echo 'XOR trained.<br>' . PHP_EOL;
           // Test $ann
           $input = array(-1, 1);
           $calc_out = fann_run($ann, $input);
           printf("XOR test (%f,%f) -> %f\n", $input[0], $input[1], $calc_out[0]);
          
           // destroy $ann
           fann_destroy($ann);
         }
    }
}


echo "<br>All Done!";

If you would like to obtain a copy of this code from GitHub you can find it here: TrainFANNNeuralNetworkFromMySQL.php on GitHub

Here is how it works,  we first make sure the training data is in the database by calling CreateTable(), we then define the variables to use with the ANN. You could compute these values at run time from the training data or store it elsewhere in the database, its up to you but I wanted to keep things simple to lessen the chance of confusion so I predefined them.

We call GetTrainingDataFromDB() to retrieve the raw training data from MySQL.

We call the PrepareDataFromDB() function to split the inputs and outputs into an associative array of ‘inputs’ and ‘outputs’ followed up with a call to fann_create_train_from_callback() which uses my callback function create_train_callback() to build the training resource.

At this point we can create a standard ANN resource using fann_create_standard().

Then as usual we specify the activation functions, but instead of using fann_train_on_file() as you may be familiar with, we use  fann_train_on_data() since our training data is a resource in memory because it loaded from MySQL.

We follow that up with a quick test using fann_run() before destroying the resource.

And with that, you now know how to train a neural network from a database!

Please support me on Patreon so I can continue to bring you more great tutorials like this!

As always I hope you found this both interesting and informative. Please Like, Comment & Share this post with your friends and followers on your social media platforms and don’t forget to click the follow button over on the top right of this page to get notified when I post something new.

If would like to suggest a topic or project for an upcoming post feel free to contact me.

Much Love,
~Joy

 

Lets teach AI how to read using PHP IV

 

Welcome back to the fourth and final installment of the OCR tutorial series. I know you have been eagerly awaiting this post which will tie everything together and enable us to finally test the OCR ANN.

Here are the previous posts in this series:

Lets teach AI how to read using PHP

Lets teach AI how to read using PHP Part 2

Lets teach AI how to read using PHP Part 3

 

Before proceeding here is the code we will be considering:

test_ocr.php


<style>
	.blue{color:blue;}
	.green{color:green;}
	.red{color:red;}
</style>

<?php
/*
    OCR( 
	    (string) $img, 
	    (char) $expected, 
		(array) $input, 
		(array)$lookup_array, 
		(FANN neural network resource)$ann
	   );
	
	Description: 
	
	With this function I simply try to illustrate how you could test the OCR ANN. 
				
	$img is a string that should be the name to the training image you are reading from. It is
	used to output the image to the browser results.
	
	$expected is a char that you are actually testing for. eg  
	
	$input should be an array of inputs (encoded pixel data)
	
	$lookup_array should be an array of ASCII characters normalized as floating point values in increments of 0.01
	
	$ann should be a FANN neural network resource.
	
	References:   
	   global - http://php.net/language.variables.scope
	   PHP_EOL - http://php.net/manual/en/reserved.constants.php
	   fann_run() - http://php.net/manual/en/function.fann-run.php
	   floor() - http://php.net/manual/en/function.floor.php
	   count() - http://php.net/manual/en/function.count.php
*/
function OCR($img, $expected, $input, $lookup_array, $ann) {
	global $correct; // refer to the non local $correct variable
	$output = ""; 
	
	/* Display image for reference */
	$output .= "Image: <img src='images/$img'><br>" . PHP_EOL;

	// Run the ANN
	$calc_out = fann_run($ann, $input);
	
	$output .= 'Raw: ' .  $calc_out[0] . '<br>' . PHP_EOL;
	$output .= 'Trimmed: ' . floor($calc_out[0]*100)/100 . '<br>' . PHP_EOL;
	$output .= 'Decoded Symbol: ';
	
	/* What did the ANN think it saw? */
	for($i = 0; $i < count($lookup_array); $i++) {
       if( floor($lookup_array[$i][0]*100)/100 == floor($calc_out[0]*100)/100) {
	        $output .= $lookup_array[$i][1] . '<br>' . PHP_EOL;
	        $output .= "Expected: $expected <br>" . PHP_EOL;
	        $output .= 'Result: ';
	        if($expected == $lookup_array[$i][1]){
	        	$output .= '<span class="green">Correct!</span>';
				
				++$correct;
				
	        }else{
	        	$output .= '<span class="red">Incorrect!</span> <a href="train_ocr.php">Retrain OCR</a>';
	        }
		}
	}
	$output .= '<br><br>' . PHP_EOL;
	
	return $output;	
}


$total = 11; // How many images are to be tested
$correct = 0; // The count of how many images were correctly read by the ANN


/* Setup a resource that points to our ANN .net file */
$train_file = (dirname(__FILE__) . '/ocr_float.net');

/* Confirm the ANN exists */
if (!is_file($train_file))
	die('<span class="red">The file ocr_float.net has not been created!</span><a href="train_ocr.php">Train OCR</a>' . PHP_EOL);

/* Create the ANN resource */
$ocr_ann = fann_create_from_file($train_file);
if ($ocr_ann) {
	// Display the images we are testing (hard coded)
	?>
	<h1 class='blue'>OCR Test</h1>
	<strong>Testing: </strong>
	<img src='images/38.png'> <!-- G -->
	<img src='images/68.png'> <!-- e -->
	<img src='images/68.png'> <!-- e -->
	<img src='images/74.png'> <!-- k -->
	<img src='images/38.png'> <!-- G -->
	<img src='images/72.png'> <!-- i -->
	<img src='images/81.png'> <!-- r -->
	<img src='images/75.png'> <!-- l -->
	<img src='images/41.png'> <!-- J -->
	<img src='images/78.png'> <!-- o -->
	<img src='images/88.png'> <!-- y -->
	<br>
	<?php

	/* 
	    Create the lookup_array from ASCII
		https://en.wikipedia.org/wiki/ASCII
		
        start: ascii dec 33 (!) 
        stop:  ascii dec 126 (~) 
    */
	$result_lookup_array = array();
	$curr = 0.00;
	for($i = 33; $i <= 126; $i++) {
		array_push($result_lookup_array, array($curr, chr($i)));
		$curr+= 0.01;
	}
	

	// For simplicity sake I hardcoded these values below as there is no need to prove that we can read
	// the pixel data for each image (as we already did that in generate_training_data.php) however you 
	// can implement similar methodology to what as I did with GenerateTrainingData() to read pixel values
	// programmaticlly into an array rather than manually specifying it as I show here.
	
	$test_G = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
	$test_e = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
	$test_k = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
	$test_i = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
	$test_r = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
	$test_l = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
	$test_J = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
	$test_o = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
	$test_y = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
	
       
	/* Test OCR and buffer results in the $output variable as string data */
	$output = "";
	$output .= OCR('38.png', 'G', $test_G, $result_lookup_array, $ocr_ann);
	$output .= OCR('68.png', 'e', $test_e, $result_lookup_array, $ocr_ann);
	$output .= OCR('68.png', 'e', $test_e, $result_lookup_array, $ocr_ann);
	$output .= OCR('74.png', 'k', $test_k, $result_lookup_array, $ocr_ann);
	$output .= OCR('38.png', 'G', $test_G, $result_lookup_array, $ocr_ann);
	$output .= OCR('72.png', 'i', $test_i, $result_lookup_array, $ocr_ann);
	$output .= OCR('81.png', 'r', $test_r, $result_lookup_array, $ocr_ann);
	$output .= OCR('75.png', 'l', $test_l, $result_lookup_array, $ocr_ann);
	$output .= OCR('41.png', 'J', $test_J, $result_lookup_array, $ocr_ann);
	$output .= OCR('78.png', 'o', $test_o, $result_lookup_array, $ocr_ann);
	$output .= OCR('88.png', 'y', $test_y, $result_lookup_array, $ocr_ann);
	
    // Determine how accurate the Neural Network is
    $percent_correct = round(($correct / $total) * 100, 2 );
    
	// Output the accuracy results
	echo "<strong>Results:</strong> $correct images correctly decoded out of $total. (<span class='"; 
	
	/* Add a css style to the percentage results */
	if($percent_correct < 70){echo "red'>";}
	elseif($percent_correct < 90){echo "blue'>";}
	else{echo "green'>";}
	
	/* Close css style span and offer link to retrain */
	echo $percent_correct . "%</span>)<br>Not good enough? <a href='train_ocr.php'>Retrain OCR</a><br><br>" ;
	
	/* display detailed results */
	echo "<h2 class='blue'>Details</h2>";
	echo $output;
	
	/* Free up memory associated with the OCR ANN resource. */ 
	fann_destroy($ocr_ann);
} else {
	die("<span class='red'>Invalid file format.</span>" . PHP_EOL);
}

?>

If you run this code the following things will happen:
  1.  The images we are testing will display on page using HTML <img> elements.
  2. Our neural network will be loaded from the file we created in step 3 of this tutorial.
  3. 11 Tests using the OCR function I provide will be preformed.
  4. The results of the ANN will be computed then displayed as an accuracy %.
  5. Detailed results of each test result will be displayed.

Now that we have tested the OCR ANN, lets break it down and understand what is going on.

 

Step 1 – generate_training_images.php

In Step 1 we create our images and log file.

 

 

 

 

 

 

 

 

 

Step 2 – generate_training_data.php

In Step 2 we use the log file as a reference to step through each image and examine every pixel and assign it a value of 1 or 0 based on the color of the pixel. We then save our results to a new file called ocr.data.

 

Step 3 – train_ocr.php

In Step 3 we train the neural network and save it as ocr_float.net.

Step 4 – test_ocr.php (This part of the tutorial)

In Step 4 load the ANN from file ocr_float.net and then proceed to test it. In this image I ran multiple tests and excluded the individual image details however in the code I provided you will get additional data about each test image.

At this point our toy OCR neural network is complete and operating as well as can be expected.

Why is this a “toy” neural network? Because it is trained to “classify” or identify images in a single one off event rather than convolving (yes that is a real word 😛 ) over the images and extracting features. Basically what this means is that while it eventually got a ~73% correct identification rate it’s not actually going to read text out of just any image… not only that we broke the cardinal rule of testing our ANN with the same data we trained it on (always test on new data not what it was trained on) so the ANN is “hyper fitting” its data set.

We could probably improve accuracy by moving the letters in the images, blurring them rotating them, changing their color and adding the ability for the ANN to work with more than black and white text etc… but in the end it would only be a marginal improvement.

To use OCR for more real world scenarios you will need to implement convolution layers. Which will allow you to not only read the letters and words in an image of any size or color but also do object recognition such as test image 1 is a cat and test image 2 is a ti82 calculator…

And with that I hope you had as much fun following along with this tutorial as much as I had creating it! 🙂

Please support me on Patreon.

If you would like to obtain a copy of this code from GitHub you can find the complete project here: OCR on GitHub

Note: This project (all the code, the title images as well as the infographic licensed under everyone’s favorite license (MIT LICENSE) so feel free to take this code and develop it into something amazing! Please just attribute me as the author of the initial code base. Also if you use this to create something cool, I’d love to hear about it! 🙂

As always I hope you found this project both interesting and informative. Please Like, Comment & Share this post with your friends and followers on your social media platforms and don’t forget to click the follow button over on the top right of this page to get notified when I post something new.

If would like to suggest a topic or project for an upcoming post feel free to contact me.

Much Love,
~Joy

Blog at WordPress.com.

Up ↑

%d bloggers like this: