Skip to content

Commit 0934f7f

Browse files
committed
Dropout layers always in training mode; except when is called, when they are in inference mode
1 parent d323175 commit 0934f7f

File tree

7 files changed

+77
-79
lines changed

7 files changed

+77
-79
lines changed

src/nf/nf_dropout_layer.f90

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ module nf_dropout_layer
2222

2323
real :: dropout_rate ! probability of dropping a neuron
2424
real :: scale ! scale factor to preserve the input sum
25-
logical :: training = .false. ! set to .true. in training mode
25+
logical :: training = .true. ! set to .false. for inference
2626

2727
contains
2828

@@ -33,13 +33,11 @@ module nf_dropout_layer
3333
end type dropout_layer
3434

3535
interface dropout_layer
36-
module function dropout_layer_cons(rate, training) &
36+
module function dropout_layer_cons(rate) &
3737
result(res)
3838
!! This function returns the `dropout_layer` instance.
3939
real, intent(in) :: rate
4040
!! Dropout rate
41-
logical, intent(in), optional :: training
42-
!! Training mode (default .false.)
4341
type(dropout_layer) :: res
4442
!! dropout_layer instance
4543
end function dropout_layer_cons

src/nf/nf_dropout_layer_submodule.f90

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@
44

55
contains
66

7-
module function dropout_layer_cons(rate, training) result(res)
7+
module function dropout_layer_cons(rate) result(res)
88
real, intent(in) :: rate
9-
logical, intent(in), optional :: training
109
type(dropout_layer) :: res
1110
res % dropout_rate = rate
12-
if (present(training)) res % training = training
1311
end function dropout_layer_cons
1412

1513

src/nf/nf_layer_constructors.f90

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ module function dense(layer_size, activation) result(res)
104104
!! Resulting layer instance
105105
end function dense
106106

