Skip to content

Commit 86d916b

Browse files
committed
merge
2 parents e2bba3c + 1db0258 commit 86d916b

33 files changed

+2389
-203
lines changed

CMakeLists.txt

+12-2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ add_library(neural-fortran
2424
src/nf/nf_avgpool3d_layer.f90
2525
src/nf/nf_avgpool3d_layer_submodule.f90
2626
src/nf/nf_base_layer.f90
27+
src/nf/nf_conv1d_layer.f90
28+
src/nf/nf_conv1d_layer_submodule.f90
2729
src/nf/nf_conv2d_layer.f90
2830
src/nf/nf_conv2d_layer_submodule.f90
2931
src/nf/nf_cross_attention_layer.f90
@@ -43,12 +45,18 @@ add_library(neural-fortran
4345
src/nf/nf_input3d_layer_submodule.f90
4446
src/nf/nf_layer_constructors.f90
4547
src/nf/nf_layer_constructors_submodule.f90
48+
src/nf/nf_layernorm.f90
49+
src/nf/nf_layernorm_submodule.f90
4650
src/nf/nf_layer.f90
4751
src/nf/nf_layer_submodule.f90
4852
src/nf/nf_locally_connected_1d_submodule.f90
4953
src/nf/nf_locally_connected_1d.f90
54+
src/nf/nf_locally_connected1d_layer_submodule.f90
55+
src/nf/nf_locally_connected1d_layer.f90
5056
src/nf/nf_linear2d_layer.f90
5157
src/nf/nf_linear2d_layer_submodule.f90
58+
src/nf/nf_embedding_layer.f90
59+
src/nf/nf_embedding_layer_submodule.f90
5260
src/nf/nf_loss.f90
5361
src/nf/nf_loss_submodule.f90
5462
src/nf/nf_maxpool1d_layer.f90
@@ -66,8 +74,10 @@ add_library(neural-fortran
6674
src/nf/nf_parallel.f90
6775
src/nf/nf_parallel_submodule.f90
6876
src/nf/nf_random.f90
69-
src/nf/nf_reshape_layer.f90
70-
src/nf/nf_reshape_layer_submodule.f90
77+
src/nf/nf_reshape2d_layer.f90
78+
src/nf/nf_reshape2d_layer_submodule.f90
79+
src/nf/nf_reshape3d_layer.f90
80+
src/nf/nf_reshape3d_layer_submodule.f90
7181
src/nf/nf_reshape2d_layer.f90
7282
src/nf/nf_reshape2d_layer_submodule.f90
7383
src/nf/nf_self_attention_layer.f90

README.md

+16-9
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ Read the paper [here](https://arxiv.org/abs/1902.06714).
1515

1616
## Features
1717

18-
* Training and inference of dense (fully connected) and convolutional neural
19-
networks
18+
* Training and inference of dense (fully connected), convolutional (1-d and 2-d),
19+
and transformer neural networks
2020
* Stochastic gradient descent optimizers: Classic, momentum, Nesterov momentum,
2121
RMSProp, Adagrad, Adam, AdamW
2222
* More than a dozen activation functions and their derivatives
@@ -30,16 +30,19 @@ Read the paper [here](https://arxiv.org/abs/1902.06714).
3030
| Layer type | Constructor name | Supported input layers | Rank of output array | Forward pass | Backward pass |
3131
|------------|------------------|------------------------|----------------------|--------------|---------------|
3232
| Input | `input` | n/a | 1, 2, 3 | n/a | n/a |
33+
| Embedding | `embedding` | n/a | 2 |||
3334
| Dense (fully-connected) | `dense` | `input1d`, `dense`, `dropout`, `flatten` | 1 |||
3435
| Dropout | `dropout` | `dense`, `flatten`, `input1d` | 1 |||
35-
| Convolutional (2-d) | `conv2d` | `input3d`, `conv2d`, `maxpool2d`, `reshape` | 3 || ✅(*) |
36+
| Locally connected (1-d) | `locally_connected1d` | `input2d`, `locally_connected1d`, `conv1d`, `maxpool1d`, `reshape2d` | 2 |||
37+
| Convolutional (1-d) | `conv1d` | `input2d`, `conv1d`, `maxpool1d`, `reshape2d` | 2 |||
38+
| Convolutional (2-d) | `conv2d` | `input3d`, `conv2d`, `maxpool2d`, `reshape` | 3 |||
39+
| Max-pooling (1-d) | `maxpool1d` | `input2d`, `conv1d`, `maxpool1d`, `reshape2d` | 2 |||
3640
| Max-pooling (2-d) | `maxpool2d` | `input3d`, `conv2d`, `maxpool2d`, `reshape` | 3 |||
37-
| Linear (2-d) | `linear2d` | `input2d`, `linear2d`, `self_attention` | 2 |||
38-
| Self-attention | `self_attention` | `input2d`, `linear2d`, `self_attention` | 2 |||
39-
| Flatten | `flatten` | `input2d`, `input3d`, `conv2d`, `maxpool2d`, `reshape` | 1 |||
40-
| Reshape (1-d to 3-d) | `reshape` | `input1d`, `dense`, `flatten` | 3 |||
41-
42-
(*) See Issue [#145](https://github.com/modern-fortran/neural-fortran/issues/145) regarding non-converging CNN training on the MNIST dataset.
41+
| Linear (2-d) | `linear2d` | `input2d`, `layernorm`, `linear2d`, `self_attention` | 2 |||
42+
| Self-attention | `self_attention` | `input2d`, `layernorm`, `linear2d`, `self_attention` | 2 |||
43+
| Layer Normalization | `layernorm` | `linear2d`, `self_attention` | 2 |||
44+
| Flatten | `flatten` | `input2d`, `input3d`, `conv1d`, `conv2d`, `maxpool1d`, `maxpool2d`, `reshape` | 1 |||
45+
| Reshape (1-d to 2-d or 3-d) | `reshape` | `dense`, `dropout`, `flatten`, `input1d` | 2, 3 |||
4346

4447
## Getting started
4548

@@ -259,13 +262,17 @@ It may be useful to read if you want to contribute a new feature to neural-fortr
259262

260263
Thanks to all open-source contributors to neural-fortran:
261264
[awvwgk](https://github.com/awvwgk),
265+
[certik](https://github.com/certik),
262266
[ggoyman](https://github.com/ggoyman),
263267
[ivan-pi](https://github.com/ivan-pi),
264268
[jacobwilliams](https://github.com/jacobwilliams),
265269
[jvdp1](https://github.com/jvdp1),
266270
[jvo203](https://github.com/jvo203),
271+
[mathomp4](https://github.com/mathomp4),
267272
[milancurcic](https://github.com/milancurcic),
273+
[OneAdder](https://github.com/OneAdder),
268274
[pirpyn](https://github.com/pirpyn),
275+
[rico07](https://github.com/ricor07),
269276
[rouson](https://github.com/rouson),
270277
[rweed](https://github.com/rweed),
271278
[Spnetic-5](https://github.com/Spnetic-5),

example/cnn_mnist.f90

+4-4
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ program cnn_mnist
1212
real, allocatable :: validation_images(:,:), validation_labels(:)
1313
real, allocatable :: testing_images(:,:), testing_labels(:)
1414
integer :: n
15-
integer, parameter :: num_epochs = 10
15+
integer, parameter :: num_epochs = 250
1616

1717
call load_mnist(training_images, training_labels, &
1818
validation_images, validation_labels, &
1919
testing_images, testing_labels)
2020

2121
net = network([ &
2222
input(784), &
23-
reshape([1,28,28]), &
23+
reshape(1, 28, 28), &
2424
conv2d(filters=8, kernel_size=3, activation=relu()), &
2525
maxpool2d(pool_size=2), &
2626
conv2d(filters=16, kernel_size=3, activation=relu()), &
@@ -35,9 +35,9 @@ program cnn_mnist
3535
call net % train( &
3636
training_images, &
3737
label_digits(training_labels), &
38-
batch_size=128, &
38+
batch_size=16, &
3939
epochs=1, &
40-
optimizer=sgd(learning_rate=3.) &
40+
optimizer=sgd(learning_rate=0.001) &
4141
)
4242

4343
print '(a,i2,a,f5.2,a)', 'Epoch ', n, ' done, Accuracy: ', accuracy( &

example/cnn_mnist_1d.f90

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
program cnn_mnist
1+
program cnn_mnist_1d
22

33
use nf, only: network, sgd, &
4-
input, conv2d, maxpool1d, maxpool2d, flatten, dense, reshape, reshape2d, locally_connected_1d, &
4+
input, conv1d, maxpool1d, flatten, dense, reshape, locally_connected1d, &
55
load_mnist, label_digits, softmax, relu
66

77
implicit none
@@ -12,18 +12,18 @@ program cnn_mnist
1212
real, allocatable :: validation_images(:,:), validation_labels(:)
1313
real, allocatable :: testing_images(:,:), testing_labels(:)
1414
integer :: n
15-
integer, parameter :: num_epochs = 10
15+
integer, parameter :: num_epochs = 250
1616

1717
call load_mnist(training_images, training_labels, &
1818
validation_images, validation_labels, &
1919
testing_images, testing_labels)
2020

2121
net = network([ &
2222
input(784), &
23-
reshape2d([28,28]), &
24-
locally_connected_1d(filters=8, kernel_size=3, activation=relu()), &
23+
reshape(28, 28), &
24+
locally_connected1d(filters=8, kernel_size=3, activation=relu()), &
2525
maxpool1d(pool_size=2), &
26-
locally_connected_1d(filters=16, kernel_size=3, activation=relu()), &
26+
locally_connected1d(filters=16, kernel_size=3, activation=relu()), &
2727
maxpool1d(pool_size=2), &
2828
dense(10, activation=softmax()) &
2929
])
@@ -37,7 +37,7 @@ program cnn_mnist
3737
label_digits(training_labels), &
3838
batch_size=16, &
3939
epochs=1, &
40-
optimizer=sgd(learning_rate=0.003) &
40+
optimizer=sgd(learning_rate=0.01) &
4141
)
4242

4343
print '(a,i2,a,f5.2,a)', 'Epoch ', n, ' done, Accuracy: ', accuracy( &
@@ -63,5 +63,5 @@ real function accuracy(net, x, y)
6363
accuracy = real(good) / size(x, dim=2)
6464
end function accuracy
6565

66-
end program cnn_mnist
66+
end program cnn_mnist_1d
6767

fpm.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name = "neural-fortran"
2-
version = "0.19.0"
2+
version = "0.21.0"
33
license = "MIT"
44
author = "Milan Curcic"
55
maintainer = "[email protected]"

src/nf.f90

+5
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,17 @@ module nf
44
use nf_layer, only: layer
55
use nf_layer_constructors, only: &
66
conv2d, dense, flatten, input, maxpool1d, maxpool2d, reshape, reshape2d, locally_connected_1d, &
7+
conv1d, &
78
conv2d, &
89
dense, &
910
dropout, &
11+
embedding, &
1012
flatten, &
1113
input, &
14+
layernorm, &
1215
linear2d, &
16+
locally_connected1d, &
17+
maxpool1d, &
1318
maxpool2d, &
1419
reshape, &
1520
self_attention

src/nf/nf_conv1d_layer.f90

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
module nf_conv1d_layer
2+
!! This modules provides a 1-d convolutional `conv1d` type.
3+
4+
use nf_activation, only: activation_function
5+
use nf_base_layer, only: base_layer
6+
implicit none
7+
8+
private
9+
public :: conv1d_layer
10+
11+
type, extends(base_layer) :: conv1d_layer
12+
13+
integer :: width
14+
integer :: height
15+
integer :: channels
16+
integer :: kernel_size
17+
integer :: filters
18+
19+
real, allocatable :: biases(:) ! size(filters)
20+
real, allocatable :: kernel(:,:,:) ! filters x channels x window
21+
real, allocatable :: output(:,:) ! filters x output_width
22+
real, allocatable :: z(:,:) ! kernel .dot. input + bias
23+
24+
real, allocatable :: dw(:,:,:) ! weight (kernel) gradients
25+
real, allocatable :: db(:) ! bias gradients
26+
real, allocatable :: gradient(:,:)
27+
28+
class(activation_function), allocatable :: activation
29+
30+
contains
31+
32+
procedure :: forward
33+
procedure :: backward
34+
procedure :: get_gradients
35+
procedure :: get_num_params
36+
procedure :: get_params
37+
procedure :: init
38+
procedure :: set_params
39+
40+
end type conv1d_layer
41+
42+
interface conv1d_layer
43+
module function conv1d_layer_cons(filters, kernel_size, activation) &
44+
result(res)
45+
!! `conv1d_layer` constructor function
46+
integer, intent(in) :: filters
47+
integer, intent(in) :: kernel_size
48+
class(activation_function), intent(in) :: activation
49+
type(conv1d_layer) :: res
50+
end function conv1d_layer_cons
51+
end interface conv1d_layer
52+
53+
interface
54+
55+
module subroutine init(self, input_shape)
56+
!! Initialize the layer data structures.
57+
!!
58+
!! This is a deferred procedure from the `base_layer` abstract type.
59+
class(conv1d_layer), intent(in out) :: self
60+
!! A `conv1d_layer` instance
61+
integer, intent(in) :: input_shape(:)
62+
!! Input layer dimensions
63+
end subroutine init
64+
65+
pure module subroutine forward(self, input)
66+
!! Apply a forward pass on the `conv1d` layer.
67+
class(conv1d_layer), intent(in out) :: self
68+
!! A `conv1d_layer` instance
69+
real, intent(in) :: input(:,:)
70+
!! Input data
71+
end subroutine forward
72+
73+
pure module subroutine backward(self, input, gradient)
74+
!! Apply a backward pass on the `conv1d` layer.
75+
class(conv1d_layer), intent(in out) :: self
76+
!! A `conv1d_layer` instance
77+
real, intent(in) :: input(:,:)
78+
!! Input data (previous layer)
79+
real, intent(in) :: gradient(:,:)
80+
!! Gradient (next layer)
81+
end subroutine backward
82+
83+
pure module function get_num_params(self) result(num_params)
84+
!! Get the number of parameters in the layer.
85+
class(conv1d_layer), intent(in) :: self
86+
!! A `conv1d_layer` instance
87+
integer :: num_params
88+
!! Number of parameters
89+
end function get_num_params
90+
91+
module function get_params(self) result(params)
92+
!! Return the parameters (weights and biases) of this layer.
93+
!! The parameters are ordered as weights first, biases second.
94+
class(conv1d_layer), intent(in), target :: self
95+
!! A `conv1d_layer` instance
96+
real, allocatable :: params(:)
97+
!! Parameters to get
98+
end function get_params
99+
100+
module function get_gradients(self) result(gradients)
101+
!! Return the gradients of this layer.
102+
!! The gradients are ordered as weights first, biases second.
103+
class(conv1d_layer), intent(in), target :: self
104+
!! A `conv1d_layer` instance
105+
real, allocatable :: gradients(:)
106+
!! Gradients to get
107+
end function get_gradients
108+
109+
module subroutine set_params(self, params)
110+
!! Set the parameters of the layer.
111+
class(conv1d_layer), intent(in out) :: self
112+
!! A `conv1d_layer` instance
113+
real, intent(in) :: params(:)
114+
!! Parameters to set
115+
end subroutine set_params
116+
117+
end interface
118+
119+
end module nf_conv1d_layer

0 commit comments

Comments
 (0)