or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

dataset-iteration.mdindex.mdmulti-input-output.mdsequence-processing.mdspark-integration.md

multi-input-output.mddocs/

0

# Multi-Input/Output Support

1

2

Advanced multi-modal data processing for complex neural network architectures with multiple inputs and outputs. The RecordReaderMultiDataSetIterator uses a flexible builder pattern to configure multiple data sources and map them to different network inputs and outputs.

3

4

## Capabilities

5

6

### RecordReaderMultiDataSetIterator

7

8

Main class for creating MultiDataSet objects from multiple RecordReaders and SequenceRecordReaders.

9

10

```java { .api }

11

public class RecordReaderMultiDataSetIterator implements MultiDataSetIterator {

12

// Iterator methods

13

public boolean hasNext();

14

public MultiDataSet next();

15

public MultiDataSet next(int num);

16

public void remove();

17

18

// Configuration methods

19

public void setPreProcessor(MultiDataSetPreProcessor preProcessor);

20

public MultiDataSetPreProcessor getPreProcessor();

21

public void setCollectMetaData(boolean collectMetaData);

22

public boolean getCollectMetaData();

23

24

// Reset and async support

25

public boolean resetSupported();

26

public boolean asyncSupported();

27

public void reset();

28

29

// Metadata support

30

public MultiDataSet loadFromMetaData(RecordMetaData recordMetaData) throws IOException;

31

public MultiDataSet loadFromMetaData(List<RecordMetaData> recordMetaDatas) throws IOException;

32

}

33

```

34

35

### Builder Class

36

37

Fluent API for configuring multi-input/output data processing.

38

39

```java { .api }

40

public static class Builder {

41

public Builder(int batchSize);

42

43

// Add data readers

44

public Builder addReader(String readerName, RecordReader recordReader);

45

public Builder addSequenceReader(String seqReaderName, SequenceRecordReader seqRecordReader);

46

47

// Configure sequence alignment

48

public Builder sequenceAlignmentMode(AlignmentMode alignmentMode);

49

50

// Add inputs (features)

51

public Builder addInput(String readerName);

52

public Builder addInput(String readerName, int columnFirst, int columnLast);

53

public Builder addInputOneHot(String readerName, int column, int numClasses);

54

55

// Add outputs (labels)

56

public Builder addOutput(String readerName);

57

public Builder addOutput(String readerName, int columnFirst, int columnLast);

58

public Builder addOutputOneHot(String readerName, int column, int numClasses);

59

60

// Time series configuration

61

public Builder timeSeriesRandomOffset(boolean timeSeriesRandomOffset, long rngSeed);

62

63

// Build the iterator

64

public RecordReaderMultiDataSetIterator build();

65

}

66

```

67

68

### AlignmentMode Enum

69

70

```java { .api }

71

public enum AlignmentMode {

72

EQUAL_LENGTH, // All sequences must be the same length

73

ALIGN_START, // Align sequences at start, pad end

74

ALIGN_END // Align sequences at end, pad start

75

}

76

```

77

78

## Usage Examples

79

80

### Basic Multi-Input Example

81

82

```java

83

import org.datavec.api.records.reader.impl.csv.CSVRecordReader;

84

import org.datavec.api.split.FileSplit;

85

import org.deeplearning4j.datasets.datavec.RecordReaderMultiDataSetIterator;

86

87

// Setup multiple record readers

88

RecordReader featuresReader = new CSVRecordReader();

89

featuresReader.initialize(new FileSplit(new File("features.csv")));

90

91

RecordReader labelsReader = new CSVRecordReader();

92

labelsReader.initialize(new FileSplit(new File("labels.csv")));

93

94

// Build multi-input iterator

95

RecordReaderMultiDataSetIterator iterator =

96

new RecordReaderMultiDataSetIterator.Builder(32) // batch size

97

.addReader("features", featuresReader)

98

.addReader("labels", labelsReader)

99

.addInput("features") // All columns from features as input

100

.addOutput("labels") // All columns from labels as output

101

.build();

102

103

// Use iterator

104

while (iterator.hasNext()) {

105

MultiDataSet multiDataSet = iterator.next();

106

INDArray[] inputs = multiDataSet.getFeatures(); // Array of input arrays

107

INDArray[] outputs = multiDataSet.getLabels(); // Array of output arrays

108

}

109

```

110

111

### Multiple Inputs and Outputs

112

113

```java

114

// Setup readers for different data modalities

115

RecordReader imageReader = new ImageRecordReader();

116

RecordReader textReader = new CSVRecordReader();

117

RecordReader metadataReader = new CSVRecordReader();

118

119

// Initialize readers

120

imageReader.initialize(new FileSplit(new File("images/")));

121

textReader.initialize(new FileSplit(new File("text_features.csv")));

122

metadataReader.initialize(new FileSplit(new File("metadata.csv")));

123

124

// Configure multi-modal architecture

125

RecordReaderMultiDataSetIterator iterator =

126

new RecordReaderMultiDataSetIterator.Builder(16)

127

// Add all readers

128

.addReader("images", imageReader)

129

.addReader("text", textReader)

130

.addReader("metadata", metadataReader)

131

132

// Configure multiple inputs

133

.addInput("images") // Input 0: Image data

134

.addInput("text", 0, 99) // Input 1: Text features (columns 0-99)

135

.addInput("metadata", 0, 9) // Input 2: Metadata (columns 0-9)

136

137

// Configure multiple outputs

138

.addOutputOneHot("metadata", 10, 5) // Output 0: Classification (column 10, 5 classes)

139

.addOutput("metadata", 11, 13) // Output 1: Regression (columns 11-13)

140

.build();

141

142

// Process multi-modal data

143

while (iterator.hasNext()) {

144

MultiDataSet batch = iterator.next();

145

146

// Access multiple inputs

147

INDArray imageInput = batch.getFeatures(0); // Images

148

INDArray textInput = batch.getFeatures(1); // Text features

149

INDArray metadataInput = batch.getFeatures(2); // Metadata

150

151

// Access multiple outputs

152

INDArray classificationOutput = batch.getLabels(0); // One-hot classification

153

INDArray regressionOutput = batch.getLabels(1); // Regression targets

154

}

155

```

