Loading...
Searching...
No Matches
optimizer.h
Go to the documentation of this file.
1// SPDX-License-Identifier: AGPL-3.0-only
2// Copyright (C) 2026 Artificial Intelligence Techniques, S.L. and Roberto López González
3
4#pragma once
5
6#include <array>
7#include <functional>
11#include "opennn/core/json.h"
17
18namespace opennn
19{
20
21inline constexpr float GRADIENT_NORM_EPS = 1e-6f;
22
23class Network;
24struct Buffer;
25struct BackPropagation;
26
28{
29 void set(const vector<Shape>&, Device device = Device::CPU);
30 void set(const vector<Shape>&, const vector<Type>& slot_types, Device device = Device::CPU);
31
33 vector<TensorView> views;
34};
35
37{
38
39public:
40
41 explicit Optimizer(Loss* = nullptr);
42 virtual ~Optimizer();
43
45
46 const Loss* get_loss() const noexcept { return loss; }
47
48 bool get_display() const noexcept { return display; }
49
50 void set(Loss* new_loss) { loss = new_loss; }
51
52 virtual void set_display(bool new_display) { display = new_display; }
53
54 void set_display_period(const Index new_display_period)
55 {
56 throw_if(new_display_period <= 0, "Optimizer::set_display_period: period must be positive.");
57 display_period = new_display_period;
58 }
59
60 void set_workers_number(int new_workers_number) { workers_number = max(1, new_workers_number); }
61
62 void set_cuda_graph(bool enabled) { use_cuda_graph = enabled; }
63
65
66 void set_shuffle(bool enabled) { shuffle_samples = enabled; }
67
69
70 void set_maximum_epochs(const Index new_maximum_epochs) { maximum_epochs = new_maximum_epochs; }
71 Index get_maximum_epochs() const noexcept { return maximum_epochs; }
72 void set_maximum_time(const float new_maximum_time) { maximum_time = new_maximum_time; }
73
74 void set_loss_goal(const float new_loss_goal) { training_loss_goal = new_loss_goal; }
75 void set_maximum_validation_failures(const Index new_maximum_validation_failures) { maximum_validation_failures = new_maximum_validation_failures; }
76 void set_validation_period(const Index n)
77 {
78 throw_if(n <= 0, "Optimizer::set_validation_period: period must be positive.");
80 }
81
82 void set_restore_best(bool enabled) { restore_best = enabled; }
83
84 void set_gradient_clip_norm(const float new_clip) { gradient_clip_norm = new_clip; }
85
86 void set_joint_gradient_arena(bool enabled) noexcept
87 {
88 joint_gradient_arena = enabled;
89 }
90
91 Index get_batch_size() const noexcept { return batch_size; }
92 void set_batch_size(const Index new_batch_size) { batch_size = new_batch_size; }
93
95
97
99
100 const string& get_name() const noexcept { return name; }
101
102 virtual void from_JSON(const JsonDocument&);
103
104 virtual void to_JSON(JsonWriter&) const;
105
106 void save(const filesystem::path&) const;
107 void load(const filesystem::path&);
108
109 function<void(Index, float, float, Network*)> post_epoch_callback;
110 function<void(Network*)> post_batch_callback;
111 function<void(Index, float)> post_best_callback;
112
113protected:
114
116
118 {
119 static constexpr int group_size = 8;
120 static constexpr int slots_count = 2 * group_size;
121 static constexpr int pipelines_count = 2;
122
130
131 Batch* fixed_batch() const { return pipelines[0].slots[0].get(); }
132
133 bool has_graph_batches() const
134 {
135 return pipelines[0].slots[1] || pipelines[1].slots[0];
136 }
137
139 {
140 for (GraphPipeline& pipeline : pipelines)
141 pipeline.exec.reset();
143 }
144
146 {
147 unique_ptr<Batch> batch;
148 unique_ptr<TrainingContext> context;
150 Index size = 0;
151 bool capture_failed = false;
152 };
153
158 size_t throttle_cursor = 0;
160 };
161
162 void set_names();
164
165 // Training always runs at least one epoch, even when the limit is zero.
166 Index get_epoch_budget() const noexcept { return max<Index>(maximum_epochs, 1); }
167
169 {
171 float seconds = 0.0f;
172 float training_error = 0.0f;
173 float loss = 0.0f;
174 optional<float> loss_decrease;
176 };
177
178 optional<StoppingCondition> find_stopping_condition(const EpochReport&,
179 float minimum_loss_decrease = -MAX) const;
180
181 void close_training_result(TrainingResult&, const EpochReport&, bool has_validation) const;
182
184 {
186 Index epoch = -1;
187 vector<float> parameters;
188 vector<float> states;
189 };
190
192 float,
193 Index,
194 Index&,
196
199 const BestModelSnapshot&);
200
202 void read_common_json(const Json*);
203
206
209 const vector<vector<Index>>&,
210 const FeatureSelection&,
213 ForwardPropagation* validation_forward_propagation = nullptr,
214 ThreadSafeQueue<Batch*>* validation_empty_queue = nullptr,
215 const vector<vector<Index>>* validation_batches = nullptr);
216
218
219 void sync_device(bool on_gpu, bool has_recurrent_layers, TrainingSession&);
220
222
223 bool should_display(Index epoch) const noexcept { return display && epoch % display_period == 0; }
224
225 void display_epoch_results(Index epoch, float training_error, float training_accuracy,
226 float validation_error, float validation_accuracy,
227 bool has_validation, bool validation_fresh, bool is_token_cross_entropy,
228 float elapsed_time) const;
229
231 Dataset& dataset,
232 Network& network,
233 Index training_batch_size,
234 Index validation_batch_size,
235 bool has_validation,
236 TrainingSession& training_session);
237
238 struct WorkerProfileCounters;
239 struct GraphEpochContext;
240 struct TrainingEpochContext;
241
242 unique_ptr<BatchPrefetchSession> start_batch_prefetch(
244 const vector<vector<Index>>&,
245 const FeatureSelection&,
246 FillMode,
247 WorkerProfileCounters* profile_counters = nullptr);
248
249 int get_batch_pool_size(const Network&) const;
250
251 struct EpochLoopContext;
253
255 {
256 Network* network = nullptr;
259 unique_ptr<Batch> training_batch;
260 unique_ptr<Batch> validation_batch;
261 unique_ptr<ForwardPropagation> training_forward_propagation;
262 unique_ptr<ForwardPropagation> validation_forward_propagation;
263 };
264
266 {
267 float training_error = 0.0f;
268 float displayed_error = 0.0f;
269 float loss = 0.0f;
270 };
271
273 {
274 function<void()> setup_state;
276 function<float()> validation_error;
277 function<void()> display_extra;
278 function<void()> post_step;
280 };
281
284
285 virtual string get_display_name() const { return name; }
286 virtual void setup_optimizer_data(OptimizerData&, Index, Device) {}
289 {
290 throw runtime_error("train() requires a mini-batch optimizer (SGD or Adam).");
291 }
292
293 virtual bool supports_cuda_graph() const noexcept { return false; }
294
296
298 {
299 return use_cuda_graph
302 && loss
303 && loss->supports_device_epoch_metrics()
305 }
306 virtual void on_epoch_begin(Index, OptimizerData&) {}
307
308 bool uses_joint_gradient_arena() const noexcept;
309
315 const vector<vector<Index>>&,
316 const FeatureSelection&);
317
318 Loss::EvaluationResult train_epoch(TrainingContext&,
320 const vector<vector<Index>>&,
321 const FeatureSelection&,
324
327 const vector<vector<Index>>&,
328 const FeatureSelection&,
330
331 Loss* loss = nullptr;
332
333 float training_loss_goal = 0.0f;
334
335 Index maximum_validation_failures = numeric_limits<Index>::max();
337
338 float gradient_clip_norm = 0.0f;
339
341
342 bool restore_best = true;
343
344 Index maximum_epochs = 10000;
345
346 Index batch_size = 0;
347
348 float maximum_time = 360000.0f;
349
350 Index display_period = 10;
351
352 bool display = true;
353
354 bool shuffle_samples = true;
355
357
358 // How many threads prepare batches ahead of the device. Two was a bare
359 // literal that nothing outside the tests ever changed, so it is measured
360 // here rather than left to look arbitrary: on the CNN family, whose fill
361 // decodes and resizes an image per sample and is the most expensive one in
362 // the suite, six workers were slower than two in every run and in both
363 // orders -- medians 378 against 406 samples/s, 7% down. The fills are not
364 // waiting on anything the extra threads could overlap with, so the workers
365 // only take the cores the main thread wants.
366 //
367 // OPENNN_BATCH_WORKERS overrides it, which is how the above was run. The
368 // batch pool sizes itself from this, so raising it widens the queue too.
369 static const int default_workers_number;
370
372
373 bool use_cuda_graph = false;
375
376 string name;
377};
378
379unique_ptr<Optimizer> create_optimizer(const string& name);
380
381}
Definition dataset.h:48
Definition json.h:75
Definition json.h:92
Definition json.h:24
Definition loss.h:19
Definition network.h:87
Definition optimizer.h:37
float training_loss_goal
Definition optimizer.h:333
opennn::StoppingCondition StoppingCondition
Definition optimizer.h:44
Loss::EvaluationResult run_epoch_loop(EpochLoopContext &)
Index get_maximum_batch_size() const
void prefetch_batch(Batch &)
bool can_use_cuda_graph() const
Definition optimizer.h:297
UpdateMode
Definition optimizer.h:115
@ Capturable
Definition optimizer.h:115
@ Standard
Definition optimizer.h:115
virtual void from_JSON(const JsonDocument &)
void set_maximum_time(const float new_maximum_time)
Definition optimizer.h:72
void set_validation_period(const Index n)
Definition optimizer.h:76
int get_batch_pool_size(const Network &) const
virtual void on_epoch_begin(Index, OptimizerData &)
Definition optimizer.h:306
void prepare_training_artifacts()
void setup_device_training()
virtual ~Optimizer()
bool cuda_graph_capture_failed
Definition optimizer.h:374
const string & get_name() const noexcept
Definition optimizer.h:100
void sync_device(bool on_gpu, bool has_recurrent_layers, TrainingSession &)
virtual void update_parameters(BackPropagation &, OptimizerData &, UpdateMode=UpdateMode::Standard)
Definition optimizer.h:287
void prepare_full_batch_training(FullBatchContext &, const char *banner)
void save(const filesystem::path &) const
bool network_has_active_dropout() const
void read_common_json(const Json *)
unique_ptr< BatchPrefetchSession > start_batch_prefetch(ThreadSafeQueue< Batch * > &, const vector< vector< Index > > &, const FeatureSelection &, FillMode, WorkerProfileCounters *profile_counters=nullptr)
optional< StoppingCondition > find_stopping_condition(const EpochReport &, float minimum_loss_decrease=-MAX) const
Loss::EvaluationResult evaluate_epoch(ForwardPropagation &, ThreadSafeQueue< Batch * > &, const vector< vector< Index > > &, const FeatureSelection &, TrainingSession &)
Loss * loss
Definition optimizer.h:331
Index get_batch_size() const noexcept
Definition optimizer.h:91
void set_shuffle(bool enabled)
Definition optimizer.h:66
bool display
Definition optimizer.h:352
void teardown_device_training()
void set_display_period(const Index new_display_period)
Definition optimizer.h:54
void display_epoch_results(Index epoch, float training_error, float training_accuracy, float validation_error, float validation_accuracy, bool has_validation, bool validation_fresh, bool is_token_cross_entropy, float elapsed_time) const
Index display_period
Definition optimizer.h:350
void close_training_result(TrainingResult &, const EpochReport &, bool has_validation) const
bool shuffle_samples
Definition optimizer.h:354
Index maximum_validation_failures
Definition optimizer.h:335
static const int default_workers_number
Definition optimizer.h:369
void set_batch_size(const Index new_batch_size)
Definition optimizer.h:92
void set_batch_pool_size(int size)
Definition optimizer.h:68
void set_cuda_graph(bool enabled)
Definition optimizer.h:62
bool uses_joint_gradient_arena() const noexcept
void update_best_parameters(Network *, float, Index, Index &, BestModelSnapshot &)
void restore_best_parameters(Network *, TrainingResult &, const BestModelSnapshot &)
virtual void configure_for_task(NetworkTask)
virtual string get_display_name() const
Definition optimizer.h:285
const Loss * get_loss() const noexcept
Definition optimizer.h:46
Optimizer(Loss *=nullptr)
Index get_epoch_budget() const noexcept
Definition optimizer.h:166
virtual bool supports_cuda_graph() const noexcept
Definition optimizer.h:293
void set_loss_goal(const float new_loss_goal)
Definition optimizer.h:74
bool use_cuda_graph
Definition optimizer.h:373
void set_maximum_epochs(const Index new_maximum_epochs)
Definition optimizer.h:70
void set_gradient_clip_norm(const float new_clip)
Definition optimizer.h:84
void set_workers_number(int new_workers_number)
Definition optimizer.h:60
function< void(Network *)> post_batch_callback
Definition optimizer.h:110
string name
Definition optimizer.h:376
virtual void setup_optimizer_data(OptimizerData &, Index, Device)
Definition optimizer.h:286
bool should_display(Index epoch) const noexcept
Definition optimizer.h:223
virtual void to_JSON(JsonWriter &) const
Loss::EvaluationResult run_graph_epoch(TrainingSession &, OptimizerData &, ForwardPropagation &, BackPropagation &, ThreadSafeQueue< Batch * > &, const vector< vector< Index > > &, const FeatureSelection &)
void warmup_device_training(TrainingContext &, ThreadSafeQueue< Batch * > &, const vector< vector< Index > > &, const FeatureSelection &, TrainingSession &, OptimizerData &, ForwardPropagation *validation_forward_propagation=nullptr, ThreadSafeQueue< Batch * > *validation_empty_queue=nullptr, const vector< vector< Index > > *validation_batches=nullptr)
void write_common_json(JsonWriter &) const
void set_joint_gradient_arena(bool enabled) noexcept
Definition optimizer.h:86
int workers_number
Definition optimizer.h:371
bool get_display() const noexcept
Definition optimizer.h:48
Index validation_period
Definition optimizer.h:336
Index get_maximum_epochs() const noexcept
Definition optimizer.h:71
int batch_pool_size_override
Definition optimizer.h:356
Index maximum_epochs
Definition optimizer.h:344
void load(const filesystem::path &)
bool get_cuda_graph_capture_failed() const noexcept
Definition optimizer.h:64
bool restore_best
Definition optimizer.h:342
function< void(Index, float)> post_best_callback
Definition optimizer.h:111
Loss::EvaluationResult train_epoch(TrainingContext &, ThreadSafeQueue< Batch * > &, const vector< vector< Index > > &, const FeatureSelection &, TrainingSession &, OptimizerData &)
float maximum_time
Definition optimizer.h:348
TrainingResult train_full_batch(FullBatchContext &, const FullBatchHooks &)
function< void(Index, float, float, Network *)> post_epoch_callback
Definition optimizer.h:109
void set_maximum_validation_failures(const Index new_maximum_validation_failures)
Definition optimizer.h:75
bool joint_gradient_arena
Definition optimizer.h:340
void set(Loss *new_loss)
Definition optimizer.h:50
float gradient_clip_norm
Definition optimizer.h:338
virtual TrainingResult train()
Index batch_size
Definition optimizer.h:346
void setup_batch_pools(BatchPools &pools, Dataset &dataset, Network &network, Index training_batch_size, Index validation_batch_size, bool has_validation, TrainingSession &training_session)
static void clip_gradient_norm(BackPropagation &, float)
virtual void set_display(bool new_display)
Definition optimizer.h:52
void set_restore_best(bool enabled)
Definition optimizer.h:82
Definition thread_safe_queue.h:16
Definition device_backend.h:298
Definition energy_meter.h:7
unique_ptr< remove_pointer_t< DeviceGraphExec >, GraphExecDeleter > GraphExecHandle
Definition device_backend.h:326
constexpr bool is_cuda_build() noexcept
Definition device_backend.h:72
Definition configuration.h:10
FillMode
Definition batch.h:20
constexpr float MAX
Definition opennn_types.h:309
StoppingCondition
Definition training_result.h:13
NetworkTask
Definition network.h:74
Device
Definition configuration.h:12
@ CPU
Definition configuration.h:12
@ CUDA
Definition configuration.h:12
Eigen::array< T, N > array
Definition tensor_types.h:736
unique_ptr< Optimizer > create_optimizer(const string &name)
constexpr float GRADIENT_NORM_EPS
Definition optimizer.h:21
#define throw_if(condition,...)
Definition opennn_types.h:243
Definition back_propagation.h:19
Definition batch.h:132
Definition batch.h:60
Definition tensor_types.h:340
Definition batch.h:24
Definition forward_propagation.h:52
Definition loss.h:94
Definition optimizer.h:28
void set(const vector< Shape > &, const vector< Type > &slot_types, Device device=Device::CPU)
Buffer data
Definition optimizer.h:32
vector< TensorView > views
Definition optimizer.h:33
void set(const vector< Shape > &, Device device=Device::CPU)
Definition optimizer.h:184
float validation_error
Definition optimizer.h:185
vector< float > parameters
Definition optimizer.h:187
Index epoch
Definition optimizer.h:186
vector< float > states
Definition optimizer.h:188
Definition optimizer.h:169
float loss
Definition optimizer.h:173
float seconds
Definition optimizer.h:171
Index completed_epochs
Definition optimizer.h:170
Index validation_failures
Definition optimizer.h:175
optional< float > loss_decrease
Definition optimizer.h:174
float training_error
Definition optimizer.h:172
Definition optimizer.h:255
Network * network
Definition optimizer.h:256
Index training_samples_number
Definition optimizer.h:257
unique_ptr< ForwardPropagation > validation_forward_propagation
Definition optimizer.h:262
Index validation_samples_number
Definition optimizer.h:258
unique_ptr< Batch > validation_batch
Definition optimizer.h:260
unique_ptr< Batch > training_batch
Definition optimizer.h:259
unique_ptr< ForwardPropagation > training_forward_propagation
Definition optimizer.h:261
Definition optimizer.h:273
function< void()> display_extra
Definition optimizer.h:277
float minimum_loss_decrease
Definition optimizer.h:279
function< void()> setup_state
Definition optimizer.h:274
function< void()> post_step
Definition optimizer.h:278
function< FullBatchStep()> train_step
Definition optimizer.h:275
function< float()> validation_error
Definition optimizer.h:276
Definition optimizer.h:266
float loss
Definition optimizer.h:269
float training_error
Definition optimizer.h:267
float displayed_error
Definition optimizer.h:268
device::GraphExecHandle exec
Definition optimizer.h:126
array< device::CudaEvent, group_size > copy_done_events
Definition optimizer.h:128
device::CudaEvent fork_event
Definition optimizer.h:127
array< unique_ptr< Batch >, group_size > slots
Definition optimizer.h:125
unique_ptr< Batch > batch
Definition optimizer.h:147
unique_ptr< TrainingContext > context
Definition optimizer.h:148
device::GraphExecHandle exec
Definition optimizer.h:149
Index size
Definition optimizer.h:150
bool capture_failed
Definition optimizer.h:151
Definition optimizer.h:118
array< GraphPipeline, pipelines_count > pipelines
Definition optimizer.h:154
bool has_graph_batches() const
Definition optimizer.h:133
bool cuda_graph_capture_allowed
Definition optimizer.h:159
Buffer device_metrics
Definition optimizer.h:156
static constexpr int pipelines_count
Definition optimizer.h:121
array< device::CudaEvent, 4 > throttle_events
Definition optimizer.h:157
TailContext tail
Definition optimizer.h:155
static constexpr int group_size
Definition optimizer.h:119
size_t throttle_cursor
Definition optimizer.h:158
Batch * fixed_batch() const
Definition optimizer.h:131
static constexpr int slots_count
Definition optimizer.h:120
void disable_cuda_graph_capture()
Definition optimizer.h:138
Definition training_context.h:15
Definition training_result.h:20