@@ -2,6 +2,7 @@
22{-# LANGUAGE DataKinds #-}
33{-# LANGUAGE ScopedTypeVariables #-}
44{-# LANGUAGE StandaloneDeriving #-}
5+{-# LANGUAGE RecordWildCards #-}
56{-# LANGUAGE GADTs #-}
67{-# LANGUAGE TypeOperators #-}
78{-# LANGUAGE TypeFamilies #-}
@@ -65,6 +66,24 @@ data Convolution :: Nat -- ^ Number of channels, for the first layer this could
6566 -> !(L kernelFlattened filters) -- ^ The last kernel update (or momentum)
6667 -> Convolution channels filters kernelRows kernelColumns strideRows strideColumns
6768
69+data Convolution' :: Nat -- ^ Number of channels, for the first layer this could be RGB for instance.
70+ -> Nat -- ^ Number of filters, this is the number of channels output by the layer.
71+ -> Nat -- ^ The number of rows in the kernel filter
72+ -> Nat -- ^ The number of column in the kernel filter
73+ -> Nat -- ^ The row stride of the convolution filter
74+ -> Nat -- ^ The columns stride of the convolution filter
75+ -> * where
76+ Convolution' :: ( KnownNat channels
77+ , KnownNat filters
78+ , KnownNat kernelRows
79+ , KnownNat kernelColumns
80+ , KnownNat strideRows
81+ , KnownNat strideColumns
82+ , KnownNat kernelFlattened
83+ , kernelFlattened ~ (kernelRows * kernelColumns * channels))
84+ => !(L kernelFlattened filters) -- ^ The kernel filter gradient
85+ -> Convolution' channels filters kernelRows kernelColumns strideRows strideColumns
86+
6887instance Show (Convolution c f k k' s s') where
6988 show (Convolution a _) = renderConv a
7089 where
@@ -99,6 +118,22 @@ randomConvolution = do
99118 mm = konst 0
100119 return $ Convolution wN mm
101120
121+instance ( Monad m
122+ , KnownNat kernelRows
123+ , KnownNat kernelCols
124+ , KnownNat channels
125+ , KnownNat filters
126+ , KnownNat strideRows
127+ , KnownNat strideCols
128+ , kernelFlattened ~ (kernelRows * kernelColumns * channels)
129+ ) => UpdateLayer m (Convolution channels filters kernelRows kernelCols strideRows strideCols) where
130+ type Gradient (Convolution channels filters kernelRows kernelCols strideRows strideCols) = (Convolution' channels filters kernelRows kernelCols strideRows strideCols)
131+ runUpdate LearningParameters {..} (Convolution oldKernel oldMomentum) (Convolution' kernelGradient) = do
132+ let newMomentum = konst learningMomentum * oldMomentum - konst learningRate * kernelGradient
133+ regulariser = konst (learningRegulariser * learningRate) * oldKernel
134+ newKernel = oldKernel + newMomentum - regulariser
135+ return $ Convolution newKernel newMomentum
136+
102137-- | A two dimentional image may have a convolution filter applied to it
103138instance ( Monad m
104139 , KnownNat kernelRows
@@ -127,7 +162,7 @@ instance ( Monad m
127162 r = col2vid 1 1 1 1 ox oy mt
128163 rs = fmap (fromJust . create) r
129164 in return . S3D' $ mkVector rs
130− runBackards rate (Convolution kernel momentum) (S2D' input) (S3D' dEdy) =
165+ runBackards (Convolution kernel _) (S2D' input) (S3D' dEdy) =
131166 let ex = extract input
132167 ix = fromIntegral $ natVal (Proxy :: Proxy inputRows)
133168 iy = fromIntegral $ natVal (Proxy :: Proxy inputCols)
@@ -145,14 +180,10 @@ instance ( Monad m
145180 vs = vid2col 1 1 1 1 ox oy eo
146181
147182 kN = fromJust . create $ tr c LA.<> vs
148− mm = momentum * 0.9 - konst rate * kN
149− wd = konst (0.0001 * rate) * kernel
150− rM = kernel + mm - wd
151−
152183 dW = vs LA.<> tr ek
153184
154185 xW = col2im kx ky sx sy ix iy dW
155− in return (Convolution rM mm, S2D' . fromJust . create $ xW)
186+ in return (Convolution' kN, S2D' . fromJust . create $ xW)
156187
157188
158189-- | A three dimensional image (or 2d with many channels) can have
@@ -187,7 +218,7 @@ instance ( Monad m
187218 r = col2vid 1 1 1 1 ox oy mt
188219 rs = fmap (fromJust . create) r
189220 in return . S3D' $ mkVector rs
190− runBackards rate (Convolution kernel momentum) (S3D' input) (S3D' dEdy) =
221+ runBackards (Convolution kernel _) (S3D' input) (S3D' dEdy) =
191222 let ex = vecToList $ fmap extract input
192223 ix = fromIntegral $ natVal (Proxy :: Proxy inputRows)
193224 iy = fromIntegral $ natVal (Proxy :: Proxy inputCols)
@@ -205,14 +236,11 @@ instance ( Monad m
205236 vs = vid2col 1 1 1 1 ox oy eo
206237
207238 kN = fromJust . create $ tr c LA.<> vs
208− mm = momentum * 0.9 - konst rate * kN
209− wd = konst (0.0005 * rate) * kernel
210− rM = kernel + mm - wd
211239
212240 dW = vs LA.<> tr ek
213241
214242 xW = col2vid kx ky sx sy ix iy dW
215− in return (Convolution rM mm, S3D' . mkVector . fmap (fromJust . create) $ xW)
243+ in return (Convolution' kN, S3D' . mkVector . fmap (fromJust . create) $ xW)
216244
217245im2col :: Int -> Int -> Int -> Int -> Matrix Double -> Matrix Double
218246im2col nrows ncols srows scols m =