[英]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.