156

157

### Sequence Multi-Input Example

158

159

```java

160

import org.datavec.api.records.reader.impl.csv.CSVSequenceRecordReader;

161

162

// Setup sequence readers

163

SequenceRecordReader audioReader = new CSVSequenceRecordReader();

164

SequenceRecordReader videoReader = new CSVSequenceRecordReader();

165

SequenceRecordReader labelReader = new CSVSequenceRecordReader();

166

167

// Initialize sequence readers

168

audioReader.initialize(new NumberedFileInputSplit("audio_%d.csv", 0, 999));

169

videoReader.initialize(new NumberedFileInputSplit("video_%d.csv", 0, 999));

170

labelReader.initialize(new NumberedFileInputSplit("labels_%d.csv", 0, 999));

171

172

// Configure multi-modal sequence processing

173

RecordReaderMultiDataSetIterator iterator =

174

new RecordReaderMultiDataSetIterator.Builder(8)

175

// Add sequence readers

176

.addSequenceReader("audio", audioReader)

177

.addSequenceReader("video", videoReader)

178

.addSequenceReader("labels", labelReader)

179

180

// Configure sequence alignment

181

.sequenceAlignmentMode(AlignmentMode.ALIGN_START)

182

183

// Add sequence inputs

184

.addInput("audio") // Audio features

185

.addInput("video") // Video features

186

187

// Add sequence output

188

.addOutputOneHot("labels", 0, 10) // 10-class classification per time step

189

190

.build();

191

```

192

193

### Column Range Selection

194

195

```java

196

// Fine-grained control over which columns to use

197

RecordReader dataReader = new CSVRecordReader();

198

dataReader.initialize(new FileSplit(new File("complex_data.csv")));

199

200

RecordReaderMultiDataSetIterator iterator =

201

new RecordReaderMultiDataSetIterator.Builder(64)

202

.addReader("data", dataReader)

203

204

// Use specific column ranges for different inputs

205

.addInput("data", 0, 49) // Input 0: Columns 0-49 (features)

206

.addInput("data", 50, 99) // Input 1: Columns 50-99 (different feature type)

207

208

// Use specific columns for outputs

209

.addOutputOneHot("data", 100, 3) // Output 0: Column 100, 3 classes

210

.addOutput("data", 101, 105) // Output 1: Columns 101-105 (regression)

211

212

.build();

213

```

214

215

### Time Series Random Offset

216

217

```java

218

// Add random time offset for data augmentation

219

RecordReaderMultiDataSetIterator iterator =

220

new RecordReaderMultiDataSetIterator.Builder(32)

221

.addSequenceReader("sequences", sequenceReader)

222

.addInput("sequences")

223

.addOutput("sequences", 10, 12)

224

225

// Enable random time series offset

226

.timeSeriesRandomOffset(true, 12345L) // enabled, with seed

227

228

.build();

229

```

230

231

### Preprocessing Multi-Modal Data

232

233

```java

234

import org.nd4j.linalg.dataset.api.preprocessor.MultiDataSetPreProcessor;

235

import org.nd4j.linalg.dataset.api.preprocessor.MultiNormalizerMinMaxScaler;

236

237

// Create iterator

238

RecordReaderMultiDataSetIterator iterator =

239

new RecordReaderMultiDataSetIterator.Builder(32)

240

.addReader("input1", reader1)

241

.addReader("input2", reader2)

242

.addInput("input1")

243

.addInput("input2")

244

.addOutput("input1", 10, 12)

245

.build();

246

247

// Add multi-input preprocessing

248

MultiNormalizerMinMaxScaler scaler = new MultiNormalizerMinMaxScaler();

249

iterator.setPreProcessor(scaler);

250

251

// Fit preprocessor

252

scaler.fit(iterator);

253

iterator.reset();

254

255

// Use preprocessed data

256

while (iterator.hasNext()) {

257

MultiDataSet preprocessed = iterator.next();

258

// All inputs normalized independently

259

}

260

```

261

262

## Advanced Configuration

263

264

### Builder Method Details

265

266

#### Reader Management

267

- `addReader(name, reader)`: Add a RecordReader with a string identifier

268

- `addSequenceReader(name, reader)`: Add a SequenceRecordReader with identifier

269

270

#### Input Configuration

271

- `addInput(readerName)`: Use all columns from reader as input

272

- `addInput(readerName, start, end)`: Use columns start to end (inclusive) as input

273

- `addInputOneHot(readerName, column, numClasses)`: Convert column to one-hot encoding

274

275

#### Output Configuration

276

- `addOutput(readerName)`: Use all columns from reader as output

277

- `addOutput(readerName, start, end)`: Use columns start to end (inclusive) as output

278

- `addOutputOneHot(readerName, column, numClasses)`: Convert column to one-hot encoding

279

280

## Error Handling

281

282

### Common Exceptions

283

- **IllegalArgumentException**: Invalid builder configuration

284

- **IllegalStateException**: Builder used incorrectly (e.g., no inputs defined)

285

- **IOException**: RecordReader I/O errors

286

287

### Validation Rules

288

- At least one input must be defined

289

- At least one output must be defined

290

- Reader names must be unique

291

- Column indices must be valid for their respective readers

292

- Batch size must be positive

293

- Sequence readers require consistent sequence alignment mode