Deeplearning4j 拆分数据集进行测试和训练
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 简直是坏掉了。最终我创建了自己的 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;
}
}
这行得通,但我对图书馆没有信心。如果其他人可以提供更好的答案,我仍然很高兴,但现在必须这样做。
由于这个问题已经过时了,对于可能发现这个问题的人,你可以看一些例子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示例
Deeplearning4j 假设数据集是小批量的,例如:它们并不都在内存中。
这与 python 世界相矛盾,后者可能会针对较小的数据集和易用性进行更多优化。
这只适用于玩具问题,不能很好地扩展到实际问题。
取而代之的是,我们针对本地场景优化了 datasetiterator 接口(请注意,对于像 spark 这样的分布式系统,这将有所不同)。
这意味着我们依赖于使用 datavec 预先拆分数据集来解析数据集(提示:不要编写自己的迭代器:使用我们的迭代器并使用 datavec 进行自定义解析)或允许使用 datasetiterator 拆分器: https://deeplearning4j.org/doc/org/deeplearning4j/datasets/iterator/DataSetIteratorSplitter.html 用于火车测试拆分。
数据集拆分训练测试 class 仅当数据集已全部在内存中时才有效,但对于大多数半现实问题(例如:超越 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 具有支持将数据集拆分为测试和训练的功能,以及洗牌数据集的机制,但据我所知,要么它们不起作用,要么我做错了什么。
示例:
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 简直是坏掉了。最终我创建了自己的 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;
}
}
这行得通,但我对图书馆没有信心。如果其他人可以提供更好的答案,我仍然很高兴,但现在必须这样做。
由于这个问题已经过时了,对于可能发现这个问题的人,你可以看一些例子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示例
Deeplearning4j 假设数据集是小批量的,例如:它们并不都在内存中。 这与 python 世界相矛盾,后者可能会针对较小的数据集和易用性进行更多优化。
这只适用于玩具问题,不能很好地扩展到实际问题。 取而代之的是,我们针对本地场景优化了 datasetiterator 接口(请注意,对于像 spark 这样的分布式系统,这将有所不同)。
这意味着我们依赖于使用 datavec 预先拆分数据集来解析数据集(提示:不要编写自己的迭代器:使用我们的迭代器并使用 datavec 进行自定义解析)或允许使用 datasetiterator 拆分器: https://deeplearning4j.org/doc/org/deeplearning4j/datasets/iterator/DataSetIteratorSplitter.html 用于火车测试拆分。
数据集拆分训练测试 class 仅当数据集已全部在内存中时才有效,但对于大多数半现实问题(例如:超越 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 并在您进行培训之前预先创建向量。否则,您将花费大量时间在更大的数据集上加载数据。