    001package visrec.ri.ml.classification;
    002
    003import deepnetts.data.ExampleImage;
    004import deepnetts.data.ImageSet;
    005import deepnetts.net.ConvolutionalNetwork;
    006import deepnetts.net.layers.SoftmaxOutputLayer;
    007import deepnetts.net.layers.activation.ActivationType;
    008import deepnetts.net.loss.CrossEntropyLoss;
    009import deepnetts.net.train.BackpropagationTrainer;
    010import deepnetts.net.train.opt.OptimizerType;
    011import deepnetts.util.DeepNettsException;
    012
    013import javax.visrec.AbstractImageClassifier;
    014import javax.visrec.util.VisRecConstants;
    015import java.awt.image.BufferedImage;
    016import java.io.File;
    017import java.io.FileNotFoundException;
    018import java.util.HashMap;
    019import java.util.Map;
    020import java.util.logging.Level;
    021import java.util.logging.Logger;
    022
    023
    024/**
    025 * TODO: Traffic sign recognition healhcare - skin, radiology caner for bone -
    026 * MRI vegetarian or non vegeterian food, transportation boxes simple
    027 * implementation and ditributed implemantayion using th esame api as hazelcast
    028 * trab what is teh biggest challange for javadeveloper starting tio use it
    029 * apache or gpl wit classpath , allow dynamic linkoing
    030 *
    031 * separate training from using. (resource usage) 3d stereo vision - using conv
    032 * networks use configuration JSR apache 382 iso standardize containers thermal
    033 * imaging
    034 *
    035 * BIG QUESTION HOW WILL WE INJECT ML MODEL? OR HOW WILL WE PROVIDE PARAMETERS
    036 * FOR BUILDING INTERNAL MODEL? WE SHOULD BE ABLE TO DO BOTH: incejt model or
    037 * build internal model using standard, or customized settings
    038 *
    039 * @author Zoran Sevarac
    040 */
    041public class DeepNettsImageClassifier extends AbstractImageClassifier<BufferedImage, ConvolutionalNetwork> {
    042
    043    private int inputWidth, inputHeight;
    044
    045    public static final Logger LOGGER = Logger.getLogger(DeepNettsImageClassifier.class.getName());
    046
    047    public DeepNettsImageClassifier() {
    048        super(BufferedImage.class);
    049    }
    050
    051    @Override
    052    public Map<String, Float> classify(BufferedImage sample) {
    053        Map<String, Float> results = new HashMap<>();
    054        ConvolutionalNetwork neuralNet = getModel();
    055
    056        ExampleImage exImage = new ExampleImage(sample);
    057        neuralNet.setInput(exImage.getInput());
    058        neuralNet.forward();
    059
    060        float[] outputs = neuralNet.getOutput();
    061
    062        for (int i = 1; i < outputs.length; i++) {
    063            results.put(neuralNet.getOutputLabel(i), outputs[i]);
    064        }
    065
    066        return results;
    067    }
    068
    069    public int getInputWidth() {
    070        return inputWidth;
    071    }
    072
    073    public int getInputHeight() {
    074        return inputHeight;
    075    }
    076
    077    public static javax.visrec.util.Builder<DeepNettsImageClassifier> builder() {
    078        return new Builder();
    079    }
    080
    081    public static class Builder implements javax.visrec.util.Builder<DeepNettsImageClassifier> {
    082
    083        DeepNettsImageClassifier dnImgClassifier = new DeepNettsImageClassifier();
    084
    085        @Override
    086        public DeepNettsImageClassifier build() {
    087            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    088        }
    089
    090        // how to specify network archittecture which is a graph abesed model?
    091        //use json object? specific Configuration? it has to be graph ike structure
    092        // json file or json object or cprecific configuration
    093        @Override
    094        public DeepNettsImageClassifier build(Map<String, Object> config) {
    095            int imageWidth = Integer.parseInt(String.valueOf(config.get(VisRecConstants.IMAGE_WIDTH)));
    096            int imageHeight = Integer.parseInt(String.valueOf(config.get(VisRecConstants.IMAGE_HEIGHT)));
    097            String labelsFile = String.valueOf(config.get(VisRecConstants.LABELS_FILE));
    098            String trainingFile = String.valueOf(config.get(VisRecConstants.TRAINING_FILE));
    099            float maxError = Float.parseFloat(String.valueOf(config.get(VisRecConstants.SGD_MAX_ERROR)));
    100            float learningRate = Float.parseFloat(String.valueOf(config.get(VisRecConstants.SGD_LEARNING_RATE)));
    101
    102            String modelFile = String.valueOf(config.get("visrec.model.saveToFile"));
    103
    104            ImageSet imageSet = new ImageSet(imageWidth, imageHeight);
    105            LOGGER.info("Loading images...");
    106
    107            imageSet.loadLabels(new File(labelsFile));
    108            try {
    109                imageSet.loadImages(new File(trainingFile), true); // paths in training file should be relative
    110                imageSet.invert();
    111                imageSet.zeroMean();
    112                imageSet.shuffle();
    113            } catch (DeepNettsException ex) {
    114                java.util.logging.Logger.getLogger(DeepNettsImageClassifier.class.getName()).log(Level.SEVERE, null, ex);
    115            } catch (FileNotFoundException ex) {
    116                Logger.getLogger(DeepNettsImageClassifier.class.getName()).log(Level.SEVERE, null, ex);
    117            }
    118
    119            int classCount = imageSet.getLabelsCount();
    120
    121            LOGGER.info("Done!");
    122            LOGGER.info("Creating neural network...");
    123
    124//        String modelJsonFile = prop.getProperty("visrec.model.deepnetts");
    125//        ConvolutionalNetwork neuralNet = null;
    126//        try {
    127//            neuralNet = FileIO.createFromJson(new File(modelJsonFile));
    128//            //neuralNet.setOutputLabels(imageSet.getLabels());
    129//        } catch (IOException ex) {
    130//            Logger.getLogger(DeepNettsImageClassifier.class.getName()).log(Level.SEVERE, null, ex);
    131//        }
    132
    133            //get architecture from json instead of this hardcoding
    134            ConvolutionalNetwork neuralNet = new ConvolutionalNetwork.Builder()
    135                    .addInputLayer(imageWidth, imageHeight, 3)
    136                    .addConvolutionalLayer(5, 5, 3, ActivationType.RELU)
    137                    .addMaxPoolingLayer(2, 2, 2)
    138                    .addConvolutionalLayer(3, 3, 6, ActivationType.RELU)
    139                    .addMaxPoolingLayer(2, 2, 2)
    140                    .addFullyConnectedLayer(30, ActivationType.RELU)
    141                    .addFullyConnectedLayer(20, ActivationType.RELU)
    142                    .addOutputLayer(classCount, SoftmaxOutputLayer.class)
    143                    .lossFunction(CrossEntropyLoss.class)
    144                    .randomSeed(123)
    145                    .build();
    146
    147            LOGGER.info("Done!");
    148            LOGGER.info("Training neural network");
    149
    150            neuralNet.setOutputLabels(imageSet.getOutputLabels());
    151
    152            // create a set of convolutional networks and do training, crossvalidation and performance evaluation
    153            BackpropagationTrainer trainer = new BackpropagationTrainer(neuralNet);
    154            trainer.setLearningRate(learningRate)
    155                    .setMomentum(0.7f)
    156                    .setMaxError(maxError)
    157                    .setBatchMode(false)
    158                    .setOptimizer(OptimizerType.MOMENTUM);
    159            trainer.train(imageSet);
    160
    161            dnImgClassifier.setModel(neuralNet);
    162
    163//            try {
    164//                FileIO.writeToFile(neuralNet, modelFile);
    165//            } catch (IOException ex) {
    166//                java.util.logging.Logger.getLogger(DeepNettsImageClassifier.class.getName()).log(Level.SEVERE, null, ex);
    167//            }
    168
    169            return dnImgClassifier;
    170
    171        }
    172
    173    }
    174
    175}