簡體   English   中英

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假設數據集是小批量的,例如:它們並非都在內存中。 這與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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM