Skip to content

Commit 4a944e7

Browse files
authored
Merge pull request #10 from jvdp1/development
Addition of 2 methods and of 2 examples
2 parents 7d81f7b + a28289f commit 4a944e7

File tree

9 files changed

+374
-33
lines changed

9 files changed

+374
-33
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
*.o
22
*.mod
33
build
4-
data/mnist/*.dat
4+
data/*/*.dat

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ foreach(execid mnist network_save network_sync set_activation_function)
7878
add_test(test_${execid} bin/test_${execid})
7979
endforeach()
8080

81-
foreach(execid mnist save_and_load simple sine)
81+
foreach(execid mnist montesinos_uni montesinos_multi save_and_load simple sine)
8282
add_executable(example_${execid} src/tests/example_${execid}.f90)
8383
target_link_libraries(example_${execid} neural ${LIBS})
8484
add_test(example_${execid} bin/example_${execid})

README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,45 @@ for example on 16 cores using [OpenCoarrays](https://github.com/sourceryinstitut
322322
$ cafrun -n 16 ./example_mnist
323323
```
324324

325+
### Montesinos-Lopez et al. (2018) univariate example
326+
327+
The Montesinos-Lopez et al. (2018) univariate example is extracted from the study:
328+
329+
```
330+
Montesinos-Lopez et al. 2018. Multi-environment genomic prediction of plant traits using deep learners with dense architecture. G3, 8, 3813-3828.
331+
```
332+
333+
This example uses the data from the dataset "Data\_Maize\_1to3", and was extracted using the R code in the Appendix of this paper.
334+
335+
336+
The Montesinos-Lopez univariate data is included with the repo and you will have to unpack it first:
337+
338+
```
339+
cd data/montesinos_uni
340+
tar xzvf montesinos_uni.tar.gz
341+
cd -
342+
```
343+
344+
### Montesinos-Lopez et al. (2018) multivariate example
345+
346+
The Montesinos-Lopez et al. (2018) multivariate example is extracted from the study:
347+
348+
```
349+
Montesinos-Lopez et al. 2018. Multi-trait, multi-environment deep learning modeling for genomic-enabled prediction of plant traits. G3, 8, 3829-3840.
350+
```
351+
352+
This example uses the data from the dataset "Data\_Maize\_set\_1", and was extracted using the R code in the Appendix B of this paper.
353+
354+
355+
The Montesinos-Lopez multivariate data is included with the repo and you will have to unpack it first:
356+
357+
```
358+
cd data/montesinos_multi
359+
tar xzvf montesinos_multi.tar.gz
360+
cd -
361+
```
362+
363+
325364
## Contributing
326365

327366
neural-fortran is currently a proof-of-concept with potential for

data/montesinos_multi.tar.gz

1.74 MB
Binary file not shown.

data/montesinos_uni.tar.gz

1.73 MB
Binary file not shown.

src/lib/mod_network.f90

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,18 @@ module mod_network
2323
procedure, public, pass(self) :: init
2424
procedure, public, pass(self) :: load
2525
procedure, public, pass(self) :: loss
26-
procedure, public, pass(self) :: output
26+
procedure, public, pass(self) :: output_batch
27+
procedure, public, pass(self) :: output_single
2728
procedure, public, pass(self) :: save
2829
procedure, public, pass(self) :: set_activation
2930
procedure, public, pass(self) :: sync
3031
procedure, public, pass(self) :: train_batch
32+
procedure, public, pass(self) :: train_epochs
3133
procedure, public, pass(self) :: train_single
3234
procedure, public, pass(self) :: update
3335

34-
generic, public :: train => train_batch, train_single
36+
generic, public :: output => output_batch, output_single
37+
generic, public :: train => train_batch, train_epochs, train_single
3538

3639
end type network_type
3740

@@ -159,7 +162,7 @@ pure real(rk) function loss(self, x, y)
159162
loss = 0.5 * sum((y - self % output(x))**2) / size(x)
160163
end function loss
161164

162-
pure function output(self, x) result(a)
165+
pure function output_single(self, x) result(a)
163166
! Use forward propagation to compute the output of the network.
164167
class(network_type), intent(in) :: self
165168
real(rk), intent(in) :: x(:)
@@ -171,7 +174,21 @@ pure function output(self, x) result(a)
171174
a = self % layers(n) % activation(matmul(transpose(layers(n-1) % w), a) + layers(n) % b)
172175
end do
173176
end associate
174-
end function output
177+
end function output_single
178+
179+
pure function output_batch(self, x) result(a)
180+
class(network_type), intent(in) :: self
181+
real(rk), intent(in) :: x(:,:)
182+
real(rk), allocatable :: a(:,:)
183+
184+
integer(ik) :: i
185+
186+
allocate(a(self%dims(size(self%dims)),size(x,dim=2)))
187+
do i = 1, size(x, dim=2)
188+
a(:,i)=self%output(x(:,i))
189+
enddo
190+
191+
end function output_batch
175192

176193
subroutine save(self, filename)
177194
! Saves the network to a file.
@@ -255,6 +272,37 @@ subroutine train_batch(self, x, y, eta)
255272

256273
end subroutine train_batch
257274

275+
subroutine train_epochs(self, x, y, eta,num_epochs,num_batch_size)
276+
!Performs the training for nun_epochs epochs with mini-bachtes of size equal to num_batch_size
277+
class(network_type), intent(in out) :: self
278+
integer(ik),intent(in)::num_epochs,num_batch_size
279+
real(rk), intent(in) :: x(:,:), y(:,:), eta
280+
281+
integer(ik)::i,n,nsamples,nbatch
282+
integer(ik)::batch_start,batch_end
283+
284+
real(rk)::pos
285+
286+
nsamples=size(y,dim=2)
287+
288+
nbatch=nsamples/num_batch_size
289+
290+
epoch: do n=1,num_epochs
291+
mini_batches: do i=1,nbatch
292+
293+
!pull a random mini-batch from the dataset
294+
call random_number(pos)
295+
batch_start=int(pos*(nsamples-num_batch_size+1))
296+
if(batch_start.eq.0)batch_start=1
297+
batch_end=batch_start+num_batch_size-1
298+
299+
call self%train(x(:,batch_start:batch_end),y(:,batch_start:batch_end),eta)
300+
301+
enddo mini_batches
302+
enddo epoch
303+
304+
end subroutine train_epochs
305+
258306
pure subroutine train_single(self, x, y, eta)
259307
! Trains a network using a single set of input data x and output data y,
260308
! and learning rate eta.

src/tests/example_mnist.f90

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,15 @@ program example_mnist
1212

1313
real(rk), allocatable :: tr_images(:,:), tr_labels(:)
1414
real(rk), allocatable :: te_images(:,:), te_labels(:)
15-
!real(rk), allocatable :: va_images(:,:), va_labels(:)
16-
real(rk), allocatable :: input(:,:), output(:,:)
1715

1816
type(network_type) :: net
1917

2018
integer(ik) :: i, n, num_epochs
21-
integer(ik) :: batch_size, batch_start, batch_end
22-
real(rk) :: pos
19+
integer(ik) :: batch_size
2320

2421
call load_mnist(tr_images, tr_labels, te_images, te_labels)
2522

26-
net = network_type([784, 10, 10])
23+
net = network_type([size(tr_images,dim=1), 10, size(label_digits(te_labels),dim=1)])
2724

2825
batch_size = 1000
2926
num_epochs = 10
@@ -33,28 +30,12 @@ program example_mnist
3330
net % accuracy(te_images, label_digits(te_labels)) * 100, ' %'
3431
end if
3532

36-
epochs: do n = 1, num_epochs
37-
mini_batches: do i = 1, size(tr_labels) / batch_size
38-
39-
! pull a random mini-batch from the dataset
40-
call random_number(pos)
41-
batch_start = int(pos * (size(tr_labels) - batch_size + 1))
42-
batch_end = batch_start + batch_size - 1
43-
44-
! prepare mini-batch
45-
input = tr_images(:,batch_start:batch_end)
46-
output = label_digits(tr_labels(batch_start:batch_end))
47-
48-
! train the network on the mini-batch
49-
call net % train(input, output, eta=3._rk)
50-
51-
end do mini_batches
52-
53-
if (this_image() == 1) then
54-
write(*, '(a,i2,a,f5.2,a)') 'Epoch ', n, ' done, Accuracy: ',&
55-
net % accuracy(te_images, label_digits(te_labels)) * 100, ' %'
56-
end if
33+
call net%train(tr_images,label_digits(tr_labels),3._rk,num_epochs,batch_size)
34+
35+
if (this_image() == 1) then
36+
write(*, '(a,f5.2,a)') 'Epochs done, Accuracy: ',&
37+
net % accuracy(te_images, label_digits(te_labels)) * 100, ' %'
38+
endif
5739

58-
end do epochs
5940

6041
end program example_mnist
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
program example_montesinos_multi
2+
use mod_kinds,only:ik,rk
3+
use mod_network,only:network_type
4+
implicit none
5+
integer(ik)::ny1_tr,ny2_tr,nx1_tr,nx2_tr
6+
integer(ik)::ny1_ts,ny2_ts,nx1_ts,nx2_ts
7+
8+
integer(ik)::batch_size,num_epochs
9+
10+
real(rk),allocatable::y_tr(:,:),x_tr(:,:)
11+
real(rk),allocatable::y_ts(:,:),x_ts(:,:)
12+
13+
type(network_type)::net
14+
15+
call readfile('../data/montesinos_multi/y_tr.dat',ny1_tr,ny2_tr,y_tr)
16+
call readfile('../data/montesinos_multi/x_tr.dat',nx1_tr,nx2_tr,x_tr)
17+
18+
net=network_type([nx1_tr,50,50,ny1_tr])
19+
20+
batch_size=50
21+
num_epochs=50
22+
23+
!training
24+
call net%train(x_tr,y_tr,3._rk,num_epochs,batch_size)
25+
26+
call net%sync(1)
27+
28+
!validation
29+
call readfile('../data/montesinos_multi/y_ts.dat',ny1_ts,ny2_ts,y_ts)
30+
call readfile('../data/montesinos_multi/x_ts.dat',nx1_ts,nx2_ts,x_ts)
31+
32+
if(this_image().eq.1)then
33+
write(*,*)'Correlation(s): ',corr_array(net%output(x_ts),y_ts)
34+
endif
35+
36+
contains
37+
38+
subroutine readfile(filename,n,m,array)
39+
character(len=*),intent(in)::filename
40+
integer(ik),intent(out)::n,m
41+
real(rk),allocatable,intent(out)::array(:,:)
42+
43+
integer(ik)::un,i,io
44+
45+
open(newunit=un,file=filename,status='old',action='read')
46+
call numlines(un,m)
47+
call numcol(un,n)
48+
49+
allocate(array(n,m))
50+
rewind(un)
51+
do i=1,m
52+
read(un,*,iostat=io)array(:,i)
53+
if(io.ne.0)exit
54+
enddo
55+
close(un)
56+
57+
end subroutine
58+
59+
pure function corr_array(array1,array2) result(a)
60+
real(rk),intent(in)::array1(:,:),array2(:,:)
61+
real(rk),allocatable::a(:)
62+
63+
integer(ik)::i,n
64+
65+
n=size(array1,dim=1)
66+
67+
allocate(a(n))
68+
a=0.0_rk
69+
do i=1,n
70+
a(i)=corr(array1(i,:),array2(i,:))
71+
enddo
72+
73+
end function
74+
75+
pure real(rk) function corr(array1,array2)
76+
real(rk),intent(in)::array1(:),array2(:)
77+
78+
real(rk)::mean1,mean2
79+
80+
!brute force
81+
82+
mean1=sum(array1)/size(array1)
83+
mean2=sum(array2)/size(array2)
84+
corr=dot_product(array1-mean1,array2-mean2)/sqrt(sum((array1-mean1)**2)*sum((array2-mean2)**2))
85+
86+
end function
87+
88+
subroutine numlines(unfile,n)
89+
implicit none
90+
integer::io
91+
integer,intent(in)::unfile
92+
integer,intent(out)::n
93+
rewind(unfile)
94+
n=0
95+
do
96+
read(unfile,*,iostat=io)
97+
if (io.ne.0) exit
98+
n=n+1
99+
enddo
100+
rewind(unfile)
101+
end subroutine
102+
103+
subroutine numcol(unfile,n)
104+
implicit none
105+
integer,intent(in)::unfile
106+
character(len=1000000)::a
107+
integer,intent(out)::n
108+
integer::curr,first,last,lena,stat,i
109+
rewind(unfile)
110+
read(unfile,"(a)")a
111+
curr=1;lena=len(a);n=0
112+
do
113+
first=0
114+
do i=curr,lena
115+
if (a(i:i) /= " ") then
116+
first=i
117+
exit
118+
endif
119+
enddo
120+
if (first == 0) exit
121+
curr=first+1
122+
last=0
123+
do i=curr,lena
124+
if (a(i:i) == " ") then
125+
last=i
126+
exit
127+
endif
128+
enddo
129+
if (last == 0) last=lena
130+
n=n+1
131+
curr=last+1
132+
enddo
133+
rewind(unfile)
134+
end subroutine
135+
136+
end program

0 commit comments

Comments
 (0)