Skip to content

Commit 53b9663

Browse files
committed
Resolve merge conflicts
2 parents 0f64044 + c316ee1 commit 53b9663

11 files changed

+472
-11
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ add_library(neural-fortran
3838
src/nf/nf_layer_constructors_submodule.f90
3939
src/nf/nf_layer.f90
4040
src/nf/nf_layer_submodule.f90
41+
src/nf/nf_linear2d_layer.f90
42+
src/nf/nf_linear2d_layer_submodule.f90
4143
src/nf/nf_loss.f90
4244
src/nf/nf_loss_submodule.f90
4345
src/nf/nf_maxpool2d_layer.f90

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ Read the paper [here](https://arxiv.org/abs/1902.06714).
3535
| Convolutional (2-d) | `conv2d` | `input3d`, `conv2d`, `maxpool2d`, `reshape` | 3 || ✅(*) |
3636
| Max-pooling (2-d) | `maxpool2d` | `input3d`, `conv2d`, `maxpool2d`, `reshape` | 3 |||
3737
| Flatten | `flatten` | `input2d`, `input3d`, `conv2d`, `maxpool2d`, `reshape` | 1 |||
38+
| Linear (2-d) | `linear2d` | `input2d`, `linear2d` | 2 |||
3839
| Reshape (1-d to 3-d) | `reshape` | `input1d`, `dense`, `flatten` | 3 |||
3940

4041
(*) See Issue [#145](https://github.com/modern-fortran/neural-fortran/issues/145) regarding non-converging CNN training on the MNIST dataset.

src/nf.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module nf
33
use nf_datasets_mnist, only: label_digits, load_mnist
44
use nf_layer, only: layer
55
use nf_layer_constructors, only: &
6-
conv2d, dense, dropout, flatten, input, maxpool2d, reshape
6+
conv2d, dense, dropout, flatten, input, linear2d, maxpool2d, reshape
77
use nf_loss, only: mse, quadratic
88
use nf_metrics, only: corr, maxabs
99
use nf_network, only: network

src/nf/nf_layer_constructors.f90

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module nf_layer_constructors
88
implicit none
99

1010
private
11-
public :: conv2d, dense, flatten, input, maxpool2d, reshape, dropout
11+
public :: conv2d, dense, dropout, flatten, input, linear2d, maxpool2d, reshape
1212

1313
interface input
1414

@@ -203,6 +203,15 @@ module function reshape(output_shape) result(res)
203203
!! Resulting layer instance
204204
end function reshape
205205

206+
module function linear2d(out_features) result(res)
207+
!! Rank-2 (sequence_length, out_features) linear layer constructor.
208+
!! sequence_length is determined at layer initialization, based on the
209+
!! output shape of the previous layer.
210+
integer, intent(in) :: out_features
211+
!! Number of output features
212+
type(layer) :: res
213+
!! Resulting layer instance
214+
end function linear2d
206215

207216
end interface
208217

src/nf/nf_layer_constructors_submodule.f90

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use nf_input3d_layer, only: input3d_layer
1111
use nf_maxpool2d_layer, only: maxpool2d_layer
1212
use nf_reshape_layer, only: reshape3d_layer
13+
use nf_linear2d_layer, only: linear2d_layer
1314
use nf_activation, only: activation_function, relu, sigmoid
1415

1516
implicit none
@@ -80,6 +81,7 @@ module function flatten() result(res)
8081
end function flatten
8182

8283

84+
8385
module function input1d(layer_size) result(res)
8486
integer, intent(in) :: layer_size
8587
type(layer) :: res
@@ -157,4 +159,14 @@ module function reshape(output_shape) result(res)
157159

158160
end function reshape
159161

162+
163+
module function linear2d(out_features) result(res)
164+
integer, intent(in) :: out_features
165+
type(layer) :: res
166+
167+
res % name = 'linear2d'
168+
allocate(res % p, source=linear2d_layer(out_features))
169+
170+
end function linear2d
171+
160172
end submodule nf_layer_constructors_submodule

src/nf/nf_layer_submodule.f90

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use nf_input3d_layer, only: input3d_layer
1111
use nf_maxpool2d_layer, only: maxpool2d_layer
1212
use nf_reshape_layer, only: reshape3d_layer
13+
use nf_linear2d_layer, only: linear2d_layer
1314
use nf_optimizers, only: optimizer_base_type
1415

1516
contains
@@ -50,6 +51,8 @@ pure module subroutine backward_1d(self, previous, gradient)
5051
call this_layer % backward(prev_layer % output, gradient)
5152
type is(maxpool2d_layer)
5253
call this_layer % backward(prev_layer % output, gradient)
54+
type is(linear2d_layer)
55+
call this_layer % backward(prev_layer % output, gradient)
5356
end select
5457

5558
end select
@@ -63,9 +66,19 @@ pure module subroutine backward_2d(self, previous, gradient)
6366
class(layer), intent(in) :: previous
6467
real, intent(in) :: gradient(:,:)
6568

66-
! Backward pass from a 2-d layer downstream currently implemented
67-
! only for dense and flatten layers
68-
! CURRENTLY NO LAYERS, tbd: pull/197 and pull/199
69+
select type(this_layer => self % p)
70+
71+
type is(linear2d_layer)
72+
73+
select type(prev_layer => previous % p)
74+
type is(input2d_layer)
75+
call this_layer % backward(prev_layer % output, gradient)
76+
type is(linear2d_layer)
77+
call this_layer % backward(prev_layer % output, gradient)
78+
end select
79+
80+
end select
81+
6982
end subroutine backward_2d
7083

7184

@@ -199,6 +212,8 @@ module subroutine forward(self, input)
199212
call this_layer % forward(prev_layer % output)
200213
type is(reshape3d_layer)
201214
call this_layer % forward(prev_layer % output)
215+
type is(linear2d_layer)
216+
call this_layer % forward(prev_layer % output)
202217
end select
203218

204219
type is(reshape3d_layer)
@@ -213,6 +228,16 @@ module subroutine forward(self, input)
213228
call this_layer % forward(prev_layer % output)
214229
end select
215230

231+
type is(linear2d_layer)
232+
233+
! Upstream layers permitted: input2d, linear2d
234+
select type(prev_layer => input % p)
235+
type is(input2d_layer)
236+
call this_layer % forward(prev_layer % output)
237+
type is(linear2d_layer)
238+
call this_layer % forward(prev_layer % output)
239+
end select
240+
216241
end select
217242

218243
end subroutine forward
@@ -248,8 +273,10 @@ pure module subroutine get_output_2d(self, output)
248273

249274
type is(input2d_layer)
250275
allocate(output, source=this_layer % output)
276+
type is(linear2d_layer)
277+
allocate(output, source=this_layer % output)
251278
class default
252-
error stop '1-d output can only be read from an input1d, dense, or flatten layer.'
279+
error stop '2-d output can only be read from an input2d or linear2d layer.'
253280

254281
end select
255282

@@ -291,20 +318,22 @@ impure elemental module subroutine init(self, input)
291318
call this_layer % init(input % layer_shape)
292319
end select
293320

294-
! The shape of conv2d, dropout, flatten, or maxpool2d layers is not known
295-
! until we receive an input layer.
321+
! The shape of conv2d, dropout, flatten, linear2d, or maxpool2d layers
322+
! is not known until we receive an input layer.
296323
select type(this_layer => self % p)
297324
type is(conv2d_layer)
298325
self % layer_shape = shape(this_layer % output)
299326
type is(dropout_layer)
300327
self % layer_shape = shape(this_layer % output)
301328
type is(flatten_layer)
302329
self % layer_shape = shape(this_layer % output)
330+
type is(linear2d_layer)
331+
self % layer_shape = shape(this_layer % output)
303332
type is(maxpool2d_layer)
304333
self % layer_shape = shape(this_layer % output)
305334
end select
306335

307-
self % input_layer_shape = input % layer_shape
336+
self % input_layer_shape = input % layer_shape
308337
self % initialized = .true.
309338

310339
end subroutine init
@@ -349,6 +378,8 @@ elemental module function get_num_params(self) result(num_params)
349378
num_params = 0
350379
type is (reshape3d_layer)
351380
num_params = 0
381+
type is (linear2d_layer)
382+
num_params = this_layer % get_num_params()
352383
class default
353384
error stop 'Unknown layer type.'
354385
end select
@@ -378,6 +409,8 @@ module function get_params(self) result(params)
378409
! No parameters to get.
379410
type is (reshape3d_layer)
380411
! No parameters to get.
412+
type is (linear2d_layer)
413+
params = this_layer % get_params()
381414
class default
382415
error stop 'Unknown layer type.'
383416
end select
@@ -404,9 +437,11 @@ module function get_gradients(self) result(gradients)
404437
type is (maxpool2d_layer)
405438
! No gradients to get.
406439
type is (flatten_layer)
407-
! No gradients to get.
440+
! No parameters to get.
408441
type is (reshape3d_layer)
409442
! No gradients to get.
443+
type is (linear2d_layer)
444+
gradients = this_layer % get_gradients()
410445
class default
411446
error stop 'Unknown layer type.'
412447
end select
@@ -459,6 +494,9 @@ module subroutine set_params(self, params)
459494
type is (conv2d_layer)
460495
call this_layer % set_params(params)
461496

497+
type is (linear2d_layer)
498+
call this_layer % set_params(params)
499+
462500
type is (maxpool2d_layer)
463501
! No parameters to set.
464502
write(stderr, '(a)') 'Warning: calling set_params() ' &
@@ -476,6 +514,7 @@ module subroutine set_params(self, params)
476514

477515
class default
478516
error stop 'Unknown layer type.'
517+
479518
end select
480519

481520
end subroutine set_params

src/nf/nf_linear2d_layer.f90

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
module nf_linear2d_layer
2+
3+
use nf_activation, only: activation_function
4+
use nf_base_layer, only: base_layer
5+
6+
implicit none
7+
8+
private
9+
public :: linear2d_layer
10+
11+
type, extends(base_layer) :: linear2d_layer
12+
integer :: sequence_length, in_features, out_features, batch_size
13+
14+
real, allocatable :: weights(:,:)
15+
real, allocatable :: biases(:)
16+
real, allocatable :: output(:,:)
17+
real, allocatable :: gradient(:,:) ! input gradient
18+
real, allocatable :: dw(:,:) ! weight gradients
19+
real, allocatable :: db(:) ! bias gradients
20+
21+
contains
22+
23+
procedure :: backward
24+
procedure :: forward
25+
procedure :: init
26+
procedure :: get_num_params
27+
procedure :: get_params
28+
procedure :: get_gradients
29+
procedure :: set_params
30+
31+
end type linear2d_layer
32+
33+
interface linear2d_layer
34+
module function linear2d_layer_cons(out_features) result(res)
35+
integer, intent(in) :: out_features
36+
type(linear2d_layer) :: res
37+
end function linear2d_layer_cons
38+
end interface linear2d_layer
39+
40+
interface
41+
pure module subroutine forward(self, input)
42+
class(linear2d_layer), intent(in out) :: self
43+
real, intent(in) :: input(:,:)
44+
end subroutine forward
45+
46+
pure module subroutine backward(self, input, gradient)
47+
class(linear2d_layer), intent(in out) :: self
48+
real, intent(in) :: input(:,:)
49+
real, intent(in) :: gradient(:,:)
50+
end subroutine backward
51+
52+
module subroutine init(self, input_shape)
53+
class(linear2d_layer), intent(in out) :: self
54+
integer, intent(in) :: input_shape(:)
55+
end subroutine init
56+
57+
pure module function get_num_params(self) result(num_params)
58+
class(linear2d_layer), intent(in) :: self
59+
integer :: num_params
60+
end function get_num_params
61+
62+
module function get_params(self) result(params)
63+
class(linear2d_layer), intent(in), target :: self
64+
real, allocatable :: params(:)
65+
end function get_params
66+
67+
module function get_gradients(self) result(gradients)
68+
class(linear2d_layer), intent(in), target :: self
69+
real, allocatable :: gradients(:)
70+
end function get_gradients
71+
72+
module subroutine set_params(self, params)
73+
class(linear2d_layer), intent(in out) :: self
74+
real, intent(in), target :: params(:)
75+
end subroutine set_params
76+
end interface
77+
end module nf_linear2d_layer

0 commit comments

Comments
 (0)