/*
* Artificial Intelligence for Humans
* Volume 3: Deep Learning and Neural Networks
* Java Version
* http://www.aifh.org
* http://www.jeffheaton.com
*
* Code repository:
* https://github.com/jeffheaton/aifh
*
* Copyright 2014-2015 by Jeff Heaton
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* For more information on Heaton Research copyrights, licenses
* and trademarks visit:
* http://www.heatonresearch.com/copyright
*/
package com.heatonresearch.aifh.examples.ann;
import com.heatonresearch.aifh.AIFH;
import com.heatonresearch.aifh.AIFHError;
import com.heatonresearch.aifh.ann.BasicLayer;
import com.heatonresearch.aifh.ann.BasicNetwork;
import com.heatonresearch.aifh.ann.activation.ActivationReLU;
import com.heatonresearch.aifh.ann.activation.ActivationSoftMax;
import com.heatonresearch.aifh.ann.train.BackPropagation;
import com.heatonresearch.aifh.examples.learning.SimpleLearn;
import com.heatonresearch.aifh.general.data.DataUtil;
import com.heatonresearch.aifh.util.ArrayUtil;
import com.heatonresearch.aifh.util.FileUtil;
import com.heatonresearch.aifh.util.MNISTReader;
import java.io.File;
/**
* http://yann.lecun.com/exdb/mnist/
*/
public class LearnDigitsBackprop extends SimpleLearn {
public static final int MNIST_DEPTH = 1;
public static void dump(double[] data) {
int idx = 0;
for(int i=0;i<28;i++) {
StringBuilder line = new StringBuilder();
for(int j=0;j<28;j++) {
line.append(data[idx++]> AIFH.DEFAULT_PRECISION?"*":" ");
}
}
}
public static MNISTReader loadMNIST(String path, boolean training, int depth) {
File path2 = new File(path);
String imagesFilename;
String labelsFilename;
if ( training ) {
imagesFilename = "train-images-idx3-ubyte";
labelsFilename = "train-labels-idx1-ubyte";
} else {
imagesFilename = "t10k-images-idx3-ubyte";
labelsFilename = "t10k-labels-idx1-ubyte";
}
File pathImages = new File(path2,imagesFilename);
File pathLabels = new File(path2,labelsFilename);
if( !pathImages.exists() ) {
imagesFilename += ".gz";
pathImages = new File(path2,imagesFilename);
}
if( !pathLabels.exists() ) {
labelsFilename += ".gz";
pathLabels = new File(path2,labelsFilename);
}
if( !pathImages.exists() ) {
// download
System.out.println("Please wait, downloading digits from: http://yann.lecun.com");
FileUtil.downloadFile("http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz",
new File(path,"train-images-idx3-ubyte.gz"));
FileUtil.downloadFile("http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz",
new File(path,"train-labels-idx1-ubyte.gz"));
FileUtil.downloadFile("http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz",
new File(path,"t10k-images-idx3-ubyte.gz"));
FileUtil.downloadFile("http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz",
new File(path,"t10k-labels-idx1-ubyte.gz"));
}
if( !pathImages.exists() ) {
throw( new AIFHError("Can't open file (with or without .gz): "
+ pathImages.toString() ));
}
if( !pathLabels.exists() ) {
throw( new AIFHError("Can't open file (with or without .gz): "
+ pathLabels.toString() ));
}
return new MNISTReader(
pathLabels.toString(),pathImages.toString(),depth);
}
public void display(MNISTReader reader) {
for(int i=0;i<10;i++) {
System.out.println("=========" + ArrayUtil.indexOfLargest(reader.getData().get(i).getIdeal()));
dump(reader.getData().get(i).getInput());
}
}
public void process() {
System.out.println("Please wait, reading MNIST training data.");
String dir = System.getProperty("user.dir");
MNISTReader trainingReader = loadMNIST(dir,true, MNIST_DEPTH);
MNISTReader validationReader = loadMNIST(dir,false, MNIST_DEPTH);
System.out.println("Training set size: " + trainingReader.getNumImages());
System.out.println("Validation set size: " + validationReader.getNumImages());
int inputCount = trainingReader.getData().get(0).getInput().length;
int outputCount = trainingReader.getData().get(0).getIdeal().length;
BasicNetwork network = new BasicNetwork();
network.addLayer(new BasicLayer(null,true,inputCount));
network.addLayer(new BasicLayer(new ActivationReLU(),true,100));
network.addLayer(new BasicLayer(new ActivationReLU(),true,50));
network.addLayer(new BasicLayer(new ActivationReLU(),true,25));
network.addLayer(new BasicLayer(new ActivationSoftMax(),false,outputCount));
network.finalizeStructure();
network.reset();
// train the neural network
System.out.println("Training neural network.");
final BackPropagation train = new BackPropagation(network, trainingReader.getData(), 1e-4, 0.9);
train.setL1(0);
train.setL2(1e-11);
this.performIterationsClassifyEarlyStop(train, network, validationReader.getData(), 5);
System.out.println("Final accuracy: Incorrect %"
+ DataUtil.calculateClassificationError(validationReader.getData(), network)*100);
}
public static void main(String[] args) {
LearnDigitsBackprop prg = new LearnDigitsBackprop();
prg.process();
}
}