This repository was archived by the owner on Jul 17, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 292
Expand file tree
/
Copy pathDataLoaders.h
More file actions
243 lines (210 loc) · 10.1 KB
/
Copy pathDataLoaders.h
File metadata and controls
243 lines (210 loc) · 10.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Project: Embedded Learning Library (ELL)
// File: DataLoaders.h (common)
// Authors: Ofer Dekel
//
////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "DataLoadArguments.h"
#include <data/include/Dataset.h>
#include <data/include/ExampleIterator.h>
#include <model/include/Map.h>
#include <utilities/include/StringUtil.h>
#include <istream>
#include <string>
namespace ell
{
namespace common
{
/// <summary> Gets an ExampleIterator from an input stream. </summary>
///
/// <typeparam name="TextLineIteratorType"> Line iterator type. </typeparam>
/// <typeparam name="MetadataParserType"> Metadata parser type. </typeparam>
/// <typeparam name="DataVectorParserType"> DataVector parser type. </typeparam>
/// <param name="stream"> Input stream to load data from. </param>
///
/// <returns> The data iterator. </returns>
template <typename TextLineIteratorType, typename MetadataParserType, typename DataVectorParserType>
auto GetExampleIterator(std::istream& stream);
/// <summary> Gets an AutoSupervisedExampleIterator iterator from an input stream. </summary>
///
/// <param name="stream"> Input stream to load data from. </param>
///
/// <returns> The data iterator. </returns>
data::AutoSupervisedExampleIterator GetAutoSupervisedExampleIterator(std::istream& stream);
/// <summary> Gets an AutoSupervisedMultiClassExampleIterator iterator from an input stream. </summary>
///
/// <param name="stream"> Input stream to load data from. </param>
///
/// <returns> The data iterator. </returns>
data::AutoSupervisedMultiClassExampleIterator GetAutoSupervisedMultiClassExampleIterator(std::istream& stream);
/// <summary> Gets an AutoSupervisedDataset dataset from data load arguments. </summary>
///
/// <param name="stream"> Input stream to load data from. </param>
///
/// <returns> The dataset. </returns>
data::AutoSupervisedDataset GetDataset(std::istream& stream);
/// <summary> Gets a dataset from data load arguments. </summary>
///
/// <param name="stream"> Input stream to load data from. </param>
///
/// <returns> The dataset. </returns>
data::AutoSupervisedMultiClassDataset GetMultiClassDataset(std::istream& stream);
/// <summary>
/// Gets a new dataset by running an existing dataset through a map.
/// </summary>
///
/// <typeparam name="ExampleType"> Example type. </typeparam>
/// <typeparam name="MapType"> Map type. </typeparam>
/// <param name="input"> Input dataset. </param>
/// <param name="map"> Map to run input dataset on. </param>
///
/// <returns> The transformed dataset. </returns>
template <typename ExampleType, typename MapType>
auto TransformDataset(data::Dataset<ExampleType>& input, const MapType& map);
/// <summary>
/// The map is first compiled, then a new dataset is returned
/// by running an existing dataset through the compiled map.
/// </summary>
///
/// <typeparam name="ExampleType"> Example type. </typeparam>
/// <typeparam name="MapType"> Map type. </typeparam>
/// <param name="input"> Input dataset. </param>
/// <param name="map"> Map to run input dataset on. </param>
/// <param name="useBlas"> Use BLAS in the emitted code to speed up linear algerbra operations. </param>
///
/// <returns> The transformed dataset. </returns>
template <typename ExampleType, typename MapType>
auto TransformDatasetWithCompiledMap(data::Dataset<ExampleType>& input, const MapType& map, bool useBlas = true);
} // namespace common
} // namespace ell
#pragma region implementation
#include <data/include/SingleLineParsingExampleIterator.h>
#include <model/include/IRCompiledMap.h>
#include <model/include/IRMapCompiler.h>
#include <nodes/include/ClockNode.h> // for nodes::TimeTickType
namespace ell
{
namespace common
{
template <typename TextLineIteratorType, typename MetadataParserType, typename DataVectorParserType>
auto GetExampleIterator(std::istream& stream)
{
TextLineIteratorType textLineIterator(stream);
MetadataParserType metadataParser;
DataVectorParserType dataVectorParser;
return data::MakeSingleLineParsingExampleIterator(std::move(textLineIterator), std::move(metadataParser), std::move(dataVectorParser));
}
template <typename ExampleType, typename MapType>
auto TransformDataset(data::Dataset<ExampleType>& input, MapType& map)
{
return input.template Transform<ExampleType>([&map](const ExampleType& example) {
auto transformedDataVector = map.template Compute<data::DoubleDataVector>(example.GetDataVector());
return ExampleType(std::move(transformedDataVector), example.GetMetadata());
});
}
namespace detail
{
// Context used by callback functions
struct CallbackContext
{
std::vector<double> inputValues;
};
} // namespace detail
// C functions called by compiled maps
extern "C" {
inline bool InputCallback_Double(void* context, double* input)
{
auto dataContext = static_cast<detail::CallbackContext*>(context);
std::copy(dataContext->inputValues.begin(), dataContext->inputValues.end(), input);
return true;
}
inline bool InputCallback_Float(void* context, float* input)
{
auto dataContext = static_cast<detail::CallbackContext*>(context);
std::transform(dataContext->inputValues.begin(), dataContext->inputValues.end(), input, [](double val) { return static_cast<float>(val); });
return true;
}
}
namespace detail
{
// Sets up the function address that the LLVM jit will call for the source function callback
// Note that this only supports a single source node, but can be extended in the future
// to support multiple source nodes (e.g. by switching the function on node id).
template <typename MapType>
void ResolveInputCallback(const MapType& map, llvm::Module* module, ell::emitters::IRExecutionEngine& jitter)
{
const std::string defaultCallbackName("ELL_InputCallback");
auto callback = module->getFunction(defaultCallbackName);
ptrdiff_t callbackAddress = 0;
switch (map.GetInputType())
{
case model::Port::PortType::smallReal: {
callbackAddress = reinterpret_cast<ptrdiff_t>(&InputCallback_Float);
break;
}
case model::Port::PortType::real: {
callbackAddress = reinterpret_cast<ptrdiff_t>(&InputCallback_Double);
break;
}
default:
throw utilities::InputException(utilities::InputExceptionErrors::invalidArgument, "Unexpected source input type for model. Should be double or float.");
}
jitter.DefineFunction(callback, callbackAddress);
}
} // namespace detail
template <typename ExampleType, typename MapType>
auto TransformDatasetWithCompiledMap(data::Dataset<ExampleType>& input, const MapType& map, bool useBlas)
{
ell::model::MapCompilerOptions settings;
settings.compilerSettings.useBlas = useBlas;
ell::model::ModelOptimizerOptions optimizerOptions;
detail::CallbackContext dataContext;
model::IRMapCompiler compiler(settings, optimizerOptions);
auto module = compiler.GetModule().GetLLVMModule();
auto compiledMap = compiler.Compile(map);
compiledMap.SetContext(&dataContext);
// Unlike reference maps, compiled maps receive the current time as the parameter input and
// values through the input callback.
if (map.GetSourceNodes().size() > 0)
{
detail::ResolveInputCallback(map, module, compiledMap.GetJitter());
return input.template Transform<ExampleType>([&compiledMap, &dataContext](const ExampleType& example) {
dataContext.inputValues = example.GetDataVector().ToArray();
compiledMap.SetInputValue(0, std::vector<nodes::TimeTickType>({ 0 /*currentTime*/ }));
auto transformedDataVector = compiledMap.template ComputeOutput<typename ExampleType::DataVectorType>(0);
return ExampleType(std::move(transformedDataVector), example.GetMetadata());
});
}
else
{
auto type = map.GetInputType();
switch (type)
{
case model::Port::PortType::smallReal: {
return input.template Transform<ExampleType>([&compiledMap](const ExampleType& example) {
auto data = example.GetDataVector().ToArray();
std::vector<float> smallData(data.size());
std::transform(data.begin(), data.end(), smallData.begin(), [](double val) { return static_cast<float>(val); });
compiledMap.SetInputValue(0, smallData);
auto transformedDataVector = compiledMap.template ComputeOutput<typename ExampleType::DataVectorType>(0);
return ExampleType(std::move(transformedDataVector), example.GetMetadata());
});
}
case model::Port::PortType::real: {
return input.template Transform<ExampleType>([&compiledMap](const ExampleType& example) {
compiledMap.SetInputValue(0, example.GetDataVector().ToArray());
auto transformedDataVector = compiledMap.template ComputeOutput<typename ExampleType::DataVectorType>(0);
return ExampleType(std::move(transformedDataVector), example.GetMetadata());
});
}
default:
throw utilities::InputException(utilities::InputExceptionErrors::typeMismatch,
utilities::FormatString("Unexpected input type %d, expecting float or double", type));
}
}
}
} // namespace common
} // namespace ell
#pragma endregion implementation