You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Deeplearning4j处理大规模数据时如何正确迭代多个DataSet

报错原因

你遇到的空指针是因为非法初始化了NDArray:INDArray output = new NDArray()用无参构造创建的NDArray没有分配内存、没有定义shape,内部jvmShapeInfo属性为null,调用add方法自然触发空指针。同时你现有的数据处理逻辑还有两处明显错误,会导致训练结果不可用:

  • 归一化逻辑错误:分批对每个训练DataSet调用fit方法,会让NormalizerStandardize每次用当前批次的均值、方差覆盖之前的统计值,最终得到的是最后一个训练批次的统计参数,不是全量训练集的统计结果,归一化完全无效。
  • 数据集拆分逻辑缺陷:每个批次单独拆分65%训练、35%测试,无法保证训练集和测试集的全局分布一致性,会影响最终评估指标的可信度。

Deeplearning4j大规模数据训练的正确实现

Deeplearning4j的DataSetIterator本身就是为了处理无法全量加载到内存的大数据设计的,不需要你手动把DataSet存入List再循环遍历,按以下步骤实现即可:

1. 提前拆分数据集

优先把全量3万条数据提前随机拆分为训练集、测试集两个独立文件,避免在内存中做拆分,简化后续处理逻辑。

2. 构建迭代器与归一化

直接用DataSetIterator读取数据,批量拟合归一化参数,框架会自动逐批次读取收集统计值,不会加载全量数据:

// 训练集迭代器,batchSize根据JVM内存调整,保证单批次加载不会触发OOM即可,比如设为32/64
int batchSize = 64;
RecordReader trainReader = new CSVRecordReader(0, ',');
trainReader.initialize(new FileSplit(new File("你的训练集路径.csv")));
DataSetIterator trainIter = new RecordReaderDataSetIterator(trainReader, batchSize, labelIndex, numClasses);

// 拟合全量训练集的归一化统计值
DataNormalization normalizer = new NormalizerStandardize();
normalizer.fit(trainIter);
// 给迭代器绑定预处理器,后续取出的所有DataSet会自动完成归一化
trainIter.setPreProcessor(normalizer);

// 测试集迭代器同理绑定归一化器,用训练集的统计值做归一化
RecordReader testReader = new CSVRecordReader(0, ',');
testReader.initialize(new FileSplit(new File("你的测试集路径.csv")));
DataSetIterator testIter = new RecordReaderDataSetIterator(testReader, batchSize, labelIndex, numClasses);
testIter.setPreProcessor(normalizer);

3. 模型训练

直接把迭代器传给fit方法,框架会自动逐批次喂入数据训练:

for (int i = 0; i < 1000; i++) {
    model.fit(trainIter);
    trainIter.reset(); // 每轮训练结束重置迭代器,下一轮从头读取数据
}

4. 分批评估

不需要拼接所有测试集的输出和标签,Evaluation支持分批传入数据自动累计指标,完全避免加载全量测试集:

Evaluation eval = new Evaluation(numClasses);
while (testIter.hasNext()) {
    DataSet testBatch = testIter.next();
    INDArray batchOutput = model.output(testBatch.getFeatures());
    eval.eval(testBatch.getLabels(), batchOutput);
}
testIter.reset();
log.info(eval.stats());

兼容现有List存储方案的修改方式

如果你不想修改现有拆分数据集存List的逻辑,只需要修改两处即可解决问题:

  1. 归一化部分:先把训练集List转为迭代器再拟合,保证统计值是全量训练集的:
DataSetIterator trainListIter = new ListDataSetIterator(trainingData, batchSize);
normalizer.fit(trainListIter);
// 再遍历训练集、测试集List调用transform即可
  1. 评估部分:删除空NDArray拼接逻辑,直接分批传入Evaluation评估即可。

内容的提问来源于stack exchange,提问作者apollox

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 13:48:04