107-
module function dropout(rate, training) result(res)
107+
module function dropout(rate) result(res)
108108
!! Create a dropout layer with a given dropout rate.
109109
!!
110110
!! This layer is for randomly disabling neurons during training.
@@ -118,8 +118,6 @@ module function dropout(rate, training) result(res)
118118
!! ```
119119
real, intent(in) :: rate
120120
!! Dropout rate - fraction of neurons to randomly disable during training
121-
logical, intent(in), optional :: training
122-
!! Training mode (default .false.)
123121
type(layer) :: res
124122
!! Resulting layer instance
125123
end function dropout

src/nf/nf_layer_constructors_submodule.f90

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,11 @@ module function dense(layer_size, activation) result(res)
6565
end function dense
6666

6767

68-
module function dropout(rate, training) result(res)
68+
module function dropout(rate) result(res)
6969
real, intent(in) :: rate
70-
logical, intent(in), optional :: training
7170
type(layer) :: res
7271
res % name = 'dropout'
73-
allocate(res % p, source=dropout_layer(rate, training))
72+
allocate(res % p, source=dropout_layer(rate))
7473
end function dropout
7574

7675

src/nf/nf_network.f90

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ module nf_network
2626
procedure :: get_params
2727
procedure :: print_info
2828
procedure :: set_params
29+
procedure :: set_training_mode
2930
procedure :: train
3031
procedure :: update
3132

@@ -223,6 +224,15 @@ module subroutine set_params(self, params)
223224
!! Network parameters to set
224225
end subroutine set_params
225226

227+
module subroutine set_training_mode(self, training)
228+
!! Set the mode to training (.true.) or inference (.false.).
229+
!! Used internally to enable/disable the dropout layers in the network.
230+
class(network), intent(in out) :: self
231+
!! Network instance
232+
logical, intent(in) :: training
233+
!! .true. for training mode, .false. for inference.
234+
end subroutine set_training_mode
235+
226236
module subroutine print_info(self)
227237
!! Prints a brief summary of the network and its layers to the screen.
228238
class(network), intent(in) :: self

src/nf/nf_network_submodule.f90

Lines changed: 53 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -251,15 +251,11 @@ module function predict_1d(self, input) result(res)
251251
num_layers = size(self % layers)
252252

253253
! predict is run in inference mode only;
254-
! set all dropout layers' training mode to false.
255-
do n = 2, num_layers
256-
select type(this_layer => self % layers(n) % p)
257-
type is(dropout_layer)
258-
this_layer % training = .false.
259-
end select
260-
end do
261-
254+
! set all dropout layers' training mode to false, and
255+
! return to training mode after inference.
256+
call self % set_training_mode(.false.)
262257
call self % forward(input)
258+
call self % set_training_mode(.true.)
263259

264260
select type(output_layer => self % layers(num_layers) % p)
265261
type is(dense_layer)
@@ -269,7 +265,8 @@ module function predict_1d(self, input) result(res)
269265
type is(flatten_layer)
270266
res = output_layer % output
271267
class default
272-
error stop 'network % output not implemented for this output layer'
268+
error stop 'network % output not implemented for ' // &
269+
trim(self % layers(num_layers) % name) // ' layer'
273270
end select
274271

275272
end function predict_1d
@@ -279,15 +276,25 @@ module function predict_2d(self, input) result(res)
279276
class(network), intent(in out) :: self
280277
real, intent(in) :: input(:,:)
281278
real, allocatable :: res(:)
282-
integer :: num_layers
279+
integer :: n, num_layers
283280

284281
num_layers = size(self % layers)
285282

283+
! predict is run in inference mode only;
284+
! set all dropout layers' training mode to false, and
285+
! return to training mode after inference.
286+
call self % set_training_mode(.false.)
286287
call self % forward(input)
288+
call self % set_training_mode(.true.)
287289

288290
select type(output_layer => self % layers(num_layers) % p)
289291
type is(dense_layer)
290292
res = output_layer % output
293+
type is(flatten_layer)
294+
res = output_layer % output
295+
class default
296+
error stop 'network % output not implemented for ' // &
297+
trim(self % layers(num_layers) % name) // ' layer'
291298
end select
292299

293300
end function predict_2d
@@ -302,15 +309,11 @@ module function predict_3d(self, input) result(res)
302309
num_layers = size(self % layers)
303310

304311
! predict is run in inference mode only;
305-
! set all dropout layers' training mode to false.
306-
do n = 2, num_layers
307-
select type(this_layer => self % layers(n) % p)
308-
type is(dropout_layer)
309-
this_layer % training = .false.
310-
end select
311-
end do
312-
312+
! set all dropout layers' training mode to false, and
313+
! return to training mode after inference.
314+
call self % set_training_mode(.false.)
313315
call self % forward(input)
316+
call self % set_training_mode(.true.)
314317

315318
select type(output_layer => self % layers(num_layers) % p)
316319
type is(conv2d_layer)
@@ -321,7 +324,8 @@ module function predict_3d(self, input) result(res)
321324
type is(flatten_layer)
322325
res = output_layer % output
323326
class default
324-
error stop 'network % output not implemented for this output layer'
327+
error stop 'network % output not implemented for ' // &
328+
trim(self % layers(num_layers) % name) // ' layer'
325329
end select
326330

327331
end function predict_3d
@@ -338,13 +342,9 @@ module function predict_batch_1d(self, input) result(res)
338342
output_size = product(self % layers(num_layers) % layer_shape)
339343

340344
! predict is run in inference mode only;
341-
! set all dropout layers' training mode to false.
342-
do n = 2, num_layers
343-
select type(this_layer => self % layers(n) % p)
344-
type is(dropout_layer)
345-
this_layer % training = .false.
346-
end select
347-
end do
345+
! set all dropout layers' training mode to false, and
346+
! return to training mode after inference.
347+
call self % set_training_mode(.false.)
348348

349349
allocate(res(output_size, batch_size))
350350

@@ -358,11 +358,16 @@ module function predict_batch_1d(self, input) result(res)
358358
type is(flatten_layer)
359359
res(:,i) = output_layer % output
360360
class default
361-
error stop 'network % output not implemented for this output layer'
361+
error stop 'network % output not implemented for ' // &
362+
trim(self % layers(num_layers) % name) // ' layer'
362363
end select
363364

364365
end do batch
365366

367+
! We are now done with inference;
368+
! return to training mode for dropout layers.
369+
call self % set_training_mode(.true.)
370+
366371
end function predict_batch_1d
367372

368373

@@ -377,13 +382,9 @@ module function predict_batch_3d(self, input) result(res)
377382
output_size = product(self % layers(num_layers) % layer_shape)
378383

379384
! predict is run in inference mode only;
380-
! set all dropout layers' training mode to false.
381-
do n = 2, num_layers
382-
select type(this_layer => self % layers(n) % p)
383-
type is(dropout_layer)
384-
this_layer % training = .false.
385-
end select
386-
end do
385+
! set all dropout layers' training mode to false, and
386+
! return to training mode after inference.
387+
call self % set_training_mode(.false.)
387388

388389
allocate(res(output_size, batch_size))
389390

@@ -400,11 +401,16 @@ module function predict_batch_3d(self, input) result(res)
400401
type is(flatten_layer)
401402
res(:,i) = output_layer % output
402403
class default
403-
error stop 'network % output not implemented for this output layer'
404+
error stop 'network % output not implemented for ' // &
405+
trim(self % layers(num_layers) % name) // ' layer'
404406
end select
405407

406408
end do batch
407409

410+
! We are now done with inference;
411+
! return to training mode for dropout layers.
412+
call self % set_training_mode(.true.)
413+
408414
end function predict_batch_3d
409415

410416

@@ -484,6 +490,18 @@ module subroutine set_params(self, params)
484490
end subroutine set_params
485491

486492

493+
module subroutine set_training_mode(self, training)
494+
class(network), intent(in out) :: self
495+
logical, intent(in) :: training
496+
integer :: n
497+
do n = 2, size(self % layers)
498+
select type(this_layer => self % layers(n) % p); type is(dropout_layer)
499+
this_layer % training = training
500+
end select
501+
end do
502+
end subroutine set_training_mode
503+
504+
487505
module subroutine train(self, input_data, output_data, batch_size, &
488506
epochs, optimizer, loss)
489507
class(network), intent(in out) :: self

test/test_dropout_layer.f90

Lines changed: 8 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ program test_dropout_layer
2424
write(stderr, '(a)') 'dropout layer dropout rate should be 0.5.. failed'
2525
end if
2626

27-
if (layer1_p % training) then
27+
if (.not. layer1_p % training) then
2828
ok = .false.
29-
write(stderr, '(a)') 'dropout layer default training mode should be false.. failed'
29+
write(stderr, '(a)') 'dropout layer default training mode should be true.. failed'
3030
end if
3131

3232
if (layer1_p % input_size /= 0) then
@@ -42,25 +42,6 @@ program test_dropout_layer
4242

4343
end select
4444

45-
! Test setting training mode explicitly.
46-
layer1 = dropout(0.5, training=.true.)
47-
select type(layer1_p => layer1 % p)
48-
type is(dropout_layer)
49-
if (.not. layer1_p % training) then
50-
ok = .false.
51-
write(stderr, '(a)') 'dropout layer training mode should be true.. failed'
52-
end if
53-
end select
54-
55-
layer1 = dropout(0.5, training=.false.)
56-
select type(layer1_p => layer1 % p)
57-
type is(dropout_layer)
58-
if (layer1_p % training) then
59-
ok = .false.
60-
write(stderr, '(a)') 'dropout layer training mode should be false.. failed'
61-
end if
62-
end select
63-
6445
! Now we're gonna initialize a minimal network with an input layer and a
6546
! dropout that follows and we'll check that the dropout layer has expected
6647
! state.
@@ -122,31 +103,27 @@ program test_dropout_layer
122103

123104

124105
training: block
125-
real :: x(10), y(5)
106+
real :: x(100), y(5)
126107
real :: tolerance = 1e-3
127108
integer :: n
128-
integer, parameter :: num_iterations = 100000
109+
integer, parameter :: num_iterations = 10000
129110

130111
call random_number(x)
131-
y = [0.1234, 0.2345, 0.3456, 0.4567, 0.5678]
112+
y = [0.12345, 0.23456, 0.34567, 0.45678, 0.56789]
132113

133114
net = network([ &
134-
input(10), &
135-
dropout(0.5, training=.true.), &
115+
input(100), &
116+
dropout(0.5), &
136117
dense(5) &
137118
])
138119

139120
do n = 1, num_iterations
140-
!select type(dropout_l => net % layers(2) % p)
141-
! type is(dropout_layer)
142-
! print *, dropout_l % training, dropout_l % mask
143-
!end select
144121
call net % forward(x)
145122
call net % backward(y)
146123
call net % update()
147-
!print *, n, net % predict(x)
148124

149125
if (all(abs(net % predict(x) - y) < tolerance)) exit
126+
150127
end do
151128

152129
if (.not. n <= num_iterations) then

0 commit comments

Comments
 (0)