Loading...
Searching...
No Matches
convolutional_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
6#include <cstdio>
11
12namespace opennn
13{
14
15class Convolutional final : public Layer
16{
17public:
18
19 Convolutional(const Shape& = {3, 3, 1},
20 const Shape& = {3, 3, 1, 1},
21 const string& = "Identity",
22 const Shape& = {1, 1},
23 const string& = "Valid",
25 const string& = "convolutional_layer");
26
27 Shape get_input_shape() const noexcept override
28 { return {convolution.input_height, convolution.input_width, input_channels}; }
29 Shape get_output_shape() const override;
30
31 Index get_output_height() const;
32 Index get_output_width() const;
33
34 Index get_kernel_height() const noexcept { return convolution.kernel_height; }
35 Index get_kernel_width() const noexcept { return convolution.kernel_width; }
36 Index get_kernel_channels() const noexcept { return convolution.kernel_channels; }
37 Index get_kernels_number() const noexcept { return convolution.kernels_number; }
38
39 Index get_row_stride() const noexcept { return convolution.row_stride; }
40 Index get_column_stride() const noexcept { return convolution.column_stride; }
41
42 Index get_padding_height() const;
43 Index get_padding_width() const;
44
45 ActivationFunction get_activation_function() const noexcept { return activation_operator.activation_function; }
46 ActivationFunction get_output_activation() const noexcept override { return activation_operator.activation_function; }
47
48 bool get_batch_normalization() const { return batch_norm.active(); }
49
50 void get_folded_parameters(vector<float>& kernel_oihw, vector<float>& bias) const;
51
52 bool get_residual() const noexcept { return residual; }
53 Index get_sources_number() const noexcept override { return residual ? 2 : 1; }
54 void set_residual(bool new_residual);
55
56 vector<TensorSpec> get_forward_specs(Index) const override;
57 vector<TensorSpec> get_backward_specs(Index) const override;
59 bool backward_uses_input(size_t input) const noexcept override { return input != 1 || !residual; }
60 ForwardSlotKind get_forward_slot_kind(size_t slot) const override
61 {
63 }
64 // With batch normalization folded into the weights, inference convolves
65 // straight into the output slot and never writes ConvolutionView -- so the
66 // arena was reserving a second full activation per layer that nothing
67 // touched. The guard mirrors forward_propagate_folded's own, because the
68 // unfolded fallback still writes the slot: no CUDA build, activations off
69 // the device, or weights outside fp32/bf16 all keep it.
70 bool is_forward_slot_inference_elidable(size_t slot, Device device) const noexcept override
71 {
72#ifdef OPENNN_HAS_CUDA
73 return slot == ConvolutionView
74 && batch_norm.active()
77#else
78 (void)slot; (void)device;
79 return false;
80#endif
81 }
82 bool folds_input_delta_addend(size_t input) const noexcept override { return input == 0; }
83 size_t get_recomputable_forward_slot() const noexcept override
84 {
85 return batch_norm.active() ? size_t(ConvolutionView) : SIZE_MAX;
86 }
88
89 void set(const Shape& = {0, 0, 0},
90 const Shape& = {3, 3, 1, 1},
91 const string& = "Identity",
92 const Shape& = {1, 1},
93 const string& = "Valid",
95 const string& = "convolutional_layer");
96
97 bool accepts_input_rank(Index rank) const override { return is_one_of(rank, 3); }
98
99 void apply_input_shape(const Shape&) override;
100
101 void on_compute_dtype_changed() override { update_convolution_operator(); }
102
103 void set_activation_function(const string&);
104 void set_batch_normalization(bool new_batch_normalization);
105
107
108 // ONNX weight loaders — kernels are expected in NCHW layout (Ultralytics/PyTorch).
109 // Ultralytics ONNX export folds BN into conv: folded_conv_bn takes the BN-folded
110 // kernel and bias (no separate BN tensors) and stores them with identity BN so
111 // inference is mathematically equivalent.
112 void load_onnx_folded_conv_bn(const float* kernel_nchw, const float* folded_bias);
113 void load_onnx_conv_bias(const float* bias, const float* kernel_nchw);
114 void reinit_onnx_cls_out(float prior_bias);
115
116 void read_JSON_body(const Json*) override;
117 void write_JSON_body(JsonWriter&) const override;
118 void on_loaded() override { update_convolution_operator(); }
119
121
122private:
123
124#ifdef OPENNN_HAS_CUDA
125 Buffer folded_parameters;
126 bool folded_dirty = true;
127
128 bool forward_propagate_folded(ForwardPropagation&, size_t);
129#endif
130
131 Index input_channels = 0;
132
133 bool use_padding = false;
134 bool residual = false;
135
136 ConvolutionOperator convolution;
137 ActivationOperator activation_operator;
139
140 enum Forward {Input, ConvolutionView, BatchNormMean, BatchNormInverseVariance, ReluMask, Output};
141
142 void update_convolution_operator();
143};
144
145}
vector< TensorSpec > get_forward_specs(Index) const override
Index get_sources_number() const noexcept override
Definition convolutional_layer.h:53
void on_compute_dtype_changed() override
Definition convolutional_layer.h:101
Shape get_output_shape() const override
ActivationFunction get_activation_function() const noexcept
Definition convolutional_layer.h:45
void on_loaded() override
Definition convolutional_layer.h:118
void set_residual(bool new_residual)
void read_JSON_body(const Json *) override
bool folds_input_delta_addend(size_t input) const noexcept override
Definition convolutional_layer.h:82
Index get_row_stride() const noexcept
Definition convolutional_layer.h:39
ForwardSlotKind get_forward_slot_kind(size_t slot) const override
Definition convolutional_layer.h:60
Index get_output_height() const
void set_activation_function(const string &)
void load_onnx_folded_conv_bn(const float *kernel_nchw, const float *folded_bias)
ActivationFunction get_output_activation() const noexcept override
Definition convolutional_layer.h:46
bool get_batch_normalization() const
Definition convolutional_layer.h:48
bool accepts_input_rank(Index rank) const override
Definition convolutional_layer.h:97
void write_JSON_body(JsonWriter &) const override
bool is_forward_slot_inference_elidable(size_t slot, Device device) const noexcept override
Definition convolutional_layer.h:70
bool get_residual() const noexcept
Definition convolutional_layer.h:52
void reinit_onnx_cls_out(float prior_bias)
Index get_padding_width() const
vector< TensorSpec > get_backward_specs(Index) const override
Index get_column_stride() const noexcept
Definition convolutional_layer.h:40
Shape get_input_shape() const noexcept override
Definition convolutional_layer.h:27
bool backward_uses_forward_output() const noexcept override
Definition convolutional_layer.h:58
void load_darknet_weights(FILE *)
void set_batch_normalization(bool new_batch_normalization)
Index get_kernels_number() const noexcept
Definition convolutional_layer.h:37
void set(const Shape &={0, 0, 0}, const Shape &={3, 3, 1, 1}, const string &="Identity", const Shape &={1, 1}, const string &="Valid", BatchNormalization=BatchNormalization::No, const string &="convolutional_layer")
Index get_kernel_height() const noexcept
Definition convolutional_layer.h:34
bool backward_uses_input(size_t input) const noexcept override
Definition convolutional_layer.h:59
void load_onnx_conv_bias(const float *bias, const float *kernel_nchw)
Index get_output_width() const
size_t get_recomputable_forward_slot() const noexcept override
Definition convolutional_layer.h:83
Index get_kernel_width() const noexcept
Definition convolutional_layer.h:35
Convolutional(const Shape &={3, 3, 1}, const Shape &={3, 3, 1, 1}, const string &="Identity", const Shape &={1, 1}, const string &="Valid", BatchNormalization=BatchNormalization::No, const string &="convolutional_layer")
void recompute_forward_slot(ForwardPropagation &, size_t) override
Index get_padding_height() const
void forward_propagate(ForwardPropagation &, size_t, ForwardPropagationMode) override
void apply_input_shape(const Shape &) override
Index get_kernel_channels() const noexcept
Definition convolutional_layer.h:36
void get_folded_parameters(vector< float > &kernel_oihw, vector< float > &bias) const
Definition json.h:92
Definition json.h:24
Layer(LayerType type, Trainability trainability=Trainability::Trainable)
Definition layer.h:210
Type weights_dtype
Definition layer.h:222
Definition energy_meter.h:7
Definition configuration.h:10
Device
Definition configuration.h:12
@ CUDA
Definition configuration.h:12
constexpr bool is_one_of(const T &value, const Candidates &... candidates)
Definition opennn_types.h:273
@ FP32
Definition configuration.h:13
@ BF16
Definition configuration.h:13
BatchNormalization
Definition layer.h:19
@ No
Definition layer.h:19
ForwardSlotKind
Definition layer.h:18
@ TrainingOnly
Definition layer.h:18
@ Pooled
Definition layer.h:18
ForwardPropagationMode
Definition forward_propagation.h:33
ActivationFunction
Definition configuration.h:39
@ Identity
Definition configuration.h:39
Definition activation_operator.h:12
Definition batch_norm_operator.h:20
Definition tensor_types.h:340
Definition convolution_operator.h:12
Definition forward_propagation.h:52
Definition tensor_types.h:172