@@ -27,7 +27,7 @@ module subroutine init(self, input_shape)
2727 integer , intent (in ) :: input_shape(:)
2828
2929 self % channels = input_shape(1 )
30- self % width = input_shape(2 ) - self % kernel_size + 1
30+ self % width = ( input_shape(2 ) - self % kernel_size + 1 ) / self % stride
3131
3232 ! Output of shape: filters x width
3333 allocate (self % output(self % filters, self % width))
@@ -70,12 +70,12 @@ pure module subroutine forward(self, input)
7070 do j = 1 , self % width
7171 ! Compute the input window corresponding to output index j.
7272 ! In forward: center index = j + half_window, so window = indices j to j+kernel_size-1.
73- iws = j
74- iwe = j + self % kernel_size - 1
73+ iws = self % stride * (j -1 ) + 1
74+ iwe = max (iws + self % kernel_size - 1 , input_width)
7575
7676 ! For each filter, compute the convolution (inner product over channels and kernel width).
7777 do concurrent (n = 1 :self % filters)
78- self % z(n, j) = sum (self % kernel(n,:,: ) * input(:,iws:iwe))
78+ self % z(n, j) = sum (self % kernel(n,:,1 :iwe - iws +1 ) * input(:,iws:iwe))
7979 end do
8080
8181 ! Add the bias for each filter.
@@ -94,7 +94,7 @@ pure module subroutine backward(self, input, gradient)
9494 real , intent (in ) :: input(:,:)
9595 real , intent (in ) :: gradient(:,:)
9696
97- integer :: input_channels, input_width, output_width
97+ integer :: input_channels, input_width
9898 integer :: j, n, k
9999 integer :: iws, iwe
100100
@@ -106,7 +106,6 @@ pure module subroutine backward(self, input, gradient)
106106 ! Determine dimensions.
107107 input_channels = size (input, dim= 1 )
108108 input_width = size (input, dim= 2 )
109- output_width = self % width ! Note: output_width = input_width - kernel_size + 1
110109
111110 !- -- Compute the local gradient gdz = (dL/dy) * sigma'(z) for each output.
112111 gdz = gradient * self % activation % eval_prime(self % z)
@@ -122,14 +121,15 @@ pure module subroutine backward(self, input, gradient)
122121 ! In the forward pass the window for output index j was:
123122 ! iws = j, iwe = j + kernel_size - 1.
124123 do n = 1 , self % filters
125- do j = 1 , output_width
126- iws = j
127- iwe = j + self % kernel_size - 1
124+ do j = 1 , self % width
125+ iws = self % stride * (j-1 ) + 1
126+ iwe = max (iws + self % kernel_size - 1 , input_width)
127+
128128 do k = 1 , self % channels
129129 ! Weight gradient: accumulate contribution from the input window.
130- dw_local(n,k,: ) = dw_local(n,k,: ) + input(k,iws:iwe) * gdz(n,j)
130+ dw_local(n,k,1 :iws - iwe +1 ) = dw_local(n,k,1 :iws - iwe +1 ) + input(k,iws:iwe) * gdz(n,j)
131131 ! Input gradient: propagate gradient back to the input window.
132- self % gradient(k,iws:iwe) = self % gradient(k,iws:iwe) + self % kernel(n,k,: ) * gdz(n,j)
132+ self % gradient(k,iws:iwe) = self % gradient(k,iws:iwe) + self % kernel(n,k,1 :iws - iwe +1 ) * gdz(n,j)
133133 end do
134134 end do
135135 end do
0 commit comments