[英]Deeplearning4j Splitting datasets for test and train
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因为生成测试和样本数据集这样简单而被破坏,那么它是否应该被任何东西信任? 或者我会更好地使用不同的库?
Deeplearning4j假设数据集是小批量的,例如:它们并非都在内存中。 这与python世界相矛盾,python世界可能会为较小的数据集和易用性优化更多。
这仅适用于玩具问题,并且不能很好地适应实际问题。 代替这一点,我们针对本地场景优化了数据集界面(请注意,对于像spark这样的分布式系统,这将是不同的)。
这意味着我们依赖数据集或者在使用datavec解析数据集之前进行拆分(提示:不要编写自己的迭代器:使用我们的数据集并使用datavec进行自定义解析)或允许使用数据库分类器: https:// deeplearning4j.org/doc/org/deeplearning4j/datasets/iterator/DataSetIteratorSplitter.html用于列车测试拆分。
数据集拆分列车测试类仅在数据集已经全部存储在内存中时才有效,但对于大多数半实际问题可能没有意义(例如:超越xor或mnist)
我建议运行一次ETL步骤,而不是每次都运行。 将数据集打包到预先切片的批次中。 一种方法是组合: https : //github.com/deeplearning4j/deeplearning4j/blob/master/nd4j/nd4j-backends/nd4j-tests/src/test/java/org/nd4j/linalg/dataset / BalanceMinibatchesTest.java#L40和: https : //nd4j.org/doc/org/nd4j/linalg/dataset/ExistingMiniBatchDataSetIterator.html
这样做的另一个原因是可重复性。 如果你想做一些像每个时代的迭代器那样的东西,你可以尝试根据上面的组合编写一些代码。 无论哪种方式,我都会尝试处理您的ETL并在训练之前预先创建向量。 否则,您将花费大量时间在较大数据集上加载数据。
据我所知,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;
}
}
这有效,但它并没有让我对图书馆充满信心。 如果其他人可以提供更好的答案仍然很高兴,但现在必须这样做。
由于这个问题已经过时,对于可能会发现这个问题的人来说,您可以在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();
首先,您创建迭代器,迭代所有数据,将其洗牌以及测试和训练之间的分割。
这是从这个例子中得到的
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.