神经网络 MNIST 数字识别

Neural Network MNIST number recognition

我最近尝试用神经网络创建我的第一个项目,这就是我想到的。我想让它识别 MNIST 手写数字。问题是,当我 运行 这段代码并让它训练大约 400k 次时,我得到了大约 28% 的测试数据准确率。应该是这样吗?是400k太少,效果不好,还是因为我的神经网络只能有一个隐藏层?

总结一下简短的问题,事情应该看起来像那样,还是我做错了什么?下面有很多冗余代码之类的,我只是想让它工作。

假设我的神经网络显然有效。

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;

        }

如果有人有兴趣,我有一个错误。在记录所有内容时,我注意到输入像素值的范围从 -255 到 255,根据 MNIST 文档,它们应该是 0-255。最重要的是,我的输入没有标准化,所以其中一些是 0,而另一些是 255。这就是我添加的。希望我没有遗漏任何东西。现在我得到了大约 90% 的准确率。

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);
}