forked from modern-fortran/neural-fortran
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathtest_conv2d_network.f90
152 lines (118 loc) · 3.81 KB
/
test_conv2d_network.f90
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
program test_conv2d_network
use iso_fortran_env, only: stderr => error_unit
use nf, only: conv2d, input, network, dense, sgd, maxpool2d
implicit none
type(network) :: net
real, allocatable :: sample_input(:,:,:), output(:,:,:)
logical :: ok = .true.
! 3-layer convolutional network
net = network([ &
input(3, 32, 32), &
conv2d(filters=16, kernel_size=3), &
conv2d(filters=32, kernel_size=3) &
])
if (.not. size(net % layers) == 3) then
write(stderr, '(a)') 'conv2d network should have 3 layers.. failed'
ok = .false.
end if
! Test for output shape
allocate(sample_input(3, 32, 32))
sample_input = 0
call net % forward(sample_input)
call net % layers(3) % get_output(output)
if (.not. all(shape(output) == [32, 28, 28])) then
write(stderr, '(a)') 'conv2d network output should have correct shape.. failed'
ok = .false.
end if
deallocate(sample_input, output)
training1: block
type(network) :: cnn
real :: y(1)
real :: tolerance = 1e-4
integer :: n
integer, parameter :: num_iterations = 1000
! Test training of a minimal constant mapping
allocate(sample_input(1, 5, 5))
call random_number(sample_input)
cnn = network([ &
input(1, 5, 5), &
conv2d(filters=1, kernel_size=3), &
conv2d(filters=1, kernel_size=3), &
dense(1) &
])
y = [0.1234567]
do n = 1, num_iterations
call cnn % forward(sample_input)
call cnn % backward(y)
call cnn % update(optimizer=sgd(learning_rate=1.))
if (all(abs(cnn % predict(sample_input) - y) < tolerance)) exit
end do
if (.not. n <= num_iterations) then
write(stderr, '(a)') &
'convolutional network 1 should converge in simple training.. failed'
ok = .false.
end if
end block training1
training2: block
type(network) :: cnn
real :: x(1, 8, 8)
real :: y(1)
real :: tolerance = 1e-4
integer :: n
integer, parameter :: num_iterations = 1000
call random_number(x)
y = [0.1234567]
cnn = network([ &
input(1, 8, 8), &
conv2d(filters=1, kernel_size=3), &
maxpool2d(pool_size=2), &
conv2d(filters=1, kernel_size=3), &
dense(1) &
])
do n = 1, num_iterations
call cnn % forward(x)
call cnn % backward(y)
call cnn % update(optimizer=sgd(learning_rate=1.))
if (all(abs(cnn % predict(x) - y) < tolerance)) exit
end do
if (.not. n <= num_iterations) then
write(stderr, '(a)') &
'convolutional network 2 should converge in simple training.. failed'
ok = .false.
end if
end block training2
training3: block
type(network) :: cnn
real :: x(1, 12, 12)
real :: y(9)
real :: tolerance = 1e-4
integer :: n
integer, parameter :: num_iterations = 5000
call random_number(x)
y = [0.12345, 0.23456, 0.34567, 0.45678, 0.56789, 0.67890, 0.78901, 0.89012, 0.90123]
cnn = network([ &
input(1, 12, 12), &
conv2d(filters=1, kernel_size=3), & ! 1x12x12 input, 1x10x10 output
maxpool2d(pool_size=2), & ! 1x10x10 input, 1x5x5 output
conv2d(filters=1, kernel_size=3), & ! 1x5x5 input, 1x3x3 output
dense(9) & ! 9 outputs
])
do n = 1, num_iterations
call cnn % forward(x)
call cnn % backward(y)
call cnn % update(optimizer=sgd(learning_rate=1.))
if (all(abs(cnn % predict(x) - y) < tolerance)) exit
end do
if (.not. n <= num_iterations) then
write(stderr, '(a)') &
'convolutional network 3 should converge in simple training.. failed'
ok = .false.
end if
end block training3
if (ok) then
print '(a)', 'test_conv2d_network: All tests passed.'
else
write(stderr, '(a)') 'test_conv2d_network: One or more tests failed.'
stop 1
end if
end program test_conv2d_network