Logo ROOT   6.12/07
Reference Guide
DataLoader.h
Go to the documentation of this file.
1 // @(#)root/tmva/tmva/dnn:$Id$
2 // Author: Simon Pfreundschuh 08/08/16
3 
4 /*************************************************************************
5  * Copyright (C) 2016, Simon Pfreundschuh *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /////////////////////////////////////////////////////////////////////
13 // Generic data loader for neural network input data. Provides a //
14 // high level abstraction for the transfer of training data to the //
15 // device. //
16 /////////////////////////////////////////////////////////////////////
17 
18 #ifndef TMVA_DNN_DATALOADER
19 #define TMVA_DNN_DATALOADER
20 
21 #include "TMatrix.h"
22 #include "TMVA/Event.h"
23 
24 #include <algorithm>
25 #include <iostream>
26 #include <random>
27 #include <vector>
28 
29 namespace TMVA {
30 
31 class DataSetInfo;
32 
33 namespace DNN {
34 
35 //
36 // Input Data Types
37 //______________________________________________________________________________
38 using MatrixInput_t = std::tuple<const TMatrixT<Double_t> &, const TMatrixT<Double_t> &, const TMatrixT<Double_t> &>;
39 using TMVAInput_t =
40  std::tuple<const std::vector<Event *> &, const DataSetInfo &>;
41 
42 using IndexIterator_t = typename std::vector<size_t>::iterator;
43 
44 /** TBatch
45  *
46  * Class representing training batches consisting of a matrix of input data
47  * and a matrix of output data. The input and output data can be accessed using
48  * the GetInput() and GetOutput() member functions.
49  *
50  * \tparam AArchitecture The underlying architecture.
51  */
52 //______________________________________________________________________________
53 template <typename AArchitecture>
54 class TBatch
55 {
56 private:
57 
58  using Matrix_t = typename AArchitecture::Matrix_t;
59 
63 
64 public:
66  TBatch(const TBatch &) = default;
67  TBatch( TBatch &&) = default;
68  TBatch & operator=(const TBatch &) = default;
69  TBatch & operator=( TBatch &&) = default;
70 
71  /** Return the matrix representing the input data. */
73  /** Return the matrix representing the output data. */
75  /** Return the matrix holding the event weights. */
77 };
78 
79 template<typename Data_t, typename AArchitecture> class TDataLoader;
80 
81 /** TBatchIterator
82  *
83  * Simple iterator class for the iterations over the training batches in
84  * a given data set represented by a TDataLoader object.
85  *
86  * \tparam AData The input data type.
87  * \tparam AArchitecture The underlying architecture type.
88  */
89 template<typename Data_t, typename AArchitecture>
91 {
92 private:
93 
95  size_t fBatchIndex;
96 
97 public:
98 
99 TBatchIterator(TDataLoader<Data_t, AArchitecture> & dataLoader, size_t index = 0)
100 : fDataLoader(dataLoader), fBatchIndex(index)
101 {
102  // Nothing to do here.
103 }
104 
105  TBatch<AArchitecture> operator*() {return fDataLoader.GetBatch();}
106  TBatchIterator operator++() {fBatchIndex++; return *this;}
107  bool operator!=(const TBatchIterator & other) {
108  return fBatchIndex != other.fBatchIndex;
109  }
110 };
111 
112 /** TDataLoader
113  *
114  * Service class managing the streaming of the training data from the input data
115  * type to the accelerator device or the CPU. A TDataLoader object manages a number
116  * of host and device buffer pairs that are used in a round-robin manner for the
117  * transfer of batches to the device.
118  *
119  * Each TDataLoader object has an associated batch size and a number of total
120  * samples in the dataset. One epoch is the number of buffers required to transfer
121  * the complete training set. Using the begin() and end() member functions allows
122  * the user to iterate over the batches in one epoch.
123  *
124  * \tparam AData The input data type.
125  * \tparam AArchitecture The achitecture class of the underlying architecture.
126  */
127 template<typename Data_t, typename AArchitecture>
128 class TDataLoader
129 {
130 private:
131 
132  using HostBuffer_t = typename AArchitecture::HostBuffer_t;
133  using DeviceBuffer_t = typename AArchitecture::DeviceBuffer_t;
134  using Matrix_t = typename AArchitecture::Matrix_t;
136 
137  const Data_t &fData;
138 
139  size_t fNSamples;
140  size_t fBatchSize;
143  size_t fBatchIndex;
144 
145  size_t fNStreams; ///< Number of buffer pairs.
146  std::vector<DeviceBuffer_t> fDeviceBuffers;
147  std::vector<HostBuffer_t> fHostBuffers;
148 
149  std::vector<size_t> fSampleIndices; ///< Ordering of the samples in the epoch.
150 
151 public:
152 
153  TDataLoader(const Data_t & data, size_t nSamples, size_t batchSize,
154  size_t nInputFeatures, size_t nOutputFeatures, size_t nStreams = 1);
155  TDataLoader(const TDataLoader &) = default;
156  TDataLoader( TDataLoader &&) = default;
157  TDataLoader & operator=(const TDataLoader &) = default;
158  TDataLoader & operator=( TDataLoader &&) = default;
159 
160  /** Copy input matrix into the given host buffer. Function to be specialized by
161  * the architecture-specific backend. */
162  void CopyInput(HostBuffer_t &buffer, IndexIterator_t begin, size_t batchSize);
163  /** Copy output matrix into the given host buffer. Function to be specialized
164  * by the architecture-spcific backend. */
165  void CopyOutput(HostBuffer_t &buffer, IndexIterator_t begin, size_t batchSize);
166  /** Copy weight matrix into the given host buffer. Function to be specialized
167  * by the architecture-spcific backend. */
168  void CopyWeights(HostBuffer_t &buffer, IndexIterator_t begin, size_t batchSize);
169 
172  {
173  return TBatchIterator<Data_t, AArchitecture>(*this, fNSamples / fBatchSize);
174  }
175 
176  /** Shuffle the order of the samples in the batch. The shuffling is indirect,
177  * i.e. only the indices are shuffled. No input data is moved by this
178  * routine. */
179  void Shuffle();
180 
181  /** Return the next batch from the training set. The TDataLoader object
182  * keeps an internal counter that cycles over the batches in the training
183  * set. */
184  TBatch<AArchitecture> GetBatch();
185 
186 };
187 
188 //
189 // TBatch Class.
190 //______________________________________________________________________________
191 template <typename AArchitecture>
192 TBatch<AArchitecture>::TBatch(Matrix_t &inputMatrix, Matrix_t &outputMatrix, Matrix_t &weightMatrix)
193  : fInputMatrix(inputMatrix), fOutputMatrix(outputMatrix), fWeightMatrix(weightMatrix)
194 {
195  // Nothing to do here.
196 }
197 
198 //
199 // TDataLoader Class.
200 //______________________________________________________________________________
201 template<typename Data_t, typename AArchitecture>
203  const Data_t & data, size_t nSamples, size_t batchSize,
204  size_t nInputFeatures, size_t nOutputFeatures, size_t nStreams)
205  : fData(data), fNSamples(nSamples), fBatchSize(batchSize),
206  fNInputFeatures(nInputFeatures), fNOutputFeatures(nOutputFeatures),
207  fBatchIndex(0), fNStreams(nStreams), fDeviceBuffers(), fHostBuffers(),
208  fSampleIndices()
209 {
210  size_t inputMatrixSize = fBatchSize * fNInputFeatures;
211  size_t outputMatrixSize = fBatchSize * fNOutputFeatures;
212  size_t weightMatrixSize = fBatchSize;
213 
214  for (size_t i = 0; i < fNStreams; i++)
215  {
216  fHostBuffers.push_back(HostBuffer_t(inputMatrixSize + outputMatrixSize + weightMatrixSize));
217  fDeviceBuffers.push_back(DeviceBuffer_t(inputMatrixSize + outputMatrixSize + weightMatrixSize));
218  }
219 
220  fSampleIndices.reserve(fNSamples);
221  for (size_t i = 0; i < fNSamples; i++) {
222  fSampleIndices.push_back(i);
223  }
224 }
225 
226 //______________________________________________________________________________
227 template<typename Data_t, typename AArchitecture>
229 {
230  fBatchIndex %= (fNSamples / fBatchSize); // Cycle through samples.
231 
232 
233  size_t inputMatrixSize = fBatchSize * fNInputFeatures;
234  size_t outputMatrixSize = fBatchSize * fNOutputFeatures;
235  size_t weightMatrixSize = fBatchSize;
236 
237  size_t streamIndex = fBatchIndex % fNStreams;
238  HostBuffer_t & hostBuffer = fHostBuffers[streamIndex];
239  DeviceBuffer_t & deviceBuffer = fDeviceBuffers[streamIndex];
240 
241  HostBuffer_t inputHostBuffer = hostBuffer.GetSubBuffer(0, inputMatrixSize);
242  HostBuffer_t outputHostBuffer = hostBuffer.GetSubBuffer(inputMatrixSize,
243  outputMatrixSize);
244  HostBuffer_t weightHostBuffer = hostBuffer.GetSubBuffer(inputMatrixSize + outputMatrixSize, weightMatrixSize);
245 
246  DeviceBuffer_t inputDeviceBuffer = deviceBuffer.GetSubBuffer(0, inputMatrixSize);
247  DeviceBuffer_t outputDeviceBuffer = deviceBuffer.GetSubBuffer(inputMatrixSize,
248  outputMatrixSize);
249  DeviceBuffer_t weightDeviceBuffer = deviceBuffer.GetSubBuffer(inputMatrixSize + outputMatrixSize, weightMatrixSize);
250 
251  size_t sampleIndex = fBatchIndex * fBatchSize;
252  IndexIterator_t sampleIndexIterator = fSampleIndices.begin() + sampleIndex;
253 
254  CopyInput(inputHostBuffer, sampleIndexIterator, fBatchSize);
255  CopyOutput(outputHostBuffer, sampleIndexIterator, fBatchSize);
256  CopyWeights(weightHostBuffer, sampleIndexIterator, fBatchSize);
257 
258  deviceBuffer.CopyFrom(hostBuffer);
259  Matrix_t inputMatrix(inputDeviceBuffer, fBatchSize, fNInputFeatures);
260  Matrix_t outputMatrix(outputDeviceBuffer, fBatchSize, fNOutputFeatures);
261  Matrix_t weightMatrix(weightDeviceBuffer, fBatchSize, fNOutputFeatures);
262 
263  fBatchIndex++;
264  return TBatch<AArchitecture>(inputMatrix, outputMatrix, weightMatrix);
265 }
266 
267 //______________________________________________________________________________
268 template<typename Data_t, typename AArchitecture>
270 {
271  std::shuffle(fSampleIndices.begin(), fSampleIndices.end(), std::default_random_engine{});
272 }
273 
274 } // namespace DNN
275 } // namespace TMVA
276 
277 #endif
TBatch< AArchitecture > operator*()
Definition: DataLoader.h:105
Matrix_t & GetInput()
Return the matrix representing the input data.
Definition: DataLoader.h:72
Matrix_t fOutputMatrix
Definition: DataLoader.h:61
void CopyOutput(HostBuffer_t &buffer, IndexIterator_t begin, size_t batchSize)
Copy output matrix into the given host buffer.
TBatch< AArchitecture > GetBatch()
Return the next batch from the training set.
Definition: DataLoader.h:228
const Data_t & fData
Definition: DataLoader.h:137
typename std::vector< size_t >::iterator IndexIterator_t
Definition: DataLoader.h:42
void CopyInput(HostBuffer_t &buffer, IndexIterator_t begin, size_t batchSize)
Copy input matrix into the given host buffer.
size_t fNStreams
Number of buffer pairs.
Definition: DataLoader.h:145
bool operator!=(const TBatchIterator &other)
Definition: DataLoader.h:107
std::tuple< const TMatrixT< Double_t > &, const TMatrixT< Double_t > &, const TMatrixT< Double_t > & > MatrixInput_t
Definition: DataLoader.h:38
TBatch(Matrix_t &, Matrix_t &, Matrix_t &)
Definition: DataLoader.h:192
TDataLoader< Data_t, AArchitecture > & fDataLoader
Definition: DataLoader.h:94
typename AArchitecture::Matrix_t Matrix_t
Definition: DataLoader.h:134
Matrix_t fWeightMatrix
Definition: DataLoader.h:62
TBatchIterator operator++()
Definition: DataLoader.h:106
BatchIterator_t begin()
Definition: DataLoader.h:170
TBatchIterator(TDataLoader< Data_t, AArchitecture > &dataLoader, size_t index=0)
Definition: DataLoader.h:99
typename AArchitecture::DeviceBuffer_t DeviceBuffer_t
Definition: DataLoader.h:133
Class that contains all the data information.
Definition: DataSetInfo.h:60
Matrix_t fInputMatrix
Definition: DataLoader.h:60
typename AArchitecture::Matrix_t Matrix_t
Definition: DataLoader.h:58
typename AArchitecture::HostBuffer_t HostBuffer_t
Definition: DataLoader.h:132
void Shuffle()
Shuffle the order of the samples in the batch.
Definition: DataLoader.h:269
TDataLoader.
Definition: DataLoader.h:79
TBatch & operator=(const TBatch &)=default
TDataLoader(const Data_t &data, size_t nSamples, size_t batchSize, size_t nInputFeatures, size_t nOutputFeatures, size_t nStreams=1)
Definition: DataLoader.h:202
std::tuple< const std::vector< Event * > &, const DataSetInfo & > TMVAInput_t
Definition: DataLoader.h:40
std::vector< size_t > fSampleIndices
Ordering of the samples in the epoch.
Definition: DataLoader.h:149
Abstract ClassifierFactory template that handles arbitrary types.
std::vector< DeviceBuffer_t > fDeviceBuffers
Definition: DataLoader.h:146
std::vector< HostBuffer_t > fHostBuffers
Definition: DataLoader.h:147
Matrix_t & GetOutput()
Return the matrix representing the output data.
Definition: DataLoader.h:74
BatchIterator_t end()
Definition: DataLoader.h:171
TBatchIterator.
Definition: DataLoader.h:90
void CopyWeights(HostBuffer_t &buffer, IndexIterator_t begin, size_t batchSize)
Copy weight matrix into the given host buffer.
Matrix_t & GetWeights()
Return the matrix holding the event weights.
Definition: DataLoader.h:76