77
88contains
99
10- module function locally_connected2d_layer_cons (filters , kernel_size , activation ) result(res)
11- implicit none
10+ module function locally_connected2d_layer_cons (filters , kernel_size , activation , stride ) result(res)
1211 integer , intent (in ) :: filters
1312 integer , intent (in ) :: kernel_size
1413 class(activation_function), intent (in ) :: activation
14+ integer , intent (in ) :: stride
1515 type (locally_connected2d_layer) :: res
1616
1717 res % kernel_size = kernel_size
1818 res % filters = filters
1919 res % activation_name = activation % get_name()
20+ res % stride = stride
2021 allocate (res % activation, source = activation)
2122 end function locally_connected2d_layer_cons
2223
@@ -26,8 +27,11 @@ module subroutine init(self, input_shape)
2627 integer , intent (in ) :: input_shape(:)
2728
2829 self % channels = input_shape(1 )
29- self % width = input_shape(2 ) - self % kernel_size + 1
30+ self % width = (input_shape(2 ) - self % kernel_size) / self % stride + 1
31+
32+ if (mod (input_shape(2 ) - self % kernel_size , self % stride) /= 0 ) self % width = self % width + 1
3033
34+ ! Output of shape: filters x width
3135 allocate (self % output(self % filters, self % width))
3236 self % output = 0
3337
@@ -63,10 +67,10 @@ pure module subroutine forward(self, input)
6367 input_width = size (input, dim= 2 )
6468
6569 do j = 1 , self % width
66- iws = j
67- iwe = j + self % kernel_size - 1
70+ iws = self % stride * (j -1 ) + 1
71+ iwe = min (iws + self % kernel_size - 1 , input_width)
6872 do n = 1 , self % filters
69- self % z(n, j) = sum (self % kernel(n, j, :, : ) * input(:, iws:iwe)) + self % biases(n, j)
73+ self % z(n, j) = sum (self % kernel(n, j, :, 1 :iwe - iws +1 ) * input(:, iws:iwe)) + self % biases(n, j)
7074 end do
7175 end do
7276 self % output = self % activation % eval(self % z)
@@ -77,7 +81,7 @@ pure module subroutine backward(self, input, gradient)
7781 class(locally_connected2d_layer), intent (in out ) :: self
7882 real , intent (in ) :: input(:,:)
7983 real , intent (in ) :: gradient(:,:)
80- integer :: input_channels, input_width, output_width
84+ integer :: input_channels, input_width
8185 integer :: j, n, k
8286 integer :: iws, iwe
8387 real :: gdz(self % filters, self % width)
@@ -86,14 +90,13 @@ pure module subroutine backward(self, input, gradient)
8690
8791 input_channels = size (input, dim= 1 )
8892 input_width = size (input, dim= 2 )
89- output_width = self % width
9093
91- do j = 1 , output_width
94+ do j = 1 , self % width
9295 gdz(:, j) = gradient(:, j) * self % activation % eval_prime(self % z(:, j))
9396 end do
9497
9598 do n = 1 , self % filters
96- do j = 1 , output_width
99+ do j = 1 , self % width
97100 db_local(n, j) = gdz(n, j)
98101 end do
99102 end do
@@ -102,12 +105,12 @@ pure module subroutine backward(self, input, gradient)
102105 self % gradient = 0.0
103106
104107 do n = 1 , self % filters
105- do j = 1 , output_width
106- iws = j
107- iwe = j + self % kernel_size - 1
108+ do j = 1 , self % width
109+ iws = self % stride * (j -1 ) + 1
110+ iwe = min (iws + self % kernel_size - 1 , input_width)
108111 do k = 1 , self % channels
109- dw_local(n, j, k, : ) = dw_local(n, j, k, : ) + input(k, iws:iwe) * gdz(n, j)
110- self % gradient(k, iws:iwe) = self % gradient(k, iws:iwe) + self % kernel(n, j, k, : ) * gdz(n, j)
112+ dw_local(n, j, k, 1 :iwe - iws +1 ) = dw_local(n, j, k, 1 :iwe - iws +1 ) + input(k, iws:iwe) * gdz(n, j)
113+ self % gradient(k, iws:iwe) = self % gradient(k, iws:iwe) + self % kernel(n, j, k, 1 :iwe - iws +1 ) * gdz(n, j)
111114 end do
112115 end do
113116 end do
@@ -144,5 +147,4 @@ module subroutine get_gradients_ptr(self, dw_ptr, db_ptr)
144147 db_ptr(1 :size (self % db)) = > self % db
145148 end subroutine get_gradients_ptr
146149
147-
148150end submodule nf_locally_connected2d_layer_submodule
0 commit comments