From d36edc786ebdb2d0bdcc07af39b27feeca97267d Mon Sep 17 00:00:00 2001 From: Riccardo Orsi Date: Sun, 3 Aug 2025 17:51:31 +0200 Subject: [PATCH 1/2] First change; take a look --- src/nf/nf_conv1d_layer.f90 | 10 ------- src/nf/nf_conv1d_layer_submodule.f90 | 8 ------ src/nf/nf_conv2d_layer.f90 | 10 ------- src/nf/nf_conv2d_layer_submodule.f90 | 16 ----------- src/nf/nf_dense_layer.f90 | 10 ------- src/nf/nf_dense_layer_submodule.f90 | 16 ----------- src/nf/nf_layer.f90 | 11 ++++++++ src/nf/nf_layer_submodule.f90 | 27 +++++++++++++++---- src/nf/nf_locally_connected2d_layer.f90 | 10 ------- ...nf_locally_connected2d_layer_submodule.f90 | 6 ----- 10 files changed, 33 insertions(+), 91 deletions(-) diff --git a/src/nf/nf_conv1d_layer.f90 b/src/nf/nf_conv1d_layer.f90 index 65f82347..dae2b1a4 100644 --- a/src/nf/nf_conv1d_layer.f90 +++ b/src/nf/nf_conv1d_layer.f90 @@ -33,7 +33,6 @@ module nf_conv1d_layer procedure :: backward procedure :: get_gradients_ptr procedure :: get_num_params - procedure :: get_params procedure :: get_params_ptr procedure :: init procedure :: set_params @@ -89,15 +88,6 @@ pure module function get_num_params(self) result(num_params) !! Number of parameters end function get_num_params - module function get_params(self) result(params) - !! Return the parameters (weights and biases) of this layer. - !! The parameters are ordered as weights first, biases second. - class(conv1d_layer), intent(in), target :: self - !! A `conv1d_layer` instance - real, allocatable :: params(:) - !! Parameters to get - end function get_params - module subroutine get_params_ptr(self, w_ptr, b_ptr) !! Return pointers to the parameters (weights and biases) of this layer. class(conv1d_layer), intent(in), target :: self diff --git a/src/nf/nf_conv1d_layer_submodule.f90 b/src/nf/nf_conv1d_layer_submodule.f90 index 98856689..a50657f5 100644 --- a/src/nf/nf_conv1d_layer_submodule.f90 +++ b/src/nf/nf_conv1d_layer_submodule.f90 @@ -144,14 +144,6 @@ pure module function get_num_params(self) result(num_params) num_params = product(shape(self % kernel)) + size(self % biases) end function get_num_params - module function get_params(self) result(params) - class(conv1d_layer), intent(in), target :: self - real, allocatable :: params(:) - real, pointer :: w_(:) => null() - w_(1:size(self % kernel)) => self % kernel - params = [ w_, self % biases] - end function get_params - module subroutine get_params_ptr(self, w_ptr, b_ptr) class(conv1d_layer), intent(in), target :: self real, pointer, intent(out) :: w_ptr(:) diff --git a/src/nf/nf_conv2d_layer.f90 b/src/nf/nf_conv2d_layer.f90 index d6c92c31..96738bfa 100644 --- a/src/nf/nf_conv2d_layer.f90 +++ b/src/nf/nf_conv2d_layer.f90 @@ -34,7 +34,6 @@ module nf_conv2d_layer procedure :: backward procedure :: get_gradients_ptr procedure :: get_num_params - procedure :: get_params procedure :: get_params_ptr procedure :: init procedure :: set_params @@ -90,15 +89,6 @@ pure module function get_num_params(self) result(num_params) !! Number of parameters end function get_num_params - module function get_params(self) result(params) - !! Return the parameters (weights and biases) of this layer. - !! The parameters are ordered as weights first, biases second. - class(conv2d_layer), intent(in), target :: self - !! A `conv2d_layer` instance - real, allocatable :: params(:) - !! Parameters to get - end function get_params - module subroutine get_params_ptr(self, w_ptr, b_ptr) !! Return pointers to the parameters (weights and biases) of this layer. class(conv2d_layer), intent(in), target :: self diff --git a/src/nf/nf_conv2d_layer_submodule.f90 b/src/nf/nf_conv2d_layer_submodule.f90 index 56b398fc..374c2b7c 100644 --- a/src/nf/nf_conv2d_layer_submodule.f90 +++ b/src/nf/nf_conv2d_layer_submodule.f90 @@ -188,22 +188,6 @@ pure module function get_num_params(self) result(num_params) num_params = product(shape(self % kernel)) + size(self % biases) end function get_num_params - - module function get_params(self) result(params) - class(conv2d_layer), intent(in), target :: self - real, allocatable :: params(:) - - real, pointer :: w_(:) => null() - - w_(1:size(self % kernel)) => self % kernel - - params = [ & - w_, & - self % biases & - ] - - end function get_params - module subroutine get_params_ptr(self, w_ptr, b_ptr) class(conv2d_layer), intent(in), target :: self diff --git a/src/nf/nf_dense_layer.f90 b/src/nf/nf_dense_layer.f90 index e93a57ca..ad7d3f76 100644 --- a/src/nf/nf_dense_layer.f90 +++ b/src/nf/nf_dense_layer.f90 @@ -35,7 +35,6 @@ module nf_dense_layer procedure :: forward procedure :: get_gradients_ptr procedure :: get_num_params - procedure :: get_params procedure :: get_params_ptr procedure :: init procedure :: set_params @@ -88,15 +87,6 @@ pure module function get_num_params(self) result(num_params) !! Number of parameters in this layer end function get_num_params - module function get_params(self) result(params) - !! Return the parameters (weights and biases) of this layer. - !! The parameters are ordered as weights first, biases second. - class(dense_layer), intent(in), target :: self - !! Dense layer instance - real, allocatable :: params(:) - !! Parameters of this layer - end function get_params - module subroutine get_params_ptr(self, w_ptr, b_ptr) class(dense_layer), intent(in), target :: self real, pointer, intent(out) :: w_ptr(:) diff --git a/src/nf/nf_dense_layer_submodule.f90 b/src/nf/nf_dense_layer_submodule.f90 index c2f7e236..815a386e 100644 --- a/src/nf/nf_dense_layer_submodule.f90 +++ b/src/nf/nf_dense_layer_submodule.f90 @@ -61,22 +61,6 @@ pure module function get_num_params(self) result(num_params) end function get_num_params - module function get_params(self) result(params) - class(dense_layer), intent(in), target :: self - real, allocatable :: params(:) - - real, pointer :: w_(:) => null() - - w_(1:size(self % weights)) => self % weights - - params = [ & - w_, & - self % biases & - ] - - end function get_params - - module subroutine get_params_ptr(self, w_ptr, b_ptr) class(dense_layer), intent(in), target :: self real, pointer, intent(out) :: w_ptr(:) diff --git a/src/nf/nf_layer.f90 b/src/nf/nf_layer.f90 index 79569845..9c91dbba 100644 --- a/src/nf/nf_layer.f90 +++ b/src/nf/nf_layer.f90 @@ -160,6 +160,17 @@ module function get_params(self) result(params) !! Parameters of this layer end function get_params + module subroutine get_params_ptr(self, w_ptr, b_ptr) + !! Returns the parameters of this layer as pointers. + !! This is used for layers that have weights and biases. + class(layer), intent(in) :: self + !! Layer instance + real, pointer :: w_ptr(:) + !! Pointer to weights of this layer + real, pointer :: b_ptr(:) + !! Pointer to biases of this layer + end subroutine get_params_ptr + module subroutine set_params(self, params) !! Returns the parameters of this layer. class(layer), intent(in out) :: self diff --git a/src/nf/nf_layer_submodule.f90 b/src/nf/nf_layer_submodule.f90 index 5b74eb5d..9d99043d 100644 --- a/src/nf/nf_layer_submodule.f90 +++ b/src/nf/nf_layer_submodule.f90 @@ -640,6 +640,8 @@ end function get_num_params module function get_params(self) result(params) class(layer), intent(in) :: self real, allocatable :: params(:) + real, pointer :: w_ptr(:) + real, pointer :: b_ptr(:) select type (this_layer => self % p) type is (input1d_layer) @@ -649,15 +651,27 @@ module function get_params(self) result(params) type is (input3d_layer) ! No parameters to get. type is (dense_layer) - params = this_layer % get_params() + call this_layer % get_params_ptr(w_ptr, b_ptr) + allocate(params(size(w_ptr) + size(b_ptr))) + params(1:size(w_ptr)) = w_ptr + params(size(w_ptr)+1:) = b_ptr type is (dropout_layer) ! No parameters to get. type is (conv1d_layer) - params = this_layer % get_params() + call this_layer % get_params_ptr(w_ptr, b_ptr) + allocate(params(size(w_ptr) + size(b_ptr))) + params(1:size(w_ptr)) = w_ptr + params(size(w_ptr)+1:) = b_ptr type is (conv2d_layer) - params = this_layer % get_params() + call this_layer % get_params_ptr(w_ptr, b_ptr) + allocate(params(size(w_ptr) + size(b_ptr))) + params(1:size(w_ptr)) = w_ptr + params(size(w_ptr)+1:) = b_ptr type is (locally_connected2d_layer) - params = this_layer % get_params() + call this_layer % get_params_ptr(w_ptr, b_ptr) + allocate(params(size(w_ptr) + size(b_ptr))) + params(1:size(w_ptr)) = w_ptr + params(size(w_ptr)+1:) = b_ptr type is (maxpool1d_layer) ! No parameters to get. type is (maxpool2d_layer) @@ -669,7 +683,10 @@ module function get_params(self) result(params) type is (reshape3d_layer) ! No parameters to get. type is (linear2d_layer) - params = this_layer % get_params() + call this_layer % get_params_ptr(w_ptr, b_ptr) + allocate(params(size(w_ptr) + size(b_ptr))) + params(1:size(w_ptr)) = w_ptr + params(size(w_ptr)+1:) = b_ptr type is (self_attention_layer) params = this_layer % get_params() type is (embedding_layer) diff --git a/src/nf/nf_locally_connected2d_layer.f90 b/src/nf/nf_locally_connected2d_layer.f90 index 2478dc0a..b2b91557 100644 --- a/src/nf/nf_locally_connected2d_layer.f90 +++ b/src/nf/nf_locally_connected2d_layer.f90 @@ -34,7 +34,6 @@ module nf_locally_connected2d_layer procedure :: get_gradients procedure :: get_gradients_ptr procedure :: get_num_params - procedure :: get_params procedure :: get_params_ptr procedure :: init procedure :: set_params @@ -90,15 +89,6 @@ pure module function get_num_params(self) result(num_params) !! Number of parameters end function get_num_params - module function get_params(self) result(params) - !! Return the parameters (weights and biases) of this layer. - !! The parameters are ordered as weights first, biases second. - class(locally_connected2d_layer), intent(in), target :: self - !! A `locally_connected2d_layer` instance - real, allocatable :: params(:) - !! Parameters to get - end function get_params - module subroutine get_params_ptr(self, w_ptr, b_ptr) class(locally_connected2d_layer), intent(in), target :: self real, pointer, intent(out) :: w_ptr(:) diff --git a/src/nf/nf_locally_connected2d_layer_submodule.f90 b/src/nf/nf_locally_connected2d_layer_submodule.f90 index 5b2f5f85..9b00d003 100644 --- a/src/nf/nf_locally_connected2d_layer_submodule.f90 +++ b/src/nf/nf_locally_connected2d_layer_submodule.f90 @@ -122,12 +122,6 @@ pure module function get_num_params(self) result(num_params) num_params = product(shape(self % kernel)) + product(shape(self % biases)) end function get_num_params - module function get_params(self) result(params) - class(locally_connected2d_layer), intent(in), target :: self - real, allocatable :: params(:) - params = [self % kernel, self % biases] - end function get_params - module subroutine get_params_ptr(self, w_ptr, b_ptr) class(locally_connected2d_layer), intent(in), target :: self real, pointer, intent(out) :: w_ptr(:) From 226b030615e2d1302d902e86270d52b5de620419 Mon Sep 17 00:00:00 2001 From: Riccardo Orsi Date: Wed, 6 Aug 2025 16:38:08 +0200 Subject: [PATCH 2/2] Removed set_params as well --- src/nf/nf_conv1d_layer.f90 | 9 -- src/nf/nf_conv1d_layer_submodule.f90 | 15 -- src/nf/nf_conv2d_layer.f90 | 9 -- src/nf/nf_conv2d_layer_submodule.f90 | 23 --- src/nf/nf_dense_layer.f90 | 1 - src/nf/nf_dense_layer_submodule.f90 | 24 ---- src/nf/nf_layer_submodule.f90 | 38 ++++- src/nf/nf_layernorm.f90 | 12 -- src/nf/nf_layernorm_submodule.f90 | 24 +--- src/nf/nf_linear2d_layer.f90 | 11 -- src/nf/nf_linear2d_layer_submodule.f90 | 31 ----- src/nf/nf_locally_connected2d_layer.f90 | 9 -- ...nf_locally_connected2d_layer_submodule.f90 | 14 -- test/test_layernorm.f90 | 18 ++- test/test_linear2d_layer.f90 | 131 ++++++++++-------- 15 files changed, 118 insertions(+), 251 deletions(-) diff --git a/src/nf/nf_conv1d_layer.f90 b/src/nf/nf_conv1d_layer.f90 index dae2b1a4..0877092c 100644 --- a/src/nf/nf_conv1d_layer.f90 +++ b/src/nf/nf_conv1d_layer.f90 @@ -35,7 +35,6 @@ module nf_conv1d_layer procedure :: get_num_params procedure :: get_params_ptr procedure :: init - procedure :: set_params end type conv1d_layer @@ -108,14 +107,6 @@ module subroutine get_gradients_ptr(self, dw_ptr, db_ptr) !! Pointer to the bias gradients end subroutine get_gradients_ptr - module subroutine set_params(self, params) - !! Set the parameters of the layer. - class(conv1d_layer), intent(in out) :: self - !! A `conv1d_layer` instance - real, intent(in) :: params(:) - !! Parameters to set - end subroutine set_params - end interface end module nf_conv1d_layer diff --git a/src/nf/nf_conv1d_layer_submodule.f90 b/src/nf/nf_conv1d_layer_submodule.f90 index a50657f5..391a8bcc 100644 --- a/src/nf/nf_conv1d_layer_submodule.f90 +++ b/src/nf/nf_conv1d_layer_submodule.f90 @@ -160,19 +160,4 @@ module subroutine get_gradients_ptr(self, dw_ptr, db_ptr) db_ptr => self % db end subroutine get_gradients_ptr - module subroutine set_params(self, params) - class(conv1d_layer), intent(in out) :: self - real, intent(in) :: params(:) - - if (size(params) /= self % get_num_params()) then - error stop 'conv1d_layer % set_params: Number of parameters does not match' - end if - - self % kernel = reshape(params(:product(shape(self % kernel))), shape(self % kernel)) - associate(n => product(shape(self % kernel))) - self % biases = params(n + 1 : n + self % filters) - end associate - - end subroutine set_params - end submodule nf_conv1d_layer_submodule diff --git a/src/nf/nf_conv2d_layer.f90 b/src/nf/nf_conv2d_layer.f90 index 96738bfa..0b9c7356 100644 --- a/src/nf/nf_conv2d_layer.f90 +++ b/src/nf/nf_conv2d_layer.f90 @@ -36,7 +36,6 @@ module nf_conv2d_layer procedure :: get_num_params procedure :: get_params_ptr procedure :: init - procedure :: set_params end type conv2d_layer @@ -109,14 +108,6 @@ module subroutine get_gradients_ptr(self, dw_ptr, db_ptr) !! Pointer to the bias gradients end subroutine get_gradients_ptr - module subroutine set_params(self, params) - !! Set the parameters of the layer. - class(conv2d_layer), intent(in out) :: self - !! A `conv2d_layer` instance - real, intent(in) :: params(:) - !! Parameters to set - end subroutine set_params - end interface end module nf_conv2d_layer diff --git a/src/nf/nf_conv2d_layer_submodule.f90 b/src/nf/nf_conv2d_layer_submodule.f90 index 374c2b7c..f4ee450c 100644 --- a/src/nf/nf_conv2d_layer_submodule.f90 +++ b/src/nf/nf_conv2d_layer_submodule.f90 @@ -206,27 +206,4 @@ module subroutine get_gradients_ptr(self, dw_ptr, db_ptr) db_ptr => self % db end subroutine get_gradients_ptr - - module subroutine set_params(self, params) - class(conv2d_layer), intent(in out) :: self - real, intent(in) :: params(:) - - ! Check that the number of parameters is correct. - if (size(params) /= self % get_num_params()) then - error stop 'conv2d % set_params: Number of parameters does not match' - end if - - ! Reshape the kernel. - self % kernel = reshape( & - params(:product(shape(self % kernel))), & - shape(self % kernel) & - ) - - ! Reshape the biases. - associate(n => product(shape(self % kernel))) - self % biases = params(n + 1 : n + self % filters) - end associate - - end subroutine set_params - end submodule nf_conv2d_layer_submodule diff --git a/src/nf/nf_dense_layer.f90 b/src/nf/nf_dense_layer.f90 index ad7d3f76..eebf6b29 100644 --- a/src/nf/nf_dense_layer.f90 +++ b/src/nf/nf_dense_layer.f90 @@ -37,7 +37,6 @@ module nf_dense_layer procedure :: get_num_params procedure :: get_params_ptr procedure :: init - procedure :: set_params end type dense_layer diff --git a/src/nf/nf_dense_layer_submodule.f90 b/src/nf/nf_dense_layer_submodule.f90 index 815a386e..6108489b 100644 --- a/src/nf/nf_dense_layer_submodule.f90 +++ b/src/nf/nf_dense_layer_submodule.f90 @@ -78,30 +78,6 @@ module subroutine get_gradients_ptr(self, dw_ptr, db_ptr) db_ptr => self % db end subroutine get_gradients_ptr - - module subroutine set_params(self, params) - class(dense_layer), intent(in out) :: self - real, intent(in), target :: params(:) - - real, pointer :: p_(:,:) => null() - - ! check if the number of parameters is correct - if (size(params) /= self % get_num_params()) then - error stop 'Error: number of parameters does not match' - end if - - associate(n => self % input_size * self % output_size) - ! reshape the weights - p_(1:self % input_size, 1:self % output_size) => params(1 : n) - self % weights = p_ - - ! reshape the biases - self % biases = params(n + 1 : n + self % output_size) - end associate - - end subroutine set_params - - module subroutine init(self, input_shape) class(dense_layer), intent(in out) :: self integer, intent(in) :: input_shape(:) diff --git a/src/nf/nf_layer_submodule.f90 b/src/nf/nf_layer_submodule.f90 index 9d99043d..31461796 100644 --- a/src/nf/nf_layer_submodule.f90 +++ b/src/nf/nf_layer_submodule.f90 @@ -691,8 +691,12 @@ module function get_params(self) result(params) params = this_layer % get_params() type is (embedding_layer) params = this_layer % get_params() + type is (layernorm_layer) - params = this_layer % get_params() + call this_layer % get_params_ptr(w_ptr, b_ptr) + allocate(params(size(w_ptr) + size(b_ptr))) + params(1:size(w_ptr)) = w_ptr + params(size(w_ptr)+1:) = b_ptr class default error stop 'Unknown layer type.' end select @@ -703,6 +707,8 @@ end function get_params module subroutine set_params(self, params) class(layer), intent(in out) :: self real, intent(in) :: params(:) + real, pointer :: w_ptr(:) + real, pointer :: b_ptr(:) ! Check that the number of parameters is correct. ! This check will still pass if the size(params) == 0 and the layer is a @@ -736,7 +742,10 @@ module subroutine set_params(self, params) // 'on a zero-parameter layer; nothing to do.' type is (dense_layer) - call this_layer % set_params(params) + call this_layer % get_params_ptr(w_ptr, b_ptr) + + w_ptr = params(1:size(w_ptr)) + b_ptr = params(size(w_ptr)+1:) type is (dropout_layer) ! No parameters to set. @@ -744,13 +753,22 @@ module subroutine set_params(self, params) // 'on a zero-parameter layer; nothing to do.' type is (conv1d_layer) - call this_layer % set_params(params) + call this_layer % get_params_ptr(w_ptr, b_ptr) + + w_ptr = params(1:size(w_ptr)) + b_ptr = params(size(w_ptr)+1:) type is (conv2d_layer) - call this_layer % set_params(params) + call this_layer % get_params_ptr(w_ptr, b_ptr) + + w_ptr = params(1:size(w_ptr)) + b_ptr = params(size(w_ptr)+1:) type is (locally_connected2d_layer) - call this_layer % set_params(params) + call this_layer % get_params_ptr(w_ptr, b_ptr) + + w_ptr = params(1:size(w_ptr)) + b_ptr = params(size(w_ptr)+1:) type is (maxpool1d_layer) ! No parameters to set. @@ -758,7 +776,10 @@ module subroutine set_params(self, params) // 'on a zero-parameter layer; nothing to do.' type is (linear2d_layer) - call this_layer % set_params(params) + call this_layer % get_params_ptr(w_ptr, b_ptr) + + w_ptr = params(1:size(w_ptr)) + b_ptr = params(size(w_ptr)+1:) type is (self_attention_layer) call this_layer % set_params(params) @@ -766,7 +787,10 @@ module subroutine set_params(self, params) call this_layer % set_params(params) type is (layernorm_layer) - call this_layer % set_params(params) + call this_layer % get_params_ptr(w_ptr, b_ptr) + + w_ptr = params(1:size(w_ptr)) + b_ptr = params(size(w_ptr)+1:) type is (maxpool2d_layer) ! No parameters to set. diff --git a/src/nf/nf_layernorm.f90 b/src/nf/nf_layernorm.f90 index 7bffc06a..9a859467 100644 --- a/src/nf/nf_layernorm.f90 +++ b/src/nf/nf_layernorm.f90 @@ -37,11 +37,9 @@ module nf_layernorm_layer procedure :: backward procedure :: init procedure :: get_num_params - procedure :: get_params procedure :: get_params_ptr procedure :: get_gradients procedure :: get_gradients_ptr - procedure :: set_params end type layernorm_layer interface layernorm_layer @@ -74,12 +72,6 @@ pure module function get_num_params(self) result(num_params) end function get_num_params - module function get_params(self) result(params) - class(layernorm_layer), intent(in), target :: self - real, allocatable :: params(:) - end function get_params - - module subroutine get_params_ptr(self, g_ptr, b_ptr) class(layernorm_layer), intent(in), target :: self real, pointer, intent(out) :: g_ptr(:), b_ptr(:) @@ -98,9 +90,5 @@ module subroutine get_gradients_ptr(self, dg_ptr, db_ptr) end subroutine get_gradients_ptr - module subroutine set_params(self, params) - class(layernorm_layer), intent(in out) :: self - real, intent(in), target :: params(:) - end subroutine set_params end interface end module nf_layernorm_layer \ No newline at end of file diff --git a/src/nf/nf_layernorm_submodule.f90 b/src/nf/nf_layernorm_submodule.f90 index 5e357b33..dbffabdf 100644 --- a/src/nf/nf_layernorm_submodule.f90 +++ b/src/nf/nf_layernorm_submodule.f90 @@ -108,14 +108,6 @@ pure module function get_num_params(self) result(num_params) end function get_num_params - - module function get_params(self) result(params) - class(layernorm_layer), intent(in), target :: self - real, allocatable :: params(:) - params = [self % gamma, self % beta] - end function get_params - - module subroutine get_params_ptr(self, g_ptr, b_ptr) class(layernorm_layer), intent(in), target :: self real, pointer, intent(out) :: g_ptr(:), b_ptr(:) @@ -137,19 +129,5 @@ module subroutine get_gradients_ptr(self, dg_ptr, db_ptr) dg_ptr => self % d_gamma db_ptr => self % d_beta end subroutine get_gradients_ptr - - - module subroutine set_params(self, params) - class(layernorm_layer), intent(in out) :: self - real, intent(in), target :: params(:) - - ! check if the number of parameters is correct - if (size(params) /= self % get_num_params()) then - error stop 'Error: number of parameters does not match' - end if - - self % gamma = params(1: self % model_dimension) - self % beta = params(self % model_dimension + 1: 2 * self % model_dimension) - - end subroutine set_params + end submodule nf_layernorm_layer_submodule diff --git a/src/nf/nf_linear2d_layer.f90 b/src/nf/nf_linear2d_layer.f90 index f2c8fd16..a336197f 100644 --- a/src/nf/nf_linear2d_layer.f90 +++ b/src/nf/nf_linear2d_layer.f90 @@ -24,11 +24,9 @@ module nf_linear2d_layer procedure :: forward procedure :: init procedure :: get_num_params - procedure :: get_params procedure :: get_params_ptr procedure :: get_gradients procedure :: get_gradients_ptr - procedure :: set_params end type linear2d_layer @@ -61,11 +59,6 @@ pure module function get_num_params(self) result(num_params) integer :: num_params end function get_num_params - module function get_params(self) result(params) - class(linear2d_layer), intent(in), target :: self - real, allocatable :: params(:) - end function get_params - module subroutine get_params_ptr(self, w_ptr, b_ptr) class(linear2d_layer), intent(in), target :: self real, pointer, intent(out) :: w_ptr(:), b_ptr(:) @@ -81,9 +74,5 @@ module subroutine get_gradients_ptr(self, dw_ptr, db_ptr) real, pointer, intent(out) :: dw_ptr(:), db_ptr(:) end subroutine get_gradients_ptr - module subroutine set_params(self, params) - class(linear2d_layer), intent(in out) :: self - real, intent(in), target :: params(:) - end subroutine set_params end interface end module nf_linear2d_layer diff --git a/src/nf/nf_linear2d_layer_submodule.f90 b/src/nf/nf_linear2d_layer_submodule.f90 index 513527f0..ec78ae1a 100644 --- a/src/nf/nf_linear2d_layer_submodule.f90 +++ b/src/nf/nf_linear2d_layer_submodule.f90 @@ -79,15 +79,6 @@ pure module function get_num_params(self) result(num_params) end function get_num_params - module function get_params(self) result(params) - class(linear2d_layer), intent(in), target :: self - real, allocatable :: params(:) - real, pointer :: w_(:) => null() - w_(1: size(self % weights)) => self % weights - params = [w_, self % biases] - end function get_params - - module subroutine get_params_ptr(self, w_ptr, b_ptr) class(linear2d_layer), intent(in), target :: self real, pointer, intent(out) :: w_ptr(:), b_ptr(:) @@ -113,26 +104,4 @@ module subroutine get_gradients_ptr(self, dw_ptr, db_ptr) end subroutine get_gradients_ptr - module subroutine set_params(self, params) - class(linear2d_layer), intent(in out) :: self - real, intent(in), target :: params(:) - - real, pointer :: p_(:,:) => null() - - ! check if the number of parameters is correct - if (size(params) /= self % get_num_params()) then - error stop 'Error: number of parameters does not match' - end if - - associate(n => self % in_features * self % out_features) - ! reshape the weights - p_(1:self % in_features, 1:self % out_features) => params(1 : n) - self % weights = p_ - - ! reshape the biases - self % biases = params(n + 1 : n + self % out_features) - end associate - - end subroutine set_params - end submodule nf_linear2d_layer_submodule \ No newline at end of file diff --git a/src/nf/nf_locally_connected2d_layer.f90 b/src/nf/nf_locally_connected2d_layer.f90 index b2b91557..b5e98ddd 100644 --- a/src/nf/nf_locally_connected2d_layer.f90 +++ b/src/nf/nf_locally_connected2d_layer.f90 @@ -36,7 +36,6 @@ module nf_locally_connected2d_layer procedure :: get_num_params procedure :: get_params_ptr procedure :: init - procedure :: set_params end type locally_connected2d_layer @@ -110,14 +109,6 @@ module subroutine get_gradients_ptr(self, dw_ptr, db_ptr) real, pointer, intent(out) :: db_ptr(:) end subroutine get_gradients_ptr - module subroutine set_params(self, params) - !! Set the parameters of the layer. - class(locally_connected2d_layer), intent(in out) :: self - !! A `locally_connected2d_layer` instance - real, intent(in) :: params(:) - !! Parameters to set - end subroutine set_params - end interface end module nf_locally_connected2d_layer diff --git a/src/nf/nf_locally_connected2d_layer_submodule.f90 b/src/nf/nf_locally_connected2d_layer_submodule.f90 index 9b00d003..43de79d8 100644 --- a/src/nf/nf_locally_connected2d_layer_submodule.f90 +++ b/src/nf/nf_locally_connected2d_layer_submodule.f90 @@ -144,19 +144,5 @@ module subroutine get_gradients_ptr(self, dw_ptr, db_ptr) db_ptr(1:size(self % db)) => self % db end subroutine get_gradients_ptr - module subroutine set_params(self, params) - class(locally_connected2d_layer), intent(in out) :: self - real, intent(in) :: params(:) - - if (size(params) /= self % get_num_params()) then - error stop 'locally_connected2d_layer % set_params: Number of parameters does not match' - end if - - self % kernel = reshape(params(:product(shape(self % kernel))), shape(self % kernel)) - associate(n => product(shape(self % kernel))) - self % biases = reshape(params(n + 1 :), shape(self % biases)) - end associate - - end subroutine set_params end submodule nf_locally_connected2d_layer_submodule diff --git a/test/test_layernorm.f90 b/test/test_layernorm.f90 index 9e8bfccf..ee32c15d 100644 --- a/test/test_layernorm.f90 +++ b/test/test_layernorm.f90 @@ -112,7 +112,7 @@ subroutine test_layernorm_gradients(input, gradient, ok) type(layernorm_layer) :: layernorm_instance type(sgd) :: optim - real :: parameters(8) + real, allocatable :: parameters(:) real :: expected_parameters(8) real :: updated_output(12) real :: expected_updated_output(12) = [& @@ -122,6 +122,9 @@ subroutine test_layernorm_gradients(input, gradient, ok) -0.564699769, -1.13543355, -1.11444426& ] + real, pointer :: w_ptr(:) + real, pointer :: b_ptr(:) + layernorm_instance = layernorm_layer() call layernorm_instance % init([3, 4]) @@ -135,7 +138,12 @@ subroutine test_layernorm_gradients(input, gradient, ok) expected_parameters(1: 4) = 1. expected_parameters(5: 8) = 0. - parameters = layernorm_instance % get_params() + + call layernorm_instance % get_params_ptr(w_ptr, b_ptr) + allocate(parameters(size(w_ptr) + size(b_ptr))) + parameters(1:size(w_ptr)) = w_ptr + parameters(size(w_ptr)+1:) = b_ptr + if (.not. all(parameters.eq.expected_parameters)) then ok = .false. write(stderr, '(a)') 'incorrect parameters.. failed' @@ -143,7 +151,11 @@ subroutine test_layernorm_gradients(input, gradient, ok) optim = SGD(learning_rate=0.01) call optim % minimize(parameters, layernorm_instance % get_gradients()) - call layernorm_instance % set_params(parameters) + + call layernorm_instance % get_params_ptr(w_ptr, b_ptr) + + w_ptr = parameters(1:size(w_ptr)) + b_ptr = parameters(size(w_ptr)+1:) call layernorm_instance % forward(input) diff --git a/test/test_linear2d_layer.f90 b/test/test_linear2d_layer.f90 index 28b99bf0..2a34b067 100644 --- a/test/test_linear2d_layer.f90 +++ b/test/test_linear2d_layer.f90 @@ -107,71 +107,82 @@ subroutine test_linear2d_layer_backward(linear, ok, input, gradient) end subroutine test_linear2d_layer_backward subroutine test_linear2d_layer_gradient_updates(ok) - logical, intent(in out) :: ok - real :: input(3, 4) = reshape([0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.11, 0.12], [3, 4]) - real :: gradient(3, 2) = reshape([0.0, 10., 0.2, 3., 0.4, 1.], [3, 2]) - type(linear2d_layer) :: linear - - integer :: num_parameters - real :: parameters(10) - real :: expected_parameters(10) = [& - 0.100000001, 0.100000001, 0.100000001, 0.100000001, 0.100000001, 0.100000001, 0.100000001, 0.100000001,& - 0.109999999, 0.109999999& - ] - real :: gradients(10) - real :: expected_gradients(10) = [& - 1.03999996, 4.09999990, 7.15999985, 1.12400007, 0.240000010, 1.56000006, 2.88000011, 2.86399961,& - 10.1999998, 4.40000010& - ] - real :: updated_parameters(10) - real :: updated_weights(8) - real :: updated_biases(2) - real :: expected_weights(8) = [& - 0.203999996, 0.509999990, 0.816000044, 0.212400019, 0.124000005, 0.256000012, 0.388000011, 0.386399955& - ] - real :: expected_biases(2) = [1.13000000, 0.550000012] + logical, intent(in out) :: ok + real :: input(3, 4) = reshape([0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.11, 0.12], [3, 4]) + real :: gradient(3, 2) = reshape([0.0, 10., 0.2, 3., 0.4, 1.], [3, 2]) + type(linear2d_layer) :: linear + real, pointer :: w_ptr(:) + real, pointer :: b_ptr(:) + + integer :: num_parameters + real, allocatable :: parameters(:) ! Remove the fixed size + real :: expected_parameters(10) = [& + 0.100000001, 0.100000001, 0.100000001, 0.100000001, 0.100000001, 0.100000001, 0.100000001, 0.100000001,& + 0.109999999, 0.109999999& + ] + real :: gradients(10) + real :: expected_gradients(10) = [& + 1.03999996, 4.09999990, 7.15999985, 1.12400007, 0.240000010, 1.56000006, 2.88000011, 2.86399961,& + 10.1999998, 4.40000010& + ] + real :: updated_parameters(10) + real :: updated_weights(8) + real :: updated_biases(2) + real :: expected_weights(8) = [& + 0.203999996, 0.509999990, 0.816000044, 0.212400019, 0.124000005, 0.256000012, 0.388000011, 0.386399955& + ] + real :: expected_biases(2) = [1.13000000, 0.550000012] + + integer :: i + + linear = linear2d_layer(out_features=2) + call linear % init([3, 4]) + linear % weights = 0.1 + linear % biases = 0.11 + call linear % forward(input) + call linear % backward(input, gradient) - integer :: i + num_parameters = linear % get_num_params() + if (num_parameters /= 10) then + ok = .false. + write(stderr, '(a)') 'incorrect number of parameters.. failed' + end if - linear = linear2d_layer(out_features=2) - call linear % init([3, 4]) - linear % weights = 0.1 - linear % biases = 0.11 - call linear % forward(input) - call linear % backward(input, gradient) + call linear % get_params_ptr(w_ptr, b_ptr) ! Change this_layer to linear + allocate(parameters(size(w_ptr) + size(b_ptr))) + parameters(1:size(w_ptr)) = w_ptr + parameters(size(w_ptr)+1:) = b_ptr - num_parameters = linear % get_num_params() - if (num_parameters /= 10) then - ok = .false. - write(stderr, '(a)') 'incorrect number of parameters.. failed' - end if + if (.not. all(parameters.eq.expected_parameters)) then + ok = .false. + write(stderr, '(a)') 'incorrect parameters.. failed' + end if - parameters = linear % get_params() - if (.not. all(parameters.eq.expected_parameters)) then - ok = .false. - write(stderr, '(a)') 'incorrect parameters.. failed' - end if + gradients = linear % get_gradients() + if (.not. all(gradients.eq.expected_gradients)) then + ok = .false. + write(stderr, '(a)') 'incorrect gradients.. failed' + end if - gradients = linear % get_gradients() - if (.not. all(gradients.eq.expected_gradients)) then - ok = .false. - write(stderr, '(a)') 'incorrect gradients.. failed' - end if + do i = 1, num_parameters + updated_parameters(i) = parameters(i) + 0.1 * gradients(i) + end do - do i = 1, num_parameters - updated_parameters(i) = parameters(i) + 0.1 * gradients(i) - end do - call linear % set_params(updated_parameters) - updated_weights = reshape(linear % weights, shape(expected_weights)) - if (.not. all(updated_weights.eq.expected_weights)) then - ok = .false. - write(stderr, '(a)') 'incorrect updated weights.. failed' - end if - updated_biases = linear % biases - if (.not. all(updated_biases.eq.expected_biases)) then - ok = .false. - write(stderr, '(a)') 'incorrect updated biases.. failed' - end if - end subroutine test_linear2d_layer_gradient_updates + call linear % get_params_ptr(w_ptr, b_ptr) ! Change this_layer to linear + + w_ptr = updated_parameters(1:size(w_ptr)) + b_ptr = updated_parameters(size(w_ptr)+1:) + + updated_weights = reshape(linear % weights, shape(expected_weights)) + if (.not. all(updated_weights.eq.expected_weights)) then + ok = .false. + write(stderr, '(a)') 'incorrect updated weights.. failed' + end if + updated_biases = linear % biases + if (.not. all(updated_biases.eq.expected_biases)) then + ok = .false. + write(stderr, '(a)') 'incorrect updated biases.. failed' + end if +end subroutine test_linear2d_layer_gradient_updates end program test_linear2d_layer \ No newline at end of file