@@ -30,8 +30,12 @@ module subroutine init(self, input_shape)
3030 integer , intent (in ) :: input_shape(:)
3131
3232 self % channels = input_shape(1 )
33- self % width = (input_shape(2 ) - self % kernel_size + 1 ) / self % stride(1 )
34- self % height = (input_shape(3 ) - self % kernel_size + 1 ) / self % stride(2 )
33+
34+ self % width = (input_shape(2 ) - self % kernel_size) / self % stride(1 ) + 1
35+ if (mod (input_shape(2 ) - self % kernel_size , self % stride(1 )) /= 0 ) self % width = self % width + 1
36+
37+ self % height = (input_shape(3 ) - self % kernel_size) / self % stride(2 ) + 1
38+ if (mod (input_shape(3 ) - self % kernel_size , self % stride(2 )) /= 0 ) self % height = self % height + 1
3539
3640 ! Output of shape filters x width x height
3741 allocate (self % output(self % filters, self % width, self % height))
@@ -89,22 +93,24 @@ pure module subroutine forward(self, input)
8993 iend = input_width - istart + 1
9094 jend = input_height - jstart + 1
9195
92- convolution: do concurrent(i = istart:iend, j = jstart:jend)
96+ ! convolution: do concurrent(i = istart:iend, j = jstart:jend)
97+ convolution: do concurrent(i = 1 :self % width, j = 1 :self% height)
9398
9499 ! Start and end indices of the input data on the filter window
95100 ! iws and jws are also coincidentally the indices of the output matrix
96- iws = i - half_window ! TODO kernel_width
97- iwe = i + half_window ! TODO kernel_width
98- jws = j - half_window ! TODO kernel_height
99- jwe = j + half_window ! TODO kernel_height
101+ iws = istart + self % stride(1 ) * (i-1 ) - half_window ! TODO kernel_width
102+ iwe = min (iws + 2 * half_window, input_width) ! TODO kernel_width
103+
104+ jws = jstart + self % stride(2 ) * (j-1 ) - half_window ! TODO kernel_height
105+ jwe = min (jws + 2 * half_window, input_height) ! TODO kernel_height
100106
101107 ! Compute the inner tensor product, sum(w_ij * x_ij), for each filter.
102108 do concurrent(n = 1 :self % filters)
103- self % z(n,iws,jws ) = sum (self % kernel(n,:,:,: ) * input(:,iws:iwe,jws:jwe))
109+ self % z(n,i,j ) = sum (self % kernel(n,:,1 :iwe - iws +1 , 1 :jwe - jws +1 ) * input(:,iws:iwe,jws:jwe))
104110 end do
105111
106112 ! Add bias to the inner product.
107- self % z(:,iws,jws ) = self % z(:,iws,jws ) + self % biases
113+ self % z(:,i,j ) = self % z(:,i,j ) + self % biases
108114
109115 end do convolution
110116
@@ -160,21 +166,28 @@ pure module subroutine backward(self, input, gradient)
160166 do concurrent( &
161167 n = 1 :self % filters, &
162168 k = 1 :self % channels, &
163- i = istart:iend, &
164- j = jstart:jend &
169+ i = 1 :self % width, &
170+ j = 1 :self % height &
171+ ! i = istart:iend, &
172+ ! j = jstart:jend &
165173 )
166174 ! Start and end indices of the input data on the filter window
167- iws = i - half_window ! TODO kernel_width
168- iwe = i + half_window ! TODO kernel_width
169- jws = j - half_window ! TODO kernel_height
170- jwe = j + half_window ! TODO kernel_height
175+ ! iws = i - half_window ! TODO kernel_width
176+ ! iwe = i + half_window ! TODO kernel_width
177+ ! jws = j - half_window ! TODO kernel_height
178+ ! jwe = j + half_window ! TODO kernel_height
179+ iws = istart + self % stride(1 ) * (i-1 ) - half_window ! TODO kernel_width
180+ iwe = min (iws + 2 * half_window, input_width) ! TODO kernel_width
181+
182+ jws = jstart + self % stride(2 ) * (j-1 ) - half_window ! TODO kernel_height
183+ jwe = min (jws + 2 * half_window, input_height) ! TODO kernel_height
171184
172185 ! dL/dw = sum(dL/dy * sigma'(z) * x)
173186 dw(n,k,:,:) = dw(n,k,:,:) + input(k,iws:iwe,jws:jwe) * gdz(n,iws:iwe,jws:jwe)
174187
175188 ! dL/dx = dL/dy * sigma'(z) .inner. w
176- self % gradient(k,i,j ) = self % gradient(k,i,j ) &
177- + sum ( gdz(n,iws:iwe,jws:jwe) * self % kernel(n,k,:,:) )
189+ self % gradient(k,iws:iwe,jws:jwe ) = self % gradient(k,iws:iwe,jws:jwe ) &
190+ + gdz(n,iws:iwe,jws:jwe) * self % kernel(n,k,1 :iwe - iws +1 , 1 :jwe - jws +1 )
178191
179192 end do
180193
0 commit comments