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因生成测试和样本数据集这样简单而被破坏,那么它是否应该被任何东西信任?或者我会更好地使用不同的库?
答案 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示例