Deeplearning4j为测试和训练分割数据集

时间:2015-11-24 20:10:17

标签: java machine-learning deep-learning

Deeplearning4j具有支持将数据集拆分为测试和训练的功能,以及用于改组数据集的机制,但据我所知,它们不起作用或者我做错了。

示例:

    DataSetIterator iter = new IrisDataSetIterator(150, 150);
    DataSet next = iter.next();
    // next.shuffle();
    SplitTestAndTrain testAndTrain = next.splitTestAndTrain(120, new Random(seed));
    DataSet train = testAndTrain.getTrain();
    DataSet test = testAndTrain.getTest();

    for (int i = 0; i < 30; i++) {
        String features = test.getFeatures().getRow(i).toString();
        String actual = test.getLabels().getRow(i).toString().trim();
        log.info("features " + features + " -> " + actual );
    }

返回的输入数据集的最后30行中的结果,splitTestAndTrain的Random(seed)参数似乎已被完全忽略。

如果不是将随机种子传递给splitTestAndTrain而是取消注释next.shuffle()行,那么奇怪的是第3和第4个特征在保持第1和第2个特征以及测试标签的现有顺序的同时被洗牌,这甚至比根本没有对输入进行排序更糟糕。

所以...问题是,我使用它是错误的,还是Deeplearning4j本身就已经坏了?

奖金问题:如果Deeplearning4j因生成测试和样本数据集这样简单而被破坏,那么它是否应该被任何东西信任?或者我会更好地使用不同的库?

3 个答案:

答案 0 :(得分:1)

Deeplearning4j假设数据集是迷你批处理,例如:它们不在内存中。 这与python世界相矛盾,后者可能会为较小的数据集和易用性进行更多优化。

这仅适用于玩具问题,不适用于实际问题。 取而代之的是,我们针对本地场景优化了datasetiterator接口(请注意,对于像spark这样的分布式系统,这将有所不同。)

这意味着我们依赖于使用datavec预先拆分数据集来解析数据集(提示:不要编写自己的迭代器:使用我们的迭代器,并使用datavec进行自定义解析),或者允许使用数据集迭代器拆分器:{ {3}}用于火车试车。

仅当数据集已经全部存在但对大多数半现实问题(例如:超越xor或mnist)有意义时,数据集拆分训练测试类才起作用。

我建议一次而不是每次都运行ETL步骤。将数据集预先混洗为预先切片的批次。 一种实现方法是结合使用https://deeplearning4j.org/doc/org/deeplearning4j/datasets/iterator/DataSetIteratorSplitter.html和: https://github.com/deeplearning4j/deeplearning4j/blob/master/nd4j/nd4j-backends/nd4j-tests/src/test/java/org/nd4j/linalg/dataset/BalanceMinibatchesTest.java#L40

另一个原因是可重复性。如果您想做一些在每个时期都将迭代器改组的操作,则可以尝试根据上述组合编写一些代码。无论哪种方式,我都会尝试处理您的ETL,并在进行训练之前预先创建向量。否则,您将花费大量时间在较大的数据集上进行数据加载。

答案 1 :(得分:0)

据我所知,deeplearning4j被打破了。最终我创建了自己的splitTestandTrain实现。

import org.nd4j.linalg.api.ndarray.INDArray;
import org.nd4j.linalg.dataset.DataSet;
import java.util.Random;
import org.nd4j.linalg.factory.Nd4j;

public class TestTrain {  
    protected DataSet test;
    protected DataSet train;

    public TestTrain(DataSet input, int splitSize, Random rng) {
        int inTest = 0;
        int inTrain = 0;
        int testSize = input.numExamples() - splitSize;

        INDArray train_features = Nd4j.create(splitSize, input.getFeatures().columns());
        INDArray train_outcomes = Nd4j.create(splitSize, input.numOutcomes());
        INDArray test_features  = Nd4j.create(testSize, input.getFeatures().columns());
        INDArray test_outcomes  = Nd4j.create(testSize, input.numOutcomes());

        for (int i = 0; i < input.numExamples(); i++) {
            DataSet D = input.get(i);
            if (rng.nextDouble() < (splitSize-inTrain)/(double)(input.numExamples()-i)) {
                train_features.putRow(inTrain, D.getFeatures());
                train_outcomes.putRow(inTrain, D.getLabels());
                inTrain += 1;
            } else {
                test_features.putRow(inTest, D.getFeatures());
                test_outcomes.putRow(inTest, D.getLabels());
                inTest += 1;
            }
        }

        train = new DataSet(train_features, train_outcomes);
        test  = new DataSet(test_features, test_outcomes);
    }

    public DataSet getTrain() {
        return train;
    }

    public DataSet getTest() {
        return test;
    }
}

这有效,但它并没有让我对图书馆充满信心。如果其他人可以提供更好的答案仍然很高兴,但现在必须这样做。

答案 2 :(得分:0)

由于这个问题已经过时,对于可能会发现此问题的人,您可以看到一些示例on GitHub,可以通过一种简单的方式来完成拆分:

DataSetIterator iterator = new RecordReaderDataSetIterator(recordReader,batchSize,labelIndex,numClasses);
DataSet allData = iterator.next();
allData.shuffle();
SplitTestAndTrain testAndTrain = allData.splitTestAndTrain(0.65);  //Use 65% of data for training

DataSet trainingData = testAndTrain.getTrain();
DataSet testData = testAndTrain.getTest();

首先,您要创建迭代器,遍历所有数据,对数据进行混洗以及测试和训练之间的划分。

这取自this示例

相关问题