#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); Не могли бы вы предоставить ссылку для примера кода о том, как правильно сохранить и загрузить нормализатор? Спасибо!