@@ -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 #-}
@@ -13,6 +14,7 @@
1314
1415module Grenade.Layers.Convolution (
1516 Convolution (..)
17+ , Convolution' (..)
1618 , randomConvolution
1719 , im2col
1820 , vid2col
@@ -65,6 +67,24 @@ data Convolution :: Nat -- ^ Number of channels, for the first layer this could
6567 -> !(L kernelFlattened filters) -- ^ The last kernel update (or momentum)
6668 -> Convolution channels filters kernelRows kernelColumns strideRows strideColumns
6769
70+data Convolution' :: Nat -- ^ Number of channels, for the first layer this could be RGB for instance.
71+ -> Nat -- ^ Number of filters, this is the number of channels output by the layer.
72+ -> Nat -- ^ The number of rows in the kernel filter
73+ -> Nat -- ^ The number of column in the kernel filter
74+ -> Nat -- ^ The row stride of the convolution filter
75+ -> Nat -- ^ The columns stride of the convolution filter
76+ -> * where
77+ Convolution' :: ( KnownNat channels
78+ , KnownNat filters
79+ , KnownNat kernelRows
80+ , KnownNat kernelColumns
81+ , KnownNat strideRows
82+ , KnownNat strideColumns
83+ , KnownNat kernelFlattened
84+ , kernelFlattened ~ (kernelRows * kernelColumns * channels))
85+ => !(L kernelFlattened filters) -- ^ The kernel filter gradient
86+ -> Convolution' channels filters kernelRows kernelColumns strideRows strideColumns
87+
6888instance Show (Convolution c f k k' s s') where
6989 show (Convolution a _) = renderConv a
7090 where
@@ -99,9 +119,16 @@ randomConvolution = do
99119 mm = konst 0
100120 return $ Convolution wN mm
101121
122+instance UpdateLayer (Convolution channels filters kernelRows kernelCols strideRows strideCols) where
123+ type Gradient (Convolution channels filters kernelRows kernelCols strideRows strideCols) = (Convolution' channels filters kernelRows kernelCols strideRows strideCols)
124+ runUpdate LearningParameters {..} (Convolution oldKernel oldMomentum) (Convolution' kernelGradient) =
125+ let newMomentum = konst learningMomentum * oldMomentum - konst learningRate * kernelGradient
126+ regulariser = konst (learningRegulariser * learningRate) * oldKernel
127+ newKernel = oldKernel + newMomentum - regulariser
128+ in Convolution newKernel newMomentum
129+
102130-- | A two dimentional image may have a convolution filter applied to it
103−instance ( Monad m
104− , KnownNat kernelRows
131+instance ( KnownNat kernelRows
105132 , KnownNat kernelCols
106133 , KnownNat filters
107134 , KnownNat strideRows
@@ -112,7 +139,7 @@ instance ( Monad m
112139 , KnownNat outputCols
113140 , ((outputRows - 1) * strideRows) ~ (inputRows - kernelRows)
114141 , ((outputCols - 1) * strideCols) ~ (inputCols - kernelCols)
115− ) => Layer m (Convolution 1 filters kernelRows kernelCols strideRows strideCols) ('D2 inputRows inputCols) ('D3 outputRows outputCols filters) where
142+ ) => Layer (Convolution 1 filters kernelRows kernelCols strideRows strideCols) ('D2 inputRows inputCols) ('D3 outputRows outputCols filters) where
116143 runForwards (Convolution kernel _) (S2D' input) =
117144 let ex = extract input
118145 ek = extract kernel
@@ -126,8 +153,8 @@ instance ( Monad m
126153 mt = c LA.<> ek
127154 r = col2vid 1 1 1 1 ox oy mt
128155 rs = fmap (fromJust . create) r
129− in return . S3D' $ mkVector rs
130− runBackards rate (Convolution kernel momentum) (S2D' input) (S3D' dEdy) =
156+ in S3D' $ mkVector rs
157+ runBackards (Convolution kernel _) (S2D' input) (S3D' dEdy) =
131158 let ex = extract input
132159 ix = fromIntegral $ natVal (Proxy :: Proxy inputRows)
133160 iy = fromIntegral $ natVal (Proxy :: Proxy inputCols)
@@ -145,20 +172,15 @@ instance ( Monad m
145172 vs = vid2col 1 1 1 1 ox oy eo
146173
147174 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−
152175 dW = vs LA.<> tr ek
153176
154177 xW = col2im kx ky sx sy ix iy dW
155− in return (Convolution rM mm, S2D' . fromJust . create $ xW)
178+ in (Convolution' kN, S2D' . fromJust . create $ xW)
156179
157180
158181-- | A three dimensional image (or 2d with many channels) can have
159182-- an appropriately sized convolution filter run across it.
160−instance ( Monad m
161− , KnownNat kernelRows
183+instance ( KnownNat kernelRows
162184 , KnownNat kernelCols
163185 , KnownNat filters
164186 , KnownNat strideRows
@@ -170,7 +192,7 @@ instance ( Monad m
170192 , KnownNat channels
171193 , ((outputRows - 1) * strideRows) ~ (inputRows - kernelRows)
172194 , ((outputCols - 1) * strideCols) ~ (inputCols - kernelCols)
173− ) => Layer m (Convolution channels filters kernelRows kernelCols strideRows strideCols) ('D3 inputRows inputCols channels) ('D3 outputRows outputCols filters) where
195+ ) => Layer (Convolution channels filters kernelRows kernelCols strideRows strideCols) ('D3 inputRows inputCols channels) ('D3 outputRows outputCols filters) where
174196 runForwards (Convolution kernel _) (S3D' input) =
175197 let ex = vecToList $ fmap extract input
176198 ek = extract kernel
@@ -186,8 +208,8 @@ instance ( Monad m
186208 mt = c LA.<> ek
187209 r = col2vid 1 1 1 1 ox oy mt
188210 rs = fmap (fromJust . create) r
189− in return . S3D' $ mkVector rs
190− runBackards rate (Convolution kernel momentum) (S3D' input) (S3D' dEdy) =
211+ in S3D' $ mkVector rs
212+ runBackards (Convolution kernel _) (S3D' input) (S3D' dEdy) =
191213 let ex = vecToList $ fmap extract input
192214 ix = fromIntegral $ natVal (Proxy :: Proxy inputRows)
193215 iy = fromIntegral $ natVal (Proxy :: Proxy inputCols)
@@ -205,14 +227,11 @@ instance ( Monad m
205227 vs = vid2col 1 1 1 1 ox oy eo
206228
207229 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
211230
212231 dW = vs LA.<> tr ek
213232
214233 xW = col2vid kx ky sx sy ix iy dW
215− in return (Convolution rM mm, S3D' . mkVector . fmap (fromJust . create) $ xW)
234+ in (Convolution' kN, S3D' . mkVector . fmap (fromJust . create) $ xW)
216235
217236im2col :: Int -> Int -> Int -> Int -> Matrix Double -> Matrix Double
218237im2col nrows ncols srows scols m =