Loading...
Searching...
No Matches
layer.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
11
12#include <ranges>
13#include <utility>
14
15namespace opennn
16{
17
19enum class BatchNormalization { No, Yes };
21enum class LayerType;
22
23inline void check_rank(const Shape& shape, initializer_list<int> allowed,
24 const char* layer, const char* what)
25{
26 if (shape.empty()) return;
27 if (ranges::any_of(allowed, [&](int r){ return int(shape.get_rank()) == r; })) return;
28
29 string allowed_str;
30 for (int r : allowed)
31 allowed_str += format("{}{}", allowed_str.empty() ? "" : "/", r);
32
33 throw runtime_error(format("{} layer supports {} rank {} (got {}).",
34 layer, what, allowed_str, shape.get_rank()));
35}
36
37class Layer
38{
39
40public:
41
43 {
44 const Layer* source = nullptr;
45 size_t spec_index = 0;
47 };
48
49 virtual ~Layer() = default;
50
51 const string& get_label() const noexcept { return label; }
52
53 const string& get_name() const;
54
55 LayerType get_type() const noexcept { return layer_type; }
56
57 virtual bool accepts_input_rank(Index) const { return false; }
58
59 void set_input_shape(const Shape& new_input_shape)
60 {
61 throw_if(!new_input_shape.empty() && !accepts_input_rank(new_input_shape.get_rank()),
62 "{} layer does not accept an input of rank {}.",
63 get_name(), new_input_shape.get_rank());
64
65 apply_input_shape(new_input_shape);
66 }
67
68 virtual void set_output_shape(const Shape&) {}
69
70 void set_label(string new_label) { label = std::move(new_label); }
71
72 Index get_parameters_number() const;
73 const vector<Operator*>& get_operators() const noexcept { return operators; }
74 virtual vector<TensorSpec> get_parameter_specs() const;
75 virtual vector<TensorSpec> get_state_specs() const;
76 virtual vector<TensorSpec> get_forward_specs(Index batch_size) const
77 {
78 return {{Shape{batch_size}.append(get_output_shape()), compute_dtype}};
79 }
80 virtual vector<TensorSpec> get_backward_specs(Index batch_size) const
81 {
82 if (!is_trainable) return {};
83 return {{Shape{batch_size}.append(get_input_shape()), compute_dtype}};
84 }
85
87 {
89 }
90 // A slot the inference pass provably never writes, so the arena need not
91 // hold it. Distinct from TrainingOnly, which is a property of the slot
92 // alone: this one depends on which kernel inference will actually dispatch
93 // to, and that follows from the device the activations live on. The layer
94 // answers for its own fused paths; the default keeps every slot.
95 virtual bool is_forward_slot_inference_elidable(size_t, Device) const noexcept
96 {
97 return false;
98 }
99 virtual size_t get_recomputable_forward_slot() const noexcept { return SIZE_MAX; }
101 virtual bool backward_uses_forward_output() const noexcept { return true; }
102 virtual bool backward_uses_input(size_t) const noexcept { return true; }
103 virtual bool preserves_output_delta_during_backward() const noexcept { return false; }
104 virtual bool allows_input_delta_alias() const noexcept { return false; }
105
106 virtual bool folds_input_delta_addend(size_t) const noexcept { return false; }
107
108 virtual Shape get_input_shape() const noexcept { return input_shape; }
109
110 virtual Shape get_output_shape() const = 0;
111
113
114 virtual Index get_sources_number() const noexcept { return 1; }
115
116 virtual bool allows_successors() const noexcept { return true; }
117 virtual bool is_recurrent() const noexcept { return false; }
118 virtual bool skip_for_pre_scaled_input() const noexcept { return false; }
119 virtual bool uses_sequence_position() const noexcept { return false; }
120
121 virtual bool allows_bf16_input_cast(size_t) const noexcept { return true; }
122
123 Index get_inputs_number() const noexcept { return get_input_shape().size(); }
124
125 Index get_outputs_number() const { return get_output_shape().size(); }
126
127 virtual void forward_propagate(ForwardPropagation& forward_propagation, size_t layer, ForwardPropagationMode pass)
128 {
129 for (Operator* op : get_operators())
130 op->forward_propagate(forward_propagation, layer, pass);
131 }
132
133 virtual void back_propagate(ForwardPropagation& forward_propagation, BackPropagation& back_propagation, size_t i) const
134 {
135 for (Operator* op : views::reverse(get_operators()))
136 op->back_propagate(forward_propagation, back_propagation, i);
137 }
138
139 virtual void from_JSON(const JsonDocument&);
140
141 virtual void read_JSON_body(const Json*) {}
142
143 virtual void on_loaded() {}
144
145 virtual void load_state_from_JSON(const JsonDocument&);
146
147 virtual void to_JSON(JsonWriter&) const;
148
149 virtual void write_JSON_body(JsonWriter&) const {}
150
151 virtual string write_expression(const vector<string>& ,
152 const vector<string>& ) const { return {}; }
153
154 bool get_is_trainable() const noexcept { return is_trainable; }
155 void set_is_trainable(bool trainable) { is_trainable = trainable; }
156
157 Type get_compute_dtype() const noexcept { return compute_dtype; }
158 Device get_compute_device() const noexcept { return compute_device; }
159
160 void set_compute_dtype(Type new_compute_dtype)
161 {
162 weights_dtype = new_compute_dtype;
163 compute_dtype = activation_dtype(new_compute_dtype);
165
166 for (Operator* op : operators)
167 op->set_weights_dtype(weights_dtype);
168 }
169
170 void set_compute_device(Device new_compute_device) { compute_device = new_compute_device; }
171
172 virtual void on_compute_dtype_changed() {}
173
174 virtual float* link_states(float*, Device);
175
176 float* link_gradients(float*, Device);
177
178 vector<TensorView>& get_parameter_views() { return parameters; }
179 const vector<TensorView>& get_parameter_views() const noexcept { return parameters; }
180
181 vector<TensorView>& get_parameter_scales() { return parameter_scales; }
182 const vector<TensorView>& get_parameter_scales() const noexcept { return parameter_scales; }
183
184 vector<Operator::SlotQuantization> get_parameter_quantization() const;
185
186 virtual TiedWeight get_tied_weight() const { return {}; }
187 virtual void set_tied_weight(const TiedWeight& tied_weight)
188 {
189 throw_if(tied_weight.source,
190 "{} layer does not support tied weights.", get_name());
191 }
192
194
195private:
196
197 const LayerType layer_type;
198
199protected:
200
201 virtual void apply_input_shape(const Shape& new_input_shape)
202 {
203 input_shape = new_input_shape;
204 }
205
206 static bool refresh_feature_storage(Buffer& storage, bool& dirty, Device device,
207 Index features, Index columns,
208 const function<void(float*)>& fill);
209
211 : layer_type(type), is_trainable(trainability == Trainability::Trainable) {}
212
214
215 string label = "my_layer";
216
217 bool is_trainable = true;
218
220
224
225 vector<TensorView> parameters;
226 vector<TensorView> parameter_scales;
227 vector<TensorView> states;
228
229 vector<Operator*> operators;
230
232 vector<TensorView>&, float*,
233 vector<TensorSpec> (Operator::*specs_fn)() const,
234 void (Operator::*link_fn)(span<const TensorView>),
235 Device);
236
237};
238
239}
Definition json.h:75
Definition json.h:92
Definition json.h:24
LayerType get_type() const noexcept
Definition layer.h:55
Index get_parameters_number() const
Type compute_dtype
Definition layer.h:221
virtual void apply_input_shape(const Shape &new_input_shape)
Definition layer.h:201
bool get_is_trainable() const noexcept
Definition layer.h:154
vector< Operator * > operators
Definition layer.h:229
virtual bool allows_input_delta_alias() const noexcept
Definition layer.h:104
virtual bool is_recurrent() const noexcept
Definition layer.h:117
void set_input_shape(const Shape &new_input_shape)
Definition layer.h:59
virtual void read_JSON_body(const Json *)
Definition layer.h:141
Index get_inputs_number() const noexcept
Definition layer.h:123
vector< TensorView > parameters
Definition layer.h:225
const vector< TensorView > & get_parameter_scales() const noexcept
Definition layer.h:182
virtual bool is_forward_slot_inference_elidable(size_t, Device) const noexcept
Definition layer.h:95
virtual size_t get_recomputable_forward_slot() const noexcept
Definition layer.h:99
virtual bool uses_sequence_position() const noexcept
Definition layer.h:119
virtual bool backward_uses_forward_output() const noexcept
Definition layer.h:101
void set_compute_device(Device new_compute_device)
Definition layer.h:170
virtual void on_compute_dtype_changed()
Definition layer.h:172
const vector< TensorView > & get_parameter_views() const noexcept
Definition layer.h:179
vector< TensorView > states
Definition layer.h:227
virtual Index get_sources_number() const noexcept
Definition layer.h:114
virtual Shape get_input_shape() const noexcept
Definition layer.h:108
virtual bool accepts_input_rank(Index) const
Definition layer.h:57
virtual string write_expression(const vector< string > &, const vector< string > &) const
Definition layer.h:151
virtual void recompute_forward_slot(ForwardPropagation &, size_t)
Definition layer.h:100
virtual TiedWeight get_tied_weight() const
Definition layer.h:186
virtual bool allows_successors() const noexcept
Definition layer.h:116
virtual vector< TensorSpec > get_state_specs() const
virtual void set_tied_weight(const TiedWeight &tied_weight)
Definition layer.h:187
virtual ~Layer()=default
virtual void on_loaded()
Definition layer.h:143
const string & get_label() const noexcept
Definition layer.h:51
static bool refresh_feature_storage(Buffer &storage, bool &dirty, Device device, Index features, Index columns, const function< void(float *)> &fill)
Type get_compute_dtype() const noexcept
Definition layer.h:157
Device get_compute_device() const noexcept
Definition layer.h:158
vector< TensorView > & get_parameter_scales()
Definition layer.h:181
Forward
Definition layer.h:213
@ Output
Definition layer.h:213
@ Input
Definition layer.h:213
virtual ForwardSlotKind get_forward_slot_kind(size_t) const
Definition layer.h:86
virtual vector< TensorSpec > get_parameter_specs() const
const vector< Operator * > & get_operators() const noexcept
Definition layer.h:73
virtual bool preserves_output_delta_during_backward() const noexcept
Definition layer.h:103
virtual bool skip_for_pre_scaled_input() const noexcept
Definition layer.h:118
string label
Definition layer.h:215
void set_compute_dtype(Type new_compute_dtype)
Definition layer.h:160
virtual void from_JSON(const JsonDocument &)
float * link_gradients(float *, Device)
bool is_trainable
Definition layer.h:217
virtual bool backward_uses_input(size_t) const noexcept
Definition layer.h:102
virtual vector< TensorSpec > get_backward_specs(Index batch_size) const
Definition layer.h:80
virtual void load_state_from_JSON(const JsonDocument &)
virtual float * link_states(float *, Device)
void set_label(string new_label)
Definition layer.h:70
virtual void write_JSON_body(JsonWriter &) const
Definition layer.h:149
vector< Operator::SlotQuantization > get_parameter_quantization() const
Layer(LayerType type, Trainability trainability=Trainability::Trainable)
Definition layer.h:210
float * link_views_to_operators(vector< TensorView > &, float *, vector< TensorSpec >(Operator::*specs_fn)() const, void(Operator::*link_fn)(span< const TensorView >), Device)
vector< TensorView > parameter_scales
Definition layer.h:226
virtual ActivationFunction get_output_activation() const
Definition layer.h:112
virtual void forward_propagate(ForwardPropagation &forward_propagation, size_t layer, ForwardPropagationMode pass)
Definition layer.h:127
virtual vector< TensorSpec > get_forward_specs(Index batch_size) const
Definition layer.h:76
Index get_outputs_number() const
Definition layer.h:125
const string & get_name() const
Device compute_device
Definition layer.h:223
virtual bool allows_bf16_input_cast(size_t) const noexcept
Definition layer.h:121
vector< TensorView > & get_parameter_views()
Definition layer.h:178
virtual bool folds_input_delta_addend(size_t) const noexcept
Definition layer.h:106
void set_is_trainable(bool trainable)
Definition layer.h:155
void redistribute_parameters_to_operators()
virtual void to_JSON(JsonWriter &) const
virtual void set_output_shape(const Shape &)
Definition layer.h:68
virtual Shape get_output_shape() const =0
virtual void back_propagate(ForwardPropagation &forward_propagation, BackPropagation &back_propagation, size_t i) const
Definition layer.h:133
Type weights_dtype
Definition layer.h:222
Shape input_shape
Definition layer.h:219
Definition energy_meter.h:7
Definition configuration.h:10
Trainability
Definition layer.h:20
@ Frozen
Definition layer.h:20
@ Trainable
Definition layer.h:20
Device
Definition configuration.h:12
@ CPU
Definition configuration.h:12
LayerType
Definition layer_registry.h:15
@ Yes
Definition tensor_operations.h:120
@ No
Definition tensor_operations.h:120
Type activation_dtype(Type type)
Definition configuration.h:55
Type
Definition configuration.h:13
@ FP32
Definition configuration.h:13
BatchNormalization
Definition layer.h:19
ForwardSlotKind
Definition layer.h:18
@ Transient
Definition layer.h:18
@ TrainingOnly
Definition layer.h:18
@ Pooled
Definition layer.h:18
ForwardPropagationMode
Definition forward_propagation.h:33
float type
Definition opennn_types.h:197
ActivationFunction
Definition configuration.h:39
@ Identity
Definition configuration.h:39
void check_rank(const Shape &shape, initializer_list< int > allowed, const char *layer, const char *what)
Definition layer.h:23
#define throw_if(condition,...)
Definition opennn_types.h:243
Definition back_propagation.h:19
Definition tensor_types.h:340
Definition forward_propagation.h:52
Definition layer.h:43
size_t source_spec_index
Definition layer.h:46
const Layer * source
Definition layer.h:44
size_t spec_index
Definition layer.h:45
Definition operator.h:28
Definition tensor_types.h:172
Index size() const
Definition tensor_types.h:221
size_t get_rank() const noexcept
Definition tensor_types.h:210
bool empty() const noexcept
Definition tensor_types.h:217
Shape & append(const Shape &other)
Definition tensor_types.h:264