/* * 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.util; import com.heatonresearch.aifh.AIFHError; import org.nd4j.linalg.api.ndarray.INDArray; import org.nd4j.linalg.dataset.DataSet; import org.nd4j.linalg.factory.Nd4j; import java.io.DataInputStream; import java.io.FileInputStream; import java.io.IOException; import java.util.zip.GZIPInputStream; /** * This reads the MNIST dataset of handwritten digits into a data set. * The MNIST dataset is found at http://yann.lecun.com/exdb/mnist/. * * Very loosely adapted from a class by Gabe Johnson <johnsogg@cmu.edu>. * https://code.google.com * /p/pen-ui/source/browse/trunk/skrui/src/org/six11/skrui * /charrec/MNISTReader.java?r=185 */ public class MNISTReader { private final int numLabels; private final int numImages; private final int numRows; private final int numCols; private final DataSet data; public MNISTReader(String labelFilename, String imageFilename) { try { DataInputStream labels; DataInputStream images; // Read label file, decompress (as read in) if needed. if( labelFilename.toLowerCase().endsWith(".gz")) { labels = new DataInputStream(new GZIPInputStream(new FileInputStream( labelFilename))); } else { labels = new DataInputStream(new FileInputStream( labelFilename)); } // Read images file, decompress (as read in) if needed. if( imageFilename.toLowerCase().endsWith(".gz")) { images = new DataInputStream(new GZIPInputStream(new FileInputStream( imageFilename))); } else { images = new DataInputStream(new FileInputStream( imageFilename)); } int magicNumber = labels.readInt(); if (magicNumber != 2049) { throw new AIFHError("Label file has wrong magic number: " + magicNumber + " (should be 2049)"); } magicNumber = images.readInt(); if (magicNumber != 2051) { throw new AIFHError("Image file has wrong magic number: " + magicNumber + " (should be 2051)"); } this.numLabels = labels.readInt(); this.numImages = images.readInt(); this.numRows = images.readInt(); this.numCols = images.readInt(); if (this.numLabels != this.numImages) { StringBuilder str = new StringBuilder(); str.append("Image file and label file do not contain the same number of entries.\n"); str.append(" Label file contains: " + this.numLabels + "\n"); str.append(" Image file contains: " + this.numImages + "\n"); throw new AIFHError(str.toString()); } byte[] labelsData = new byte[this.numLabels]; labels.readFully(labelsData); int imageVectorSize = this.numCols * this.numRows; byte[] imagesData = new byte[this.numLabels * imageVectorSize]; images.readFully(imagesData); INDArray training = Nd4j.create(this.numLabels,imageVectorSize); INDArray ideal = Nd4j.create(this.numLabels,10); int imageIndex = 0; for(int i=0;i<this.numLabels;i++) { int label = labelsData[i]; for (int j = 0; j < imageVectorSize; j++) { training.put(i,j, ((double) (imagesData[imageIndex++] & 0xff)) / 255.0); } for(int j=0;j<10;j++) { ideal.put(i, j, j==label?1:0); } } images.close(); labels.close(); this.data = new DataSet(training,ideal); } catch (IOException ex) { throw new AIFHError(ex); } } /** * @return the numLabels */ public int getNumLabels() { return this.numLabels; } /** * @return the numImages */ public int getNumImages() { return this.numImages; } /** * @return the numRows */ public int getNumRows() { return this.numRows; } /** * @return the numCols */ public int getNumCols() { return this.numCols; } /** * @return the data */ public DataSet getData() { return this.data; } }