-3

I recently tried to create my first project with Neural Networks and that's what i came up with. I wanted to make it recognize MNIST handwritten numbers. The problem is, when i run this code and make it train like ~400k times i get ~28% of accuracy with test data. Is it supposed to be like that? Is 400k too little to get better results, or is it because my neural network can only have one hidden layer?

Summing up to short question, are things supposed to look like that, or did i do something wrong? There's a lot of redundant code below and stuff like that, i just wanted to make it work.

Everything assuming that my Neural Network works obviously.

public static void main(String[] args) {

  List<Data> trainData = new ArrayList<>();
  List<Data> testData = new ArrayList<>();

  byte[] trainLabels;
  byte[] trainImages;
  byte[] testLabels;
  byte[] testImages;

  try {

     Path tempPath1 = Paths.get("res/train-labels-idx1-ubyte");
     trainLabels = Files.readAllBytes(tempPath1);
     ByteBuffer bufferLabels = ByteBuffer.wrap(trainLabels);
     int magicLabels = bufferLabels.getInt();
     int numberOfItems = bufferLabels.getInt();

     Path tempPath = Paths.get("res/train-images-idx3-ubyte");
     trainImages = Files.readAllBytes(tempPath);
     ByteBuffer bufferImages = ByteBuffer.wrap(trainImages);
     int magicImages = bufferImages.getInt();
     int numberOfImageItems = bufferImages.getInt();
     int rows = bufferImages.getInt();
     int cols = bufferImages.getInt();

     for(int i = 0; i < numberOfItems; i++) {
        int t = bufferLabels.get();
        double[] target = createTargets(t);
        double[] inputs = new double[rows*cols];
        for(int j = 0; j < inputs.length; j++) {
           inputs[j] = bufferImages.get();
           }
         Data tobj = new Data(inputs, target);
         trainData.add(tobj);
       }

      tempPath = Paths.get("res/t10k-labels-idx1-ubyte");
      testLabels = Files.readAllBytes(tempPath);
      ByteBuffer testLabelBuffer = ByteBuffer.wrap(testLabels);
      int testMagicLabels = testLabelBuffer.getInt();
      int numberOfTestLabels = testLabelBuffer.getInt();

      tempPath = Paths.get("res/t10k-images-idx3-ubyte");
      testImages = Files.readAllBytes(tempPath);
      ByteBuffer testImageBuffer = ByteBuffer.wrap(testImages);
      int testMagicImages = testImageBuffer.getInt();
      int numberOfTestImages = testImageBuffer.getInt();
      int testRows = testImageBuffer.getInt();
      int testCols = testImageBuffer.getInt();

      for(int i = 0; i < numberOfTestImages; i++) {
          double[] target = new double[]{testLabelBuffer.get()};
          double[] inputs = new double[testRows*testCols];
          for(int j = 0; j < inputs.length; j++) {
              inputs[j] = testImageBuffer.get();
             }
          Data tobj = new Data(inputs, target);
          testData.add(tobj);
         }

       NeuralNetwork neuralNetwork = new NeuralNetwork(784,64,10);

       int len = trainData.size();
       Random randomGenerator = new Random();
       for(int i = 0; i < 400000; i++) {
           int randomInt = randomGenerator.nextInt(len);
           neuralNetwork.train(trainData.get(randomInt).getInputs(), trainData.get(randomInt).getTargets());
          }

        float rightAnswers = 0;

        for(Data testObj : testData) {
           double[] output = neuralNetwork.feedforward(testObj.getInputs());
           double[] answer = testObj.getTargets(); 
         }
            System.out.println(percentage);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        public static double[] createTargets(int number) {
            double[] result = new double[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
            result[number] = 1;
            return  result;

        }
Wiktor
  • 885
  • 1
  • 9
  • 23

1 Answers1

0

If anyone is interested, there was a bug on my part. When logging everything i noticed that the input pixel values ranged from like -255 to 255, and from MNIST documentation they should be 0-255. On top of that my inputs weren't normalized, so some of them were 0 when others 255. That's what i've added. Hope i'm not missing anything. Now I'm getting ~90% of accuracy.

for(int i = 0; i < numberOfTestImages; i++) {

   double[] target = new double[]{testLabelBuffer.get()& 0xFF};
   double[] inputs = new double[testRows*testCols];
   or(int j = 0; j < inputs.length; j++) {
   // Normalize input from 0-255 to 0-1
   double temp = (testImageBuffer.get() & 0xFF) / 255f;
   inputs[j] = temp;
 }
 Data tobj = new Data(inputs, target);
 testData.add(tobj);
}
Wiktor
  • 885
  • 1
  • 9
  • 23