GCC Code Coverage Report


Directory: src/lib/
File: src/lib/mod_full_layer.f90
Date: 2024-06-28 12:51:18
Exec Total Coverage
Lines: 116 190 61.1%
Functions: 0 0 -%
Branches: 721 1472 49.0%

Line Branch Exec Source
1 !!!#############################################################################
2 !!! Code written by Ned Thaddeus Taylor
3 !!! Code part of the ATHENA library - a feedforward neural network library
4 !!!#############################################################################
5 !!! module contains implementation of a fully connected (dense) layer
6 !!!#############################################################################
7 !!! Attribution statement:
8 !!! The following procedures are based on code from the neural-fortran library
9 !!! https://github.com/modern-fortran/neural-fortran/blob/main/src/nf/nf_layer.f90
10 !!! procedures:
11 !!! - get_num_params*
12 !!! - get_params*
13 !!! - set_params*
14 !!! - get_gradients*
15 !!! - set_gradients*
16 !!!#############################################################################
17 module full_layer
18 use constants, only: real12
19 use base_layer, only: learnable_layer_type
20 use custom_types, only: activation_type, initialiser_type
21 implicit none
22
23
24 !!!-----------------------------------------------------------------------------
25 !!! fully connected network layer type
26 !!!-----------------------------------------------------------------------------
27 type, extends(learnable_layer_type) :: full_layer_type
28 integer :: num_inputs, num_addit_inputs = 0
29 integer :: num_outputs
30 real(real12), allocatable, dimension(:,:) :: weight
31 real(real12), allocatable, dimension(:,:,:) :: dw ! weight gradient
32 real(real12), allocatable, dimension(:,:) :: output, z !output and activation
33 real(real12), allocatable, dimension(:,:) :: di ! input gradient (i.e. delta)
34 contains
35 procedure, pass(this) :: get_num_params => get_num_params_full
36 procedure, pass(this) :: get_params => get_params_full
37 procedure, pass(this) :: set_params => set_params_full
38 procedure, pass(this) :: get_gradients => get_gradients_full
39 procedure, pass(this) :: set_gradients => set_gradients_full
40 procedure, pass(this) :: get_output => get_output_full
41
42 procedure, pass(this) :: print => print_full
43 procedure, pass(this) :: set_shape => set_shape_full
44 procedure, pass(this) :: init => init_full
45 procedure, pass(this) :: set_batch_size => set_batch_size_full
46
47 procedure, pass(this) :: forward => forward_rank
48 procedure, pass(this) :: backward => backward_rank
49 procedure, private, pass(this) :: forward_2d
50 procedure, private, pass(this) :: backward_2d
51
52 procedure, pass(this) :: reduce => layer_reduction
53 procedure, pass(this) :: merge => layer_merge
54 procedure :: add_t_t => layer_add !t = type, r = real, i = int
55 generic :: operator(+) => add_t_t !, public
56 end type full_layer_type
57
58
59 !!!-----------------------------------------------------------------------------
60 !!! interface for layer set up
61 !!!-----------------------------------------------------------------------------
62 interface full_layer_type
63 module function layer_setup( &
64 num_outputs, num_inputs, num_addit_inputs, batch_size, &
65 activation_function, activation_scale, &
66 kernel_initialiser, bias_initialiser) result(layer)
67 integer, intent(in) :: num_outputs
68 integer, optional, intent(in) :: num_inputs, num_addit_inputs
69 integer, optional, intent(in) :: batch_size
70 real(real12), optional, intent(in) :: activation_scale
71 character(*), optional, intent(in) :: activation_function, &
72 kernel_initialiser, bias_initialiser
73 type(full_layer_type) :: layer
74 end function layer_setup
75 end interface full_layer_type
76
77
78 private
79 public :: full_layer_type
80 public :: read_full_layer
81
82
83 contains
84
85 !!!#############################################################################
86 !!! layer reduction
87 !!!#############################################################################
88 1 subroutine layer_reduction(this, rhs)
89 implicit none
90 class(full_layer_type), intent(inout) :: this
91 class(learnable_layer_type), intent(in) :: rhs
92
93 select type(rhs)
94 type is(full_layer_type)
95
37/70
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 1 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 1 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 1 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 1 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 1 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 1 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 1 times.
✗ Branch 54 not taken.
✓ Branch 55 taken 1 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 1 times.
✗ Branch 60 not taken.
✓ Branch 61 taken 1 times.
✗ Branch 63 not taken.
✓ Branch 64 taken 1 times.
✗ Branch 66 not taken.
✓ Branch 67 taken 1 times.
✗ Branch 69 not taken.
✓ Branch 70 taken 1 times.
✗ Branch 72 not taken.
✓ Branch 73 taken 1 times.
✗ Branch 75 not taken.
✓ Branch 76 taken 1 times.
✗ Branch 78 not taken.
✓ Branch 79 taken 1 times.
✓ Branch 81 taken 1 times.
✗ Branch 82 not taken.
✓ Branch 83 taken 1 times.
✗ Branch 84 not taken.
✓ Branch 85 taken 1 times.
✗ Branch 86 not taken.
✓ Branch 87 taken 1 times.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✓ Branch 91 taken 1 times.
✓ Branch 92 taken 1 times.
✓ Branch 93 taken 10 times.
✓ Branch 94 taken 1 times.
✓ Branch 95 taken 20 times.
✓ Branch 96 taken 10 times.
32 this%dw = this%dw + rhs%dw
96 end select
97
98 1 end subroutine layer_reduction
99 !!!#############################################################################
100
101
102 !!!#############################################################################
103 !!! layer addition
104 !!!#############################################################################
105 1 function layer_add(a, b) result(output)
106 implicit none
107 class(full_layer_type), intent(in) :: a, b
108 type(full_layer_type) :: output
109
110
19/38
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 1 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 1 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 1 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 1 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
1 output = a
111
37/70
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 1 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 1 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 1 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 1 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 1 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 1 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 1 times.
✗ Branch 54 not taken.
✓ Branch 55 taken 1 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 1 times.
✗ Branch 60 not taken.
✓ Branch 61 taken 1 times.
✗ Branch 63 not taken.
✓ Branch 64 taken 1 times.
✗ Branch 66 not taken.
✓ Branch 67 taken 1 times.
✗ Branch 69 not taken.
✓ Branch 70 taken 1 times.
✗ Branch 72 not taken.
✓ Branch 73 taken 1 times.
✗ Branch 75 not taken.
✓ Branch 76 taken 1 times.
✗ Branch 78 not taken.
✓ Branch 79 taken 1 times.
✓ Branch 81 taken 1 times.
✗ Branch 82 not taken.
✓ Branch 83 taken 1 times.
✗ Branch 84 not taken.
✓ Branch 85 taken 1 times.
✗ Branch 86 not taken.
✓ Branch 87 taken 1 times.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✓ Branch 91 taken 1 times.
✓ Branch 92 taken 1 times.
✓ Branch 93 taken 10 times.
✓ Branch 94 taken 1 times.
✓ Branch 95 taken 20 times.
✓ Branch 96 taken 10 times.
32 output%dw = output%dw + b%dw
112
113
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
2 end function layer_add
114 !!!#############################################################################
115
116
117 !!!#############################################################################
118 !!! layer merge
119 !!!#############################################################################
120 3 subroutine layer_merge(this, input)
121 implicit none
122 class(full_layer_type), intent(inout) :: this
123 class(learnable_layer_type), intent(in) :: input
124
125 select type(input)
126 class is(full_layer_type)
127
37/70
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 3 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 3 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 3 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 3 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 3 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 3 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 3 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 3 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 3 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 3 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 3 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 3 times.
✗ Branch 54 not taken.
✓ Branch 55 taken 3 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 3 times.
✗ Branch 60 not taken.
✓ Branch 61 taken 3 times.
✗ Branch 63 not taken.
✓ Branch 64 taken 3 times.
✗ Branch 66 not taken.
✓ Branch 67 taken 3 times.
✗ Branch 69 not taken.
✓ Branch 70 taken 3 times.
✗ Branch 72 not taken.
✓ Branch 73 taken 3 times.
✗ Branch 75 not taken.
✓ Branch 76 taken 3 times.
✗ Branch 78 not taken.
✓ Branch 79 taken 3 times.
✓ Branch 81 taken 3 times.
✗ Branch 82 not taken.
✓ Branch 83 taken 3 times.
✗ Branch 84 not taken.
✓ Branch 85 taken 3 times.
✗ Branch 86 not taken.
✓ Branch 87 taken 3 times.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✓ Branch 91 taken 3 times.
✓ Branch 92 taken 3 times.
✓ Branch 93 taken 17 times.
✓ Branch 94 taken 3 times.
✓ Branch 95 taken 52 times.
✓ Branch 96 taken 17 times.
75 this%dw = this%dw + input%dw
128 end select
129
130 3 end subroutine layer_merge
131 !!!#############################################################################
132
133
134 !!!##########################################################################!!!
135 !!! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * !!!
136 !!!##########################################################################!!!
137
138
139 !!!#############################################################################
140 !!! get number of parameters
141 !!! procedure modified from neural-fortran library
142 !!!#############################################################################
143 5052 pure function get_num_params_full(this) result(num_params)
144 implicit none
145 class(full_layer_type), intent(in) :: this
146 integer :: num_params
147
148 5052 num_params = ( this%num_inputs + 1 )* this%num_outputs
149
150 5052 end function get_num_params_full
151 !!!#############################################################################
152
153
154 !!!#############################################################################
155 !!! get number of parameters
156 !!! procedure modified from neural-fortran library
157 !!!#############################################################################
158 1006 pure function get_params_full(this) result(params)
159 implicit none
160 class(full_layer_type), intent(in) :: this
161 real(real12), allocatable, dimension(:) :: params
162
163
4/6
✓ Branch 0 taken 1006 times.
✓ Branch 1 taken 1006 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1006 times.
✓ Branch 5 taken 1006 times.
✗ Branch 6 not taken.
2012 params = reshape(this%weight, [ (this%num_inputs+1) * this%num_outputs ])
164
165 1006 end function get_params_full
166 !!!#############################################################################
167
168
169 !!!#############################################################################
170 !!! get number of parameters
171 !!! procedure modified from neural-fortran library
172 !!!#############################################################################
173
1/2
✓ Branch 0 taken 1006 times.
✗ Branch 1 not taken.
1006 subroutine set_params_full(this, params)
174 implicit none
175 class(full_layer_type), intent(inout) :: this
176 real(real12), dimension(:), intent(in) :: params
177
178
12/20
✗ Branch 0 not taken.
✓ Branch 1 taken 1006 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1006 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1006 times.
✓ Branch 9 taken 2012 times.
✓ Branch 10 taken 1006 times.
✓ Branch 12 taken 1006 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1006 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1006 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 3501 times.
✓ Branch 21 taken 1006 times.
✓ Branch 22 taken 15984 times.
✓ Branch 23 taken 3501 times.
22503 this%weight = reshape(params, [ this%num_inputs+1, this%num_outputs ])
179
180 1006 end subroutine set_params_full
181 !!!#############################################################################
182
183
184 !!!#############################################################################
185 !!! get number of parameters
186 !!! procedure modified from neural-fortran library
187 !!!#############################################################################
188 1010 pure function get_gradients_full(this, clip_method) result(gradients)
189 use clipper, only: clip_type
190 implicit none
191 class(full_layer_type), intent(in) :: this
192 type(clip_type), optional, intent(in) :: clip_method
193 real(real12), allocatable, dimension(:) :: gradients
194
195 12120 gradients = reshape(sum(this%dw,dim=3)/this%batch_size, &
196
23/38
✗ Branch 0 not taken.
✓ Branch 1 taken 1010 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1010 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1010 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1010 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1010 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1010 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1010 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1010 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1010 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1010 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 1010 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 1010 times.
✓ Branch 36 taken 1010 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 3515 times.
✓ Branch 39 taken 1010 times.
✓ Branch 40 taken 16048 times.
✓ Branch 41 taken 3515 times.
✓ Branch 42 taken 16048 times.
✓ Branch 43 taken 16048 times.
✓ Branch 44 taken 1010 times.
✓ Branch 45 taken 1010 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 1010 times.
✓ Branch 49 taken 1010 times.
✗ Branch 50 not taken.
37631 [ (this%num_inputs+1) * this%num_outputs ])
197
198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1010 times.
1010 if(present(clip_method)) call clip_method%apply(size(gradients),gradients)
199
200 1010 end function get_gradients_full
201 !!!#############################################################################
202
203
204 !!!#############################################################################
205 !!! set gradients
206 !!! procedure modified from neural-fortran library
207 !!!#############################################################################
208 1010 subroutine set_gradients_full(this, gradients)
209 implicit none
210 class(full_layer_type), intent(inout) :: this
211 real(real12), dimension(..), intent(in) :: gradients
212
213 select rank(gradients)
214 rank(0)
215
6/6
✓ Branch 0 taken 1008 times.
✓ Branch 1 taken 1008 times.
✓ Branch 2 taken 3508 times.
✓ Branch 3 taken 1008 times.
✓ Branch 4 taken 16016 times.
✓ Branch 5 taken 3508 times.
21540 this%dw = gradients
216 rank(1)
217 this%dw = spread(reshape(gradients, shape(this%dw(:,:,1))), 3, &
218
29/46
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 4 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 4 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 4 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 4 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 4 times.
✓ Branch 26 taken 4 times.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✓ Branch 29 taken 4 times.
✓ Branch 32 taken 2 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 2 times.
✓ Branch 35 taken 2 times.
✓ Branch 36 taken 7 times.
✓ Branch 37 taken 2 times.
✓ Branch 38 taken 32 times.
✓ Branch 39 taken 7 times.
✓ Branch 40 taken 2 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 2 times.
✗ Branch 43 not taken.
✓ Branch 44 taken 2 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 2 times.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✓ Branch 50 taken 2 times.
✓ Branch 51 taken 2 times.
✓ Branch 52 taken 7 times.
✓ Branch 53 taken 2 times.
✓ Branch 54 taken 32 times.
✓ Branch 55 taken 7 times.
88 this%batch_size)
219 end select
220
221 1010 end subroutine set_gradients_full
222 !!!#############################################################################
223
224
225 !!!#############################################################################
226 !!! get layer outputs
227 !!!#############################################################################
228 508 pure subroutine get_output_full(this, output)
229 implicit none
230 class(full_layer_type), intent(in) :: this
231 real(real12), allocatable, dimension(..), intent(out) :: output
232
233 select rank(output)
234 rank(1)
235 output = reshape(this%output, [size(this%output)])
236 rank(2)
237
18/36
✗ Branch 0 not taken.
✓ Branch 1 taken 508 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 508 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 508 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 508 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 508 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 508 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 508 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 508 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 508 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✓ Branch 30 taken 508 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 508 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 508 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 508 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 508 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 508 times.
✓ Branch 41 taken 508 times.
✓ Branch 42 taken 1008 times.
✓ Branch 43 taken 508 times.
2024 output = this%output
238 end select
239
240 508 end subroutine get_output_full
241 !!!#############################################################################
242
243
244 !!!##########################################################################!!!
245 !!! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * !!!
246 !!!##########################################################################!!!
247
248
249 !!!##########################################################################!!!
250 !!! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * !!!
251 !!!##########################################################################!!!
252
253
254 !!!#############################################################################
255 !!! forward propagation assumed rank handler
256 !!!#############################################################################
257 1027 pure subroutine forward_rank(this, input)
258 implicit none
259 class(full_layer_type), intent(inout) :: this
260 real(real12), dimension(..), intent(in) :: input
261
262 select rank(input); rank(2)
263 1027 call forward_2d(this, input)
264 end select
265 1027 end subroutine forward_rank
266 !!!#############################################################################
267
268
269 !!!#############################################################################
270 !!! backward propagation assumed rank handler
271 !!!#############################################################################
272 1008 pure subroutine backward_rank(this, input, gradient)
273 implicit none
274 class(full_layer_type), intent(inout) :: this
275 real(real12), dimension(..), intent(in) :: input
276 real(real12), dimension(..), intent(in) :: gradient
277
278 select rank(input); rank(2)
279 1008 select rank(gradient); rank(2)
280 1008 call backward_2d(this, input, gradient)
281 end select
282 end select
283 1008 end subroutine backward_rank
284 !!!#############################################################################
285
286
287 !!!##########################################################################!!!
288 !!! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * !!!
289 !!!##########################################################################!!!
290
291
292 !!!#############################################################################
293 !!! set up layer
294 !!!#############################################################################
295 32 module function layer_setup( &
296 num_outputs, num_inputs, num_addit_inputs, &
297 batch_size, &
298 activation_function, activation_scale, &
299 kernel_initialiser, bias_initialiser) result(layer)
300 use activation, only: activation_setup
301 use initialiser, only: get_default_initialiser
302 implicit none
303 integer, intent(in) :: num_outputs
304 integer, optional, intent(in) :: num_inputs, num_addit_inputs
305 integer, optional, intent(in) :: batch_size
306 real(real12), optional, intent(in) :: activation_scale
307 character(*), optional, intent(in) :: activation_function, &
308 kernel_initialiser, bias_initialiser
309
310 type(full_layer_type) :: layer
311
312 real(real12) :: scale
313 character(len=10) :: activation_function_
314
315
316
2/6
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 32 times.
32 layer%name = "full"
317 32 layer%input_rank = 1
318 !!--------------------------------------------------------------------------
319 !! set activation and derivative functions based on input name
320 !!--------------------------------------------------------------------------
321
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 19 times.
32 if(present(activation_function))then
322
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 9 times.
13 activation_function_ = activation_function
323 else
324 19 activation_function_ = "none"
325 end if
326
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if(present(activation_scale))then
327 scale = activation_scale
328 else
329 32 scale = 1._real12
330 end if
331
1/2
✓ Branch 3 taken 32 times.
✗ Branch 4 not taken.
32 write(*,'("FULL activation function: ",A)') trim(activation_function_)
332 allocate(layer%transfer, &
333
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 32 times.
✓ Branch 8 taken 32 times.
✗ Branch 9 not taken.
64 source=activation_setup(activation_function_, scale))
334
335
336 !!--------------------------------------------------------------------------
337 !! initialise batch size
338 !!--------------------------------------------------------------------------
339
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 10 times.
32 if(present(batch_size)) layer%batch_size = batch_size
340
341
342 !!--------------------------------------------------------------------------
343 !! define weights (kernels) and biases initialisers
344 !!--------------------------------------------------------------------------
345
4/4
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 11 times.
32 if(present(kernel_initialiser)) layer%kernel_initialiser =kernel_initialiser
346
4/4
✓ Branch 1 taken 21 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 21 times.
32 if(trim(layer%kernel_initialiser).eq.'') &
347
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 layer%kernel_initialiser=get_default_initialiser(activation_function_)
348
1/2
✓ Branch 3 taken 32 times.
✗ Branch 4 not taken.
32 write(*,'("FULL kernel initialiser: ",A)') trim(layer%kernel_initialiser)
349
3/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
32 if(present(bias_initialiser)) layer%bias_initialiser = bias_initialiser
350
4/4
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 23 times.
✓ Branch 4 taken 9 times.
32 if(trim(layer%bias_initialiser).eq.'') &
351 layer%bias_initialiser = get_default_initialiser(&
352
1/2
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
23 activation_function_, is_bias=.true.)
353
1/2
✓ Branch 3 taken 32 times.
✗ Branch 4 not taken.
32 write(*,'("FULL bias initialiser: ",A)') trim(layer%bias_initialiser)
354
355
356 !!--------------------------------------------------------------------------
357 !! initialise layer shape
358 !!--------------------------------------------------------------------------
359 32 layer%num_outputs = num_outputs
360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if(present(num_addit_inputs)) layer%num_addit_inputs = num_addit_inputs
361
4/4
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 26 times.
58 if(present(num_inputs)) call layer%init(input_shape=[num_inputs])
362
363
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
96 end function layer_setup
364 !!!#############################################################################
365
366
367 !!!#############################################################################
368 !!! setup input layer shape
369 !!!#############################################################################
370
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 subroutine set_shape_full(this, input_shape)
371 implicit none
372 class(full_layer_type), intent(inout) :: this
373 integer, dimension(:), intent(in) :: input_shape
374
375 !!--------------------------------------------------------------------------
376 !! initialise input shape
377 !!--------------------------------------------------------------------------
378
5/8
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 32 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 32 times.
✓ Branch 9 taken 30 times.
✓ Branch 10 taken 2 times.
32 if(size(input_shape,dim=1).eq.this%input_rank)then
379
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 this%num_inputs = input_shape(1) + this%num_addit_inputs
380 else
381
5/8
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✓ Branch 9 taken 7 times.
✓ Branch 10 taken 2 times.
9 this%num_inputs = product(input_shape) + this%num_addit_inputs
382 !stop "ERROR: invalid size of input_shape in full, expected (1)"
383 end if
384
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 32 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 32 times.
✓ Branch 7 taken 32 times.
64 this%input_shape = [this%num_inputs]
385
386 32 end subroutine set_shape_full
387 !!!#############################################################################
388
389
390 !!!#############################################################################
391 !!! initialise layer
392 !!!#############################################################################
393
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 subroutine init_full(this, input_shape, batch_size, verbose)
394 use initialiser, only: initialiser_setup
395 implicit none
396 class(full_layer_type), intent(inout) :: this
397 integer, dimension(:), intent(in) :: input_shape
398 integer, optional, intent(in) :: batch_size
399 integer, optional, intent(in) :: verbose
400
401 integer :: verbose_ = 0
402 64 class(initialiser_type), allocatable :: initialiser_
403
404
405 !!--------------------------------------------------------------------------
406 !! initialise optional arguments
407 !!--------------------------------------------------------------------------
408
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if(present(verbose)) verbose_ = verbose
409
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 27 times.
32 if(present(batch_size)) this%batch_size = batch_size
410
411
412 !!--------------------------------------------------------------------------
413 !! initialise number of inputs
414 !!--------------------------------------------------------------------------
415
4/8
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 32 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 32 times.
32 if(.not.allocated(this%input_shape)) call this%set_shape(input_shape)
416
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 32 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 32 times.
✓ Branch 7 taken 32 times.
64 this%output_shape = [this%num_outputs]
417
418
419 !!--------------------------------------------------------------------------
420 !! allocate weight, weight steps (velocities), output, and activation
421 !!--------------------------------------------------------------------------
422
22/40
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 32 times.
✓ Branch 6 taken 32 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 32 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 32 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 32 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 32 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 32 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 32 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 32 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 32 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 32 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 32 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 32 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 32 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 32 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 32 times.
✓ Branch 47 taken 247 times.
✓ Branch 48 taken 32 times.
✓ Branch 49 taken 24542 times.
✓ Branch 50 taken 247 times.
24821 allocate(this%weight(this%num_inputs+1,this%num_outputs), source=0._real12)
423
424
425 !!--------------------------------------------------------------------------
426 !! initialise weights (kernels)
427 !!--------------------------------------------------------------------------
428
4/8
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 32 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 32 times.
✓ Branch 10 taken 32 times.
✗ Branch 11 not taken.
64 allocate(initialiser_, source=initialiser_setup(this%kernel_initialiser))
429 256 call initialiser_%initialise(this%weight(:this%num_inputs,:), &
430
8/16
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 32 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 32 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 32 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 32 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 32 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 32 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 32 times.
32 fan_in=this%num_inputs+1, fan_out=this%num_outputs)
431
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 32 times.
32 deallocate(initialiser_)
432
433 !! initialise biases
434 !!--------------------------------------------------------------------------
435
4/8
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 32 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 32 times.
✓ Branch 10 taken 32 times.
✗ Branch 11 not taken.
64 allocate(initialiser_, source=initialiser_setup(this%bias_initialiser))
436 128 call initialiser_%initialise(this%weight(this%num_inputs+1,:), &
437
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 32 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 32 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 32 times.
32 fan_in=this%num_inputs+1, fan_out=this%num_outputs)
438
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 32 times.
32 deallocate(initialiser_)
439
440
441 !!--------------------------------------------------------------------------
442 !! initialise batch size-dependent arrays
443 !!--------------------------------------------------------------------------
444
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 10 times.
32 if(this%batch_size.gt.0) call this%set_batch_size(this%batch_size)
445
446
1/4
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
96 end subroutine init_full
447 !!!#############################################################################
448
449
450 !!!#############################################################################
451 !!! set batch size
452 !!!#############################################################################
453 40 subroutine set_batch_size_full(this, batch_size, verbose)
454 implicit none
455 class(full_layer_type), intent(inout) :: this
456 integer, intent(in) :: batch_size
457 integer, optional, intent(in) :: verbose
458
459 integer :: verbose_ = 0
460
461
462 !!--------------------------------------------------------------------------
463 !! initialise optional arguments
464 !!--------------------------------------------------------------------------
465
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if(present(verbose)) verbose_ = verbose
466 40 this%batch_size = batch_size
467
468
469 !!--------------------------------------------------------------------------
470 !! allocate arrays
471 !!--------------------------------------------------------------------------
472
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 if(allocated(this%input_shape))then
473
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
40 if(allocated(this%output)) deallocate(this%output)
474
21/38
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 40 times.
✓ Branch 4 taken 40 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 40 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 40 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 40 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 40 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 40 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 40 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 40 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 40 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 40 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 40 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 40 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 40 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 40 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 40 times.
✓ Branch 45 taken 51 times.
✓ Branch 46 taken 40 times.
✓ Branch 47 taken 339 times.
✓ Branch 48 taken 51 times.
430 allocate(this%output(this%num_outputs, this%batch_size), source=0._real12)
475
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
40 if(allocated(this%z)) deallocate(this%z)
476
31/58
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 40 times.
✓ Branch 4 taken 40 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 40 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 40 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 40 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 40 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 40 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 40 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 40 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 40 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 40 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 40 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 40 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 40 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 40 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 40 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 40 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 40 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 40 times.
✗ Branch 54 not taken.
✓ Branch 55 taken 40 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 40 times.
✗ Branch 60 not taken.
✓ Branch 61 taken 40 times.
✗ Branch 63 not taken.
✓ Branch 64 taken 40 times.
✗ Branch 66 not taken.
✓ Branch 67 taken 40 times.
✗ Branch 69 not taken.
✓ Branch 70 taken 40 times.
✗ Branch 72 not taken.
✓ Branch 73 taken 40 times.
✓ Branch 75 taken 51 times.
✓ Branch 76 taken 40 times.
✓ Branch 77 taken 339 times.
✓ Branch 78 taken 51 times.
430 allocate(this%z, source=this%output)
477
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
40 if(allocated(this%dw)) deallocate(this%dw)
478 allocate(this%dw(this%num_inputs+1,this%num_outputs, this%batch_size), &
479
30/54
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 40 times.
✓ Branch 6 taken 40 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 40 times.
✓ Branch 10 taken 40 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 40 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 40 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 40 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 40 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 40 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 40 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 40 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 40 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 40 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 40 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 40 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 40 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 40 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 40 times.
✗ Branch 50 not taken.
✓ Branch 51 taken 40 times.
✗ Branch 53 not taken.
✓ Branch 54 taken 40 times.
✗ Branch 56 not taken.
✓ Branch 57 taken 40 times.
✗ Branch 59 not taken.
✓ Branch 60 taken 40 times.
✓ Branch 62 taken 51 times.
✓ Branch 63 taken 40 times.
✓ Branch 64 taken 339 times.
✓ Branch 65 taken 51 times.
✓ Branch 66 taken 24272 times.
✓ Branch 67 taken 339 times.
24702 source=0._real12)
480
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
40 if(allocated(this%di)) deallocate(this%di)
481
21/38
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 40 times.
✓ Branch 4 taken 40 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 40 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 40 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 40 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 40 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 40 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 40 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 40 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 40 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 40 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 40 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 40 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 40 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 40 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 40 times.
✓ Branch 45 taken 51 times.
✓ Branch 46 taken 40 times.
✓ Branch 47 taken 876 times.
✓ Branch 48 taken 51 times.
967 allocate(this%di(this%num_inputs, this%batch_size), source=0._real12)
482 end if
483
484 40 end subroutine set_batch_size_full
485 !!!#############################################################################
486
487
488 !!!##########################################################################!!!
489 !!! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * !!!
490 !!!##########################################################################!!!
491
492
493 !!!#############################################################################
494 !!! print layer to file
495 !!!#############################################################################
496 subroutine print_full(this, file)
497 implicit none
498 class(full_layer_type), intent(in) :: this
499 character(*), intent(in) :: file
500
501 integer :: i, unit
502
503
504 !! open file with new unit
505 !!--------------------------------------------------------------------------
506 open(newunit=unit, file=trim(file), access='append')
507
508 !! write convolution initial parameters
509 !!--------------------------------------------------------------------------
510 write(unit,'("FULL")')
511 write(unit,'(3X,"NUM_INPUTS = ",I0)') this%num_inputs
512 write(unit,'(3X,"NUM_OUTPUTS = ",I0)') this%num_outputs
513
514 write(unit,'(3X,"ACTIVATION = ",A)') trim(this%transfer%name)
515 write(unit,'(3X,"ACTIVATION_SCALE = ",F0.9)') this%transfer%scale
516
517 !! write fully connected weights and biases
518 !!--------------------------------------------------------------------------
519 write(unit,'("WEIGHTS")')
520 do i=1,this%num_outputs
521 write(unit,'(5(E16.8E2))') this%weight(:,i)
522 end do
523 write(unit,'("END WEIGHTS")')
524 write(unit,'("END FULL")')
525
526 !! close unit
527 !!--------------------------------------------------------------------------
528 close(unit)
529
530 end subroutine print_full
531 !!!#############################################################################
532
533
534 !!!#############################################################################
535 !!! read layer from file
536 !!!#############################################################################
537 function read_full_layer(unit, verbose) result(layer)
538 use infile_tools, only: assign_val, assign_vec
539 use misc, only: to_lower, icount
540 implicit none
541 integer, intent(in) :: unit
542 integer, optional, intent(in) :: verbose
543
544 class(full_layer_type), allocatable :: layer
545
546 integer :: stat, verbose_ = 0
547 integer :: i, j, k, c, itmp1
548 integer :: num_inputs, num_outputs
549 real(real12) :: activation_scale
550 logical :: found_weights = .false.
551 character(14) :: kernel_initialiser='', bias_initialiser=''
552 character(20) :: activation_function
553 character(256) :: buffer, tag
554
555 real(real12), allocatable, dimension(:) :: data_list
556
557
558 !!--------------------------------------------------------------------------
559 !! initialise optional arguments
560 !!--------------------------------------------------------------------------
561 if(present(verbose)) verbose_ = verbose
562
563
564 !!--------------------------------------------------------------------------
565 !! loop over tags in layer card
566 !!--------------------------------------------------------------------------
567 tag_loop: do
568
569 !! check for end of file
570 !!-----------------------------------------------------------------------
571 read(unit,'(A)',iostat=stat) buffer
572 if(stat.ne.0)then
573 write(0,*) "ERROR: file encountered error (EoF?) before END FULL"
574 stop "Exiting..."
575 end if
576 if(trim(adjustl(buffer)).eq."") cycle tag_loop
577
578 !! check for end of layer card
579 !!-----------------------------------------------------------------------
580 if(trim(adjustl(buffer)).eq."END FULL")then
581 backspace(unit)
582 exit tag_loop
583 end if
584
585 tag=trim(adjustl(buffer))
586 if(scan(buffer,"=").ne.0) tag=trim(tag(:scan(tag,"=")-1))
587
588 !! read parameters from file
589 !!-----------------------------------------------------------------------
590 select case(trim(tag))
591 case("NUM_INPUTS")
592 call assign_val(buffer, num_inputs, itmp1)
593 case("NUM_OUTPUTS")
594 call assign_val(buffer, num_outputs, itmp1)
595 case("ACTIVATION")
596 call assign_val(buffer, activation_function, itmp1)
597 case("ACTIVATION_SCALE")
598 call assign_val(buffer, activation_scale, itmp1)
599 case("KERNEL_INITIALISER")
600 call assign_val(buffer, kernel_initialiser, itmp1)
601 case("BIAS_INITIALISER")
602 call assign_val(buffer, bias_initialiser, itmp1)
603 case("WEIGHTS")
604 found_weights = .true.
605 kernel_initialiser = 'zeros'
606 bias_initialiser = 'zeros'
607 exit tag_loop
608 case default
609 !! don't look for "e" due to scientific notation of numbers
610 !! ... i.e. exponent (E+00)
611 if(scan(to_lower(trim(adjustl(buffer))),&
612 'abcdfghijklmnopqrstuvwxyz').eq.0)then
613 cycle tag_loop
614 elseif(tag(:3).eq.'END')then
615 cycle tag_loop
616 end if
617 stop "Unrecognised line in input file: "//trim(adjustl(buffer))
618 end select
619 end do tag_loop
620
621
622 !!--------------------------------------------------------------------------
623 !! allocate layer
624 !!--------------------------------------------------------------------------
625 layer = full_layer_type( &
626 num_outputs = num_outputs, num_inputs = num_inputs, &
627 activation_function = activation_function, &
628 activation_scale = activation_scale, &
629 kernel_initialiser = kernel_initialiser, &
630 bias_initialiser = bias_initialiser)
631
632 !! check if WEIGHTS card was found
633 !!--------------------------------------------------------------------------
634 if(.not.found_weights)then
635 write(0,*) "WARNING: WEIGHTS card in FULL not found"
636 else
637 do i=1,num_outputs
638 allocate(data_list((num_inputs+1)), source=0._real12)
639 c = 1
640 k = 1
641 data_concat_loop: do while(c.le.num_inputs+1)
642 read(unit,'(A)',iostat=stat) buffer
643 if(stat.ne.0) exit data_concat_loop
644 k = icount(buffer)
645 read(buffer,*,iostat=stat) (data_list(j),j=c,c+k-1)
646 c = c + k
647 end do data_concat_loop
648 layer%weight(:,i) = data_list
649 deallocate(data_list)
650 end do
651
652 !! check for end of weights card
653 !!-----------------------------------------------------------------------
654 read(unit,'(A)') buffer
655 if(trim(adjustl(buffer)).ne."END WEIGHTS")then
656 write(*,*) trim(adjustl(buffer))
657 stop "ERROR: END WEIGHTS not where expected"
658 end if
659 end if
660
661
662 !!--------------------------------------------------------------------------
663 !! check for end of layer card
664 !!--------------------------------------------------------------------------
665 read(unit,'(A)') buffer
666 if(trim(adjustl(buffer)).ne."END FULL")then
667 write(*,*) trim(adjustl(buffer))
668 stop "ERROR: END FULL not where expected"
669 end if
670
671 end function read_full_layer
672 !!!#############################################################################
673
674
675 !!!##########################################################################!!!
676 !!! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * !!!
677 !!!##########################################################################!!!
678
679
680 !!!#############################################################################
681 !!! forward propagation
682 !!!#############################################################################
683 1027 pure subroutine forward_2d(this, input)
684 implicit none
685 class(full_layer_type), intent(inout) :: this
686 real(real12), dimension(this%num_inputs, this%batch_size), &
687 intent(in) :: input
688
689 integer :: s
690
691
692 !! generate outputs from weights, biases, and inputs
693 1027 do concurrent(s=1:this%batch_size)
694 13351 this%z(:,s) = this%weight(this%num_inputs+1,:) + &
695
28/52
✓ Branch 0 taken 1027 times.
✓ Branch 1 taken 1027 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1027 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1027 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1027 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1027 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1027 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 1027 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 1027 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 1027 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 1027 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 1027 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 1027 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 1027 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 1027 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 1027 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 1027 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 1027 times.
✗ Branch 50 not taken.
✓ Branch 51 taken 1027 times.
✗ Branch 53 not taken.
✓ Branch 54 taken 1027 times.
✗ Branch 56 not taken.
✓ Branch 57 taken 1027 times.
✗ Branch 59 not taken.
✓ Branch 60 taken 1027 times.
✗ Branch 63 not taken.
✓ Branch 64 taken 1027 times.
✗ Branch 66 not taken.
✓ Branch 67 taken 1027 times.
✗ Branch 69 not taken.
✓ Branch 70 taken 1027 times.
✗ Branch 72 not taken.
✓ Branch 73 taken 1027 times.
✓ Branch 75 taken 3532 times.
✓ Branch 76 taken 1027 times.
5586 matmul(input(:,s),this%weight(:this%num_inputs,:))
696 end do
697
698 !! apply activation function to activation
699
20/38
✗ Branch 0 not taken.
✓ Branch 1 taken 1027 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1027 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1027 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1027 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1027 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1027 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1027 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1027 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1027 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1027 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 1027 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1027 times.
✓ Branch 24 taken 1027 times.
✗ Branch 25 not taken.
✓ Branch 27 taken 1027 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 1027 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 1027 times.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✓ Branch 35 taken 1027 times.
✓ Branch 36 taken 1027 times.
✓ Branch 37 taken 3532 times.
✓ Branch 38 taken 1027 times.
5586 this%output = this%transfer%activate(this%z)
700
701 1027 end subroutine forward_2d
702 !!!#############################################################################
703
704
705 !!!#############################################################################
706 !!! backward propagation
707 !!! method : gradient descent
708 !!!#############################################################################
709 1008 pure subroutine backward_2d(this, input, gradient)
710 implicit none
711 class(full_layer_type), intent(inout) :: this
712 real(real12), dimension(this%num_inputs, this%batch_size), &
713 intent(in) :: input
714 real(real12), dimension(this%num_outputs, this%batch_size), &
715 intent(in) :: gradient
716
717 2016 real(real12), dimension(this%num_outputs, this%batch_size) :: delta
718 real(real12), dimension(&
719 2016 this%num_inputs, this%num_outputs, this%batch_size) :: dw
720
721 real(real12), dimension(1) :: bias_diff
722
723 integer :: s
724
725
726
2/2
✓ Branch 1 taken 1008 times.
✓ Branch 2 taken 1008 times.
2016 bias_diff = this%transfer%differentiate([1._real12])
727
728 !! the delta values are the error multipled by the derivative ...
729 !! ... of the transfer function
730 !! delta(l) = g'(a) * dE/dI(l)
731 !! delta(l) = differential of activation * error from next layer
732
19/34
✗ Branch 0 not taken.
✓ Branch 1 taken 1008 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1008 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1008 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1008 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1008 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1008 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1008 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1008 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1008 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1008 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 1008 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 1008 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 1008 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 1008 times.
✓ Branch 42 taken 1008 times.
✗ Branch 43 not taken.
✓ Branch 45 taken 1008 times.
✓ Branch 46 taken 1008 times.
✓ Branch 47 taken 3508 times.
✓ Branch 48 taken 1008 times.
5524 delta(:,:) = gradient * this%transfer%differentiate(this%z)
733
734 1008 do concurrent(s=1:this%batch_size)
735 !! partial derivatives of error wrt weights
736 !! dE/dW = o/p(l-1) * delta
737
20/40
✗ Branch 0 not taken.
✓ Branch 1 taken 1008 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1008 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1008 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1008 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1008 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1008 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1008 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1008 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1008 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1008 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 1008 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 1008 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 1008 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 1008 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 1008 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 1008 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 1008 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 1008 times.
✗ Branch 54 not taken.
✓ Branch 55 taken 1008 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 1008 times.
1008 dw(:,:,s) = matmul(input(:,s:s), transpose(delta(:,s:s)))
738
739 !! the errors are summed from the delta of the ...
740 !! ... 'child' node * 'child' weight
741 !! dE/dI(l-1) = sum(weight(l) * delta(l))
742 !! this prepares dE/dI for when it is passed into the previous layer
743
21/38
✓ Branch 0 taken 1008 times.
✓ Branch 1 taken 1008 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1008 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1008 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1008 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1008 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1008 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 1008 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 1008 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 1008 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 1008 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 1008 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 1008 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 1008 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 1008 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 1008 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 1008 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 1008 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 1008 times.
✓ Branch 54 taken 4008 times.
✓ Branch 55 taken 1008 times.
6024 this%di(:,s) = matmul(this%weight(:this%num_inputs,:), delta(:,s))
744 end do
745
746 !! sum weights and biases errors to use in batch gradient descent
747
18/32
✗ Branch 0 not taken.
✓ Branch 1 taken 1008 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1008 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1008 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1008 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1008 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1008 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1008 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1008 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1008 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1008 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 1008 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 1008 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 1008 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 1008 times.
✓ Branch 42 taken 1008 times.
✓ Branch 43 taken 1008 times.
✓ Branch 44 taken 3508 times.
✓ Branch 45 taken 1008 times.
5524 delta = delta * bias_diff(1)
748
45/84
✗ Branch 0 not taken.
✓ Branch 1 taken 1008 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1008 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1008 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1008 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1008 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1008 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1008 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1008 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1008 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1008 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 1008 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 1008 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 1008 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 1008 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 1008 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 1008 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 1008 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 1008 times.
✗ Branch 54 not taken.
✓ Branch 55 taken 1008 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 1008 times.
✗ Branch 60 not taken.
✓ Branch 61 taken 1008 times.
✗ Branch 63 not taken.
✓ Branch 64 taken 1008 times.
✗ Branch 66 not taken.
✓ Branch 67 taken 1008 times.
✗ Branch 69 not taken.
✓ Branch 70 taken 1008 times.
✗ Branch 72 not taken.
✓ Branch 73 taken 1008 times.
✗ Branch 75 not taken.
✓ Branch 76 taken 1008 times.
✗ Branch 78 not taken.
✓ Branch 79 taken 1008 times.
✗ Branch 81 not taken.
✓ Branch 82 taken 1008 times.
✗ Branch 84 not taken.
✓ Branch 85 taken 1008 times.
✗ Branch 87 not taken.
✓ Branch 88 taken 1008 times.
✗ Branch 90 not taken.
✓ Branch 91 taken 1008 times.
✗ Branch 93 not taken.
✓ Branch 94 taken 1008 times.
✗ Branch 96 not taken.
✓ Branch 97 taken 1008 times.
✗ Branch 99 not taken.
✓ Branch 100 taken 1008 times.
✗ Branch 102 not taken.
✓ Branch 103 taken 1008 times.
✗ Branch 105 not taken.
✓ Branch 106 taken 1008 times.
✗ Branch 108 not taken.
✓ Branch 109 taken 1008 times.
✗ Branch 111 not taken.
✓ Branch 112 taken 1008 times.
✗ Branch 114 not taken.
✓ Branch 115 taken 1008 times.
✓ Branch 117 taken 1008 times.
✓ Branch 118 taken 1008 times.
✓ Branch 119 taken 3508 times.
✓ Branch 120 taken 1008 times.
✓ Branch 121 taken 12508 times.
✓ Branch 122 taken 3508 times.
18032 this%dw(:this%num_inputs,:,:) = this%dw(:this%num_inputs,:,:) + dw
749
34/64
✗ Branch 0 not taken.
✓ Branch 1 taken 1008 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1008 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1008 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1008 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1008 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1008 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1008 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1008 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1008 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1008 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 1008 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 1008 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 1008 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 1008 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 1008 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 1008 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 1008 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 1008 times.
✗ Branch 54 not taken.
✓ Branch 55 taken 1008 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 1008 times.
✗ Branch 60 not taken.
✓ Branch 61 taken 1008 times.
✗ Branch 63 not taken.
✓ Branch 64 taken 1008 times.
✗ Branch 66 not taken.
✓ Branch 67 taken 1008 times.
✗ Branch 69 not taken.
✓ Branch 70 taken 1008 times.
✗ Branch 72 not taken.
✓ Branch 73 taken 1008 times.
✗ Branch 75 not taken.
✓ Branch 76 taken 1008 times.
✗ Branch 78 not taken.
✓ Branch 79 taken 1008 times.
✗ Branch 81 not taken.
✓ Branch 82 taken 1008 times.
✗ Branch 84 not taken.
✓ Branch 85 taken 1008 times.
✗ Branch 87 not taken.
✓ Branch 88 taken 1008 times.
✓ Branch 90 taken 1008 times.
✓ Branch 91 taken 1008 times.
✓ Branch 92 taken 3508 times.
✓ Branch 93 taken 1008 times.
5524 this%dw(this%num_inputs+1,:,:) = this%dw(this%num_inputs+1,:,:) + delta(:,:)
750
751 1008 end subroutine backward_2d
752 !!!#############################################################################
753
754
56/96
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 54 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 68 times.
✓ Branch 5 taken 14 times.
✓ Branch 6 taken 1050 times.
✓ Branch 7 taken 14 times.
✓ Branch 8 taken 54 times.
✓ Branch 9 taken 1008 times.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 44 times.
✓ Branch 12 taken 12 times.
✓ Branch 13 taken 30 times.
✓ Branch 14 taken 532 times.
✓ Branch 15 taken 538 times.
✓ Branch 16 taken 24 times.
✓ Branch 17 taken 1057 times.
✓ Branch 18 taken 24 times.
✓ Branch 19 taken 1057 times.
✓ Branch 20 taken 24 times.
✓ Branch 21 taken 1027 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1008 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1008 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 1008 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 1008 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 1008 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 1008 times.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✓ Branch 40 taken 26 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 26 times.
✓ Branch 45 taken 26 times.
✓ Branch 46 taken 26 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 26 times.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✓ Branch 67 taken 26 times.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✓ Branch 70 taken 26 times.
✓ Branch 71 taken 26 times.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✓ Branch 74 taken 26 times.
✓ Branch 75 taken 26 times.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✓ Branch 78 taken 26 times.
✓ Branch 79 taken 26 times.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✓ Branch 82 taken 26 times.
✗ Branch 83 not taken.
✓ Branch 84 taken 26 times.
✓ Branch 86 taken 26 times.
✗ Branch 87 not taken.
✗ Branch 88 not taken.
✓ Branch 89 taken 26 times.
✓ Branch 90 taken 26 times.
✗ Branch 91 not taken.
✓ Branch 92 taken 3 times.
✓ Branch 93 taken 23 times.
✓ Branch 94 taken 26 times.
✗ Branch 95 not taken.
✓ Branch 96 taken 3 times.
✓ Branch 97 taken 23 times.
✓ Branch 98 taken 26 times.
✗ Branch 99 not taken.
✓ Branch 100 taken 3 times.
✓ Branch 101 taken 23 times.
✓ Branch 102 taken 26 times.
✗ Branch 103 not taken.
✓ Branch 104 taken 3 times.
✓ Branch 105 taken 23 times.
4777 end module full_layer
755 !!!#############################################################################
756