Разные прогнозы для одних и тех же данных

#machine-learning #deeplearning4j #dl4j

#машинное обучение #углубление4j #dl4j

Вопрос:

Я использую Deeplearning4j для классификации названий оборудования. Я отметил ~ 50 000 предметов 495 классами и использую эти данные для обучения нейронной сети.

То есть в качестве входных данных я предоставляю набор векторов (50 000), состоящий из 0 и 1, и ожидаемый класс для каждого вектора (от 0 до 494).

Я использую пример IrisClassifier в качестве основы для кода.

Я сохранил обученную модель в файл и теперь могу использовать ее для прогнозирования класса оборудования.

В качестве примера я попытался использовать для прогнозирования те же данные (50 000 элементов), которые я использовал для обучения, и сравнить прогноз с моей разметкой этих данных.

Результат получился очень хорошим, погрешность нейронной сети составляет ~ 1%.

После этого я попытался использовать для прогнозирования первые 100 векторов из этих 50 000 записей, а остальные 49900 удалил.

И для этих 100 векторов прогноз отличается по сравнению с прогнозом для тех же 100 векторов в составе 50 000.

То есть, чем меньше данных мы предоставляем обученной модели, тем больше ошибка прогнозирования.

Даже для точно таких же векторов.

Почему это происходит?

Мой код.

Обучение:

 //First: get the dataset using the record reader. CSVRecordReader handles loading/parsing int numLinesToSkip = 0; char delimiter = ','; RecordReader recordReader = new CSVRecordReader(numLinesToSkip,delimiter); recordReader.initialize(new FileSplit(new File(args[0])));  //Second: the RecordReaderDataSetIterator handles conversion to DataSet objects, ready for use in neural network int labelIndex = 3331; int numClasses = 495; int batchSize = 4000;  // DataSetIterator iterator = new RecordReaderDataSetIterator(recordReader,batchSize,labelIndex,numClasses); DataSetIterator iterator = new RecordReaderDataSetIterator.Builder(recordReader, batchSize).classification(labelIndex, numClasses).build();  Listlt;DataSetgt; trainingData = new ArrayListlt;gt;(); Listlt;DataSetgt; testData = new ArrayListlt;gt;();  while (iterator.hasNext()) {  DataSet allData = iterator.next();  allData.shuffle();  SplitTestAndTrain testAndTrain = allData.splitTestAndTrain(0.8); //Use 80% of data for training  trainingData.add(testAndTrain.getTrain());  testData.add(testAndTrain.getTest()); }  DataSet allTrainingData = DataSet.merge(trainingData); DataSet allTestData = DataSet.merge(testData);  //We need to normalize our data. We'll use NormalizeStandardize (which gives us mean 0, unit variance): DataNormalization normalizer = new NormalizerStandardize(); normalizer.fit(allTrainingData); //Collect the statistics (mean/stdev) from the training data. This does not modify the input data normalizer.transform(allTrainingData); //Apply normalization to the training data normalizer.transform(allTestData); //Apply normalization to the test data. This is using statistics calculated from the *training* set  long seed = 6; int firstHiddenLayerSize = labelIndex/6; int secondHiddenLayerSize = firstHiddenLayerSize/4;  //log.info("Build model...."); MultiLayerConfiguration conf = new NeuralNetConfiguration.Builder()  .seed(seed)  .activation(Activation.TANH)  .weightInit(WeightInit.XAVIER)  .updater(new Sgd(0.1))  .l2(1e-4)  .list()  .layer(new DenseLayer.Builder().nIn(labelIndex).nOut(firstHiddenLayerSize)  .build())  .layer(new DenseLayer.Builder().nIn(firstHiddenLayerSize).nOut(secondHiddenLayerSize)  .build())  .layer( new OutputLayer.Builder(LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD)  .activation(Activation.SOFTMAX) //Override the global TANH activation with softmax for this layer  .nIn(secondHiddenLayerSize).nOut(numClasses).build())  .build();  //run the model MultiLayerNetwork model = new MultiLayerNetwork(conf); model.init();  //record score once every 100 iterations model.setListeners(new ScoreIterationListener(100));  for(int i=0; ilt;5000; i   ) {  model.fit(allTrainingData); }  //evaluate the model on the test set Evaluation eval = new Evaluation(numClasses);  INDArray output = model.output(allTestData.getFeatures());  eval.eval(allTestData.getLabels(), output); log.info(eval.stats());  // Save the Model File locationToSave = new File(args[1]); model.save(locationToSave, false);  

Предсказание:

 // Open the network file File locationToLoad = new File(args[0]); MultiLayerNetwork model = MultiLayerNetwork.load(locationToLoad, false); model.init();  // First: get the dataset using the record reader. CSVRecordReader handles loading/parsing int numLinesToSkip = 0; char delimiter = ',';  // Data to predict CSVRecordReader recordReader = new CSVRecordReader(numLinesToSkip, delimiter); //skip no lines at the top - i.e. no header recordReader.initialize(new FileSplit(new File(args[1])));  //Second: the RecordReaderDataSetIterator handles conversion to DataSet objects, ready for use in neural network int batchSize = 4000;  DataSetIterator iterator = new RecordReaderDataSetIterator.Builder(recordReader, batchSize).build();  Listlt;DataSetgt; dataSetList = new ArrayListlt;gt;();  while (iterator.hasNext()) {  DataSet allData = iterator.next();  dataSetList.add(allData); }  DataSet dataSet = DataSet.merge(dataSetList);  DataNormalization normalizer = new NormalizerStandardize(); normalizer.fit(dataSet); normalizer.transform(dataSet);  // Now use it to classify some data INDArray output = model.output(dataSet.getFeatures());  // Save result BufferedWriter writer = new BufferedWriter(new FileWriter(args[2], true)); for (int i=0; ilt;output.rows(); i  ) {  writer  .append(output.getRow(i).argMax().toString())  .append(" ")  .append(String.valueOf(i))  .append(" ")  .append(output.getRow(i).toString())  .append('n'); } writer.close();  

Ответ №1:

Убедитесь, что вы сохранили нормализатор следующим образом вместе с моделью:

 import org.nd4j.linalg.dataset.api.preprocessor.serializer.NormalizerSerializer;  NormalizerSerializer SUT = NormalizerSerializer.getDefault();   SUT.write(normalizer,new File("outputFile.bin"));   NormalizeStandardize restored = SUT.restore(new File("outputFile.bin");  

Ответ №2:

Вам нужно использовать одни и те же данные нормализатора как для обучения, так и для прогнозирования. В противном случае он будет использовать неверную статистику при преобразовании ваших данных.

То, как вы это делаете в настоящее время, приводит к получению данных, которые сильно отличаются от данных обучения, вот почему вы получаете такой другой результат.

Комментарии:

1. Я использую нормализатор нормализации данных = новый стандарт нормализации(); как в обучении, так и в прогнозах.. Или, может быть, вы имеете в виду, что мне нужно сохранять данные нормализатора при обучении и загружать их в прогнозы ?

2. Нормализатор имеет среднее значение и дисперсию, которые он извлекает из обучающих данных. Вам нужно сохранить нормализатор и загрузить его с этой статистикой после вызова fit, чтобы правильно обработать данные.

3. Правильно ли я понимаю, что мне нужно сохранить нормализатор при сохранении модели? Но метод сохранения имеет только два параметра: model.save (файл, saveUpdater); Не могли бы вы предоставить ссылку для примера кода о том, как правильно сохранить и загрузить нормализатор? Спасибо!