on master help sign in
Tests
670f2d9Huw Campbell
grenade.cabal+3−1
@@ -40,7 +40,6 @@ library
40 Grenade.Core.Shape
40 Grenade.Core.Shape
41 Grenade.Layers.Crop
41 Grenade.Layers.Crop
42 Grenade.Layers.Convolution
42 Grenade.Layers.Convolution
43− Grenade.Layers.Convolution.Internal
44 Grenade.Layers.Dropout
43 Grenade.Layers.Dropout
45 Grenade.Layers.FullyConnected
44 Grenade.Layers.FullyConnected
46 Grenade.Layers.Flatten
45 Grenade.Layers.Flatten
@@ -51,6 +50,9 @@ library
51 Grenade.Layers.Pad
50 Grenade.Layers.Pad
52 Grenade.Layers.Pooling
51 Grenade.Layers.Pooling
53
52
53+ Grenade.Layers.Internal.Convolution
54+ Grenade.Layers.Internal.Pooling
55+
54
56
55executable feedforward
57executable feedforward
56 ghc-options: -Wall -threaded -O2
58 ghc-options: -Wall -threaded -O2
src/Grenade/Layers/Convolution.hs+9−13
@@ -31,7 +31,7 @@ import Numeric.LinearAlgebra.Static hiding ((|||), build, toRows)
31import Grenade.Core.Network
31import Grenade.Core.Network
32import Grenade.Core.Shape
32import Grenade.Core.Shape
33import Grenade.Core.Vector
33import Grenade.Core.Vector
34−import Grenade.Layers.Convolution.Internal
34+import Grenade.Layers.Internal.Convolution
35
35
36-- | A convolution layer for a neural network.
36-- | A convolution layer for a neural network.
37-- This uses the im2col convolution trick popularised by Caffe, which essentially turns the
37-- This uses the im2col convolution trick popularised by Caffe, which essentially turns the
@@ -149,15 +149,13 @@ instance ( KnownNat kernelRows
149 runForwards (Convolution kernel _) (S2D' input) =
149 runForwards (Convolution kernel _) (S2D' input) =
150 let ex = extract input
150 let ex = extract input
151 ek = extract kernel
151 ek = extract kernel
152− ix = fromIntegral $ natVal (Proxy :: Proxy inputRows)
153− iy = fromIntegral $ natVal (Proxy :: Proxy inputCols)
154 kx = fromIntegral $ natVal (Proxy :: Proxy kernelRows)
152 kx = fromIntegral $ natVal (Proxy :: Proxy kernelRows)
155 ky = fromIntegral $ natVal (Proxy :: Proxy kernelCols)
153 ky = fromIntegral $ natVal (Proxy :: Proxy kernelCols)
156 sx = fromIntegral $ natVal (Proxy :: Proxy strideRows)
154 sx = fromIntegral $ natVal (Proxy :: Proxy strideRows)
157 sy = fromIntegral $ natVal (Proxy :: Proxy strideCols)
155 sy = fromIntegral $ natVal (Proxy :: Proxy strideCols)
158 ox = fromIntegral $ natVal (Proxy :: Proxy outputRows)
156 ox = fromIntegral $ natVal (Proxy :: Proxy outputRows)
159 oy = fromIntegral $ natVal (Proxy :: Proxy outputCols)
157 oy = fromIntegral $ natVal (Proxy :: Proxy outputCols)
160− c = im2colUnsafe kx ky sx sy ix iy ex
158+ c = im2colUnsafe kx ky sx sy ex
161 mt = c LA.<> ek
159 mt = c LA.<> ek
162 r = col2vidUnsafe 1 1 1 1 ox oy mt
160 r = col2vidUnsafe 1 1 1 1 ox oy mt
163 rs = fmap (fromJust . create) r
161 rs = fmap (fromJust . create) r
@@ -173,14 +171,13 @@ instance ( KnownNat kernelRows
173 sy = fromIntegral $ natVal (Proxy :: Proxy strideCols)
171 sy = fromIntegral $ natVal (Proxy :: Proxy strideCols)
174 ox = fromIntegral $ natVal (Proxy :: Proxy outputRows)
172 ox = fromIntegral $ natVal (Proxy :: Proxy outputRows)
175 oy = fromIntegral $ natVal (Proxy :: Proxy outputCols)
173 oy = fromIntegral $ natVal (Proxy :: Proxy outputCols)
176− fl = fromIntegral $ natVal (Proxy :: Proxy filters)
177
174
178− c = im2colUnsafe kx ky sx sy ix iy ex
175+ c = im2colUnsafe kx ky sx sy ex
179
176
180 eo = vecToList $ fmap extract dEdy
177 eo = vecToList $ fmap extract dEdy
181 ek = extract kernel
178 ek = extract kernel
182
179
183− vs = vid2colUnsafe fl 1 1 1 1 ox oy eo
180+ vs = vid2colUnsafe 1 1 1 1 ox oy eo
184
181
185 kN = fromJust . create $ tr c LA.<> vs
182 kN = fromJust . create $ tr c LA.<> vs
186 dW = vs LA.<> tr ek
183 dW = vs LA.<> tr ek
@@ -216,8 +213,8 @@ instance ( KnownNat kernelRows
216 sy = fromIntegral $ natVal (Proxy :: Proxy strideCols)
213 sy = fromIntegral $ natVal (Proxy :: Proxy strideCols)
217 ox = fromIntegral $ natVal (Proxy :: Proxy outputRows)
214 ox = fromIntegral $ natVal (Proxy :: Proxy outputRows)
218 oy = fromIntegral $ natVal (Proxy :: Proxy outputCols)
215 oy = fromIntegral $ natVal (Proxy :: Proxy outputCols)
219− ch = fromIntegral $ natVal (Proxy :: Proxy channels)
216+
220− c = vid2colUnsafe ch kx ky sx sy ix iy ex
217+ c = vid2colUnsafe kx ky sx sy ix iy ex
221 mt = c LA.<> ek
218 mt = c LA.<> ek
222 r = col2vidUnsafe 1 1 1 1 ox oy mt
219 r = col2vidUnsafe 1 1 1 1 ox oy mt
223 rs = fmap (fromJust . create) r
220 rs = fmap (fromJust . create) r
@@ -232,14 +229,13 @@ instance ( KnownNat kernelRows
232 sy = fromIntegral $ natVal (Proxy :: Proxy strideCols)
229 sy = fromIntegral $ natVal (Proxy :: Proxy strideCols)
233 ox = fromIntegral $ natVal (Proxy :: Proxy outputRows)
230 ox = fromIntegral $ natVal (Proxy :: Proxy outputRows)
234 oy = fromIntegral $ natVal (Proxy :: Proxy outputCols)
231 oy = fromIntegral $ natVal (Proxy :: Proxy outputCols)
235− ch = fromIntegral $ natVal (Proxy :: Proxy channels)
232+
236− fl = fromIntegral $ natVal (Proxy :: Proxy filters)
237− c = vid2colUnsafe ch kx ky sx sy ix iy ex
233+ c = vid2colUnsafe kx ky sx sy ix iy ex
238
234
239 eo = vecToList $ fmap extract dEdy
235 eo = vecToList $ fmap extract dEdy
240 ek = extract kernel
236 ek = extract kernel
241
237
242− vs = vid2colUnsafe fl 1 1 1 1 ox oy eo
238+ vs = vid2colUnsafe 1 1 1 1 ox oy eo
243
239
244 kN = fromJust . create $ tr c LA.<> vs
240 kN = fromJust . create $ tr c LA.<> vs
245
241
src/Grenade/Layers/Convolution/Internal.hs → src/Grenade/Layers/Internal/Convolution.hsrenamed+42−52
@@ -1,4 +1,4 @@
1−module Grenade.Layers.Convolution.Internal (
1+module Grenade.Layers.Internal.Convolution (
2 im2col
2 im2col
3-- , im2colUnsafe
3-- , im2colUnsafe
4 , vid2col
4 , vid2col
@@ -72,7 +72,7 @@ fittingStart width kernel steps =
72 | left + kernel == width
72 | left + kernel == width
73 = [left]
73 = [left]
74 | otherwise
74 | otherwise
75− = error "Kernel and step do not fit in matrix."
75+ = [] -- error "Kernel and step do not fit in matrix."
76 in go 0
76 in go 0
77
77
78col2imFit :: [(Int,Int)] -> Int -> Int -> Int -> Int -> Matrix Double -> Matrix Double
78col2imFit :: [(Int,Int)] -> Int -> Int -> Int -> Int -> Matrix Double -> Matrix Double
@@ -119,14 +119,9 @@ col2imFit starts krows kcols drows dcols m =
119-- }
119-- }
120-- }
120-- }
121
121
122−
123−-- let starts = fittingStart (cols m) (krows * kcols) (krows * kcols)
124−-- r = rows m
125−-- mats = fmap (\s -> subMatrix (0,s) (r, krows * kcols) m) starts
126−-- in parMap rseq (col2imUnsafe krows kcols srows scols drows dcols) mats
127−
128col2imUnsafe :: Int -> Int -> Int -> Int -> Int -> Int -> Matrix Double -> Matrix Double
122col2imUnsafe :: Int -> Int -> Int -> Int -> Int -> Int -> Matrix Double -> Matrix Double
129col2imUnsafe kernelRows kernelColumns strideRows strideColumns destinationRows destinationCols columnMatrix = U.runSTMatrix $ do
123col2imUnsafe kernelRows kernelColumns strideRows strideColumns destinationRows destinationCols columnMatrix = U.runSTMatrix $ do
124+
130 let columnMatrixRows = rows columnMatrix
125 let columnMatrixRows = rows columnMatrix
131
126
132 dataIm <- U.newMatrix 0 destinationRows destinationCols
127 dataIm <- U.newMatrix 0 destinationRows destinationCols
@@ -134,15 +129,15 @@ col2imUnsafe kernelRows kernelColumns strideRows strideColumns destinationRows d
134 offsetR <- newSTRef 0
129 offsetR <- newSTRef 0
135 offsetC <- newSTRef 0
130 offsetC <- newSTRef 0
136
131
137− forM_ [0 .. columnMatrixRows - 1] $ \ir -> do
132+ forM_ [0 .. columnMatrixRows - 1] $ \inputRow -> do
138− inputColumn <- newSTRef 0
133+ inputColumnRef <- newSTRef 0
139 forM_ [0 .. kernelRows -1] $ \kr ->
134 forM_ [0 .. kernelRows -1] $ \kr ->
140 forM_ [0 .. kernelColumns -1] $ \kc -> do
135 forM_ [0 .. kernelColumns -1] $ \kc -> do
141− ic <- readSTRef inputColumn
136+ inputColumn <- readSTRef inputColumnRef
142− offsetR' <- readSTRef offsetR
137+ offsetR' <- readSTRef offsetR
143− offsetC' <- readSTRef offsetC
138+ offsetC' <- readSTRef offsetC
144− U.modifyMatrix dataIm (kr + offsetR') (kc + offsetC') (+ atIndex columnMatrix (ir,ic))
139+ U.modifyMatrix dataIm (kr + offsetR') (kc + offsetC') (+ U.atM' columnMatrix inputRow inputColumn)
145− modifySTRef inputColumn (+1)
140+ modifySTRef inputColumnRef (+1)
146
141
147 offsetC' <- readSTRef offsetC
142 offsetC' <- readSTRef offsetC
148 if offsetC' + kernelColumns < destinationCols
143 if offsetC' + kernelColumns < destinationCols
@@ -158,12 +153,12 @@ col2vidUnsafe kernelRows kernelColumns strideRows strideColumns destinationRows
158
153
159 dataIms <- traverse (\_ -> U.newMatrix 0 destinationRows destinationCols) [0 .. filters-1]
154 dataIms <- traverse (\_ -> U.newMatrix 0 destinationRows destinationCols) [0 .. filters-1]
160
155
161− offsetR <- newSTRef 0
162− offsetC <- newSTRef 0
163 offsetM <- newSTRef 0
156 offsetM <- newSTRef 0
164
157
165 forM_ dataIms $ \dataIm -> do
158 forM_ dataIms $ \dataIm -> do
159+ offsetR <- newSTRef 0
160+ offsetC <- newSTRef 0
166− offsetM' <- readSTRef offsetM
161+ offsetM' <- readSTRef offsetM
167 forM_ [0 .. columnMatrixRows - 1] $ \ir -> do
162 forM_ [0 .. columnMatrixRows - 1] $ \ir -> do
168 inputColumn <- newSTRef 0
163 inputColumn <- newSTRef 0
169 forM_ [0 .. kernelRows -1] $ \kr ->
164 forM_ [0 .. kernelRows -1] $ \kr ->
@@ -171,7 +166,7 @@ col2vidUnsafe kernelRows kernelColumns strideRows strideColumns destinationRows
171 ic <- readSTRef inputColumn
166 ic <- readSTRef inputColumn
172 offsetR' <- readSTRef offsetR
167 offsetR' <- readSTRef offsetR
173 offsetC' <- readSTRef offsetC
168 offsetC' <- readSTRef offsetC
174− U.modifyMatrix dataIm (kr + offsetR') (kc + offsetC') (+ atIndex columnMatrix (ir, ic + offsetM'))
169+ U.modifyMatrix dataIm (kr + offsetR') (kc + offsetC') (+ U.atM' columnMatrix ir (ic + offsetM'))
175 modifySTRef inputColumn (+1)
170 modifySTRef inputColumn (+1)
176
171
177 offsetC' <- readSTRef offsetC
172 offsetC' <- readSTRef offsetC
@@ -179,60 +174,55 @@ col2vidUnsafe kernelRows kernelColumns strideRows strideColumns destinationRows
179 then modifySTRef offsetC (+ strideColumns)
174 then modifySTRef offsetC (+ strideColumns)
180 else writeSTRef offsetC 0 >> modifySTRef offsetR (+ strideRows)
175 else writeSTRef offsetC 0 >> modifySTRef offsetR (+ strideRows)
181
176
182− writeSTRef offsetR 0
183− writeSTRef offsetC 0
184 modifySTRef offsetM (+ (kernelRows * kernelColumns))
177 modifySTRef offsetM (+ (kernelRows * kernelColumns))
185
178
186− traverse U.freezeMatrix dataIms
179+ traverse U.unsafeFreezeMatrix dataIms
187
180
188−vid2colUnsafe :: Int -> Int -> Int -> Int -> Int -> Int -> Int -> [Matrix Double] -> Matrix Double
181+vid2colUnsafe :: Int -> Int -> Int -> Int -> Int -> Int -> [Matrix Double] -> Matrix Double
189−vid2colUnsafe channels kernelRows kernelColumns striderows stridecols vidrows vidcols dataVid = U.runSTMatrix $ do
182+vid2colUnsafe kernelRows kernelColumns striderows stridecols vidrows vidcols dataVid = U.runSTMatrix $ do
190 let starts = fittingStarts vidrows kernelRows striderows vidcols kernelColumns stridecols
183 let starts = fittingStarts vidrows kernelRows striderows vidcols kernelColumns stridecols
191− matWidth = kernelRows * kernelColumns
184+ kernelSize = kernelRows * kernelColumns
192− destinationRows = 1 + (vidrows - kernelRows) `div` striderows
185+ numberOfPatches = length starts
193− destinationCols = 1 + (vidcols - kernelColumns) `div` stridecols
186+ channels = length dataVid
194− destinationSize = destinationRows * destinationCols
195
187
196− dataCol <- U.newMatrix 0 destinationSize (channels * matWidth)
188+ dataCol <- U.newMatrix 0 numberOfPatches (channels * kernelSize)
197
189
198 offsetC <- newSTRef 0
190 offsetC <- newSTRef 0
199
191
200 forM_ dataVid $ \dataIm -> do
192 forM_ dataVid $ \dataIm -> do
201− inputRow <- newSTRef 0
193+ inputRowRef <- newSTRef 0
202 offsetC' <- readSTRef offsetC
194 offsetC' <- readSTRef offsetC
203 forM_ starts $ \(startRow, startCol) -> do
195 forM_ starts $ \(startRow, startCol) -> do
204− inputColumn <- newSTRef 0
196+ inputColumnRef <- newSTRef 0
205− inputRow' <- readSTRef inputRow
197+ inputRow <- readSTRef inputRowRef
206 forM_ [0 .. kernelRows -1] $ \kr ->
198 forM_ [0 .. kernelRows -1] $ \kr ->
207 forM_ [0 .. kernelColumns -1] $ \kc -> do
199 forM_ [0 .. kernelColumns -1] $ \kc -> do
208− inputColumn' <- readSTRef inputColumn
200+ inputColumn <- readSTRef inputColumnRef
209− U.modifyMatrix dataCol inputRow' (inputColumn' + offsetC') (+ atIndex dataIm (kr + startRow, kc + startCol))
201+ U.modifyMatrix dataCol inputRow (inputColumn + offsetC') (+ U.atM' dataIm (kr + startRow) (kc + startCol))
210− modifySTRef inputColumn (+1)
202+ modifySTRef inputColumnRef (+1)
211− modifySTRef inputRow (+1)
203+ modifySTRef inputRowRef (+1)
212
204
213− modifySTRef offsetC (+ matWidth)
205+ modifySTRef offsetC (+ kernelSize)
214
206
215 return dataCol
207 return dataCol
216
208
217−im2colUnsafe :: Int -> Int -> Int -> Int -> Int -> Int -> Matrix Double -> Matrix Double
209+im2colUnsafe :: Int -> Int -> Int -> Int -> Matrix Double -> Matrix Double
218−im2colUnsafe kernelRows kernelColumns striderows stridecols vidrows vidcols dataIm = U.runSTMatrix $ do
210+im2colUnsafe kernelRows kernelColumns striderows stridecols dataIm = U.runSTMatrix $ do
219− let starts = fittingStarts vidrows kernelRows striderows vidcols kernelColumns stridecols
211+ let starts = fittingStarts (rows dataIm) kernelRows striderows (cols dataIm) kernelColumns stridecols
220− matWidth = kernelRows * kernelColumns
212+ kernelSize = kernelRows * kernelColumns
221− destinationRows = 1 + (vidrows - kernelRows) `div` striderows
213+ numberOfPatches = length starts
222− destinationCols = 1 + (vidcols - kernelColumns) `div` stridecols
223− destinationSize = destinationRows * destinationCols
224
214
225− dataCol <- U.newMatrix 0 destinationSize matWidth
215+ dataCol <- U.newMatrix 0 numberOfPatches kernelSize
226
216
227− inputRow <- newSTRef 0
217+ inputRowRef <- newSTRef 0
228 forM_ starts $ \(startRow, startCol) -> do
218 forM_ starts $ \(startRow, startCol) -> do
229− inputColumn <- newSTRef 0
219+ inputColumnRef <- newSTRef 0
230− inputRow' <- readSTRef inputRow
220+ inputRow <- readSTRef inputRowRef
231 forM_ [0 .. kernelRows -1] $ \kr ->
221 forM_ [0 .. kernelRows -1] $ \kr ->
232 forM_ [0 .. kernelColumns -1] $ \kc -> do
222 forM_ [0 .. kernelColumns -1] $ \kc -> do
233− inputColumn' <- readSTRef inputColumn
223+ inputColumn <- readSTRef inputColumnRef
234− U.modifyMatrix dataCol inputRow' inputColumn' (+ atIndex dataIm (kr + startRow, kc + startCol))
224+ U.modifyMatrix dataCol inputRow inputColumn (+ U.atM' dataIm (kr + startRow) (kc + startCol))
235− modifySTRef inputColumn (+1)
225+ modifySTRef inputColumnRef (+1)
236− modifySTRef inputRow (+1)
226+ modifySTRef inputRowRef (+1)
237
227
238 return dataCol
228 return dataCol
src/Grenade/Layers/Internal/Pooling.hsnew file+48
@@ -0,0 +1,48 @@
1+module Grenade.Layers.Internal.Pooling (
2+ poolForward
3+ , poolBackward
4+ , poolForwardList
5+ , poolBackwardList
6+ ) where
7+
8+import Numeric.LinearAlgebra hiding ( uniformSample, konst )
9+import qualified Numeric.LinearAlgebra as LA
10+
11+import Grenade.Layers.Internal.Convolution
12+
13+poolForward :: Int -> Int -> Int -> Int -> Int -> Int -> Matrix Double -> Matrix Double
14+poolForward nrows ncols srows scols outputRows outputCols m =
15+ let starts = fittingStarts (rows m) nrows srows (cols m) ncols scols
16+ in poolForwardFit starts nrows ncols outputRows outputCols m
17+
18+poolForwardList :: Functor f => Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> f (Matrix Double) -> f (Matrix Double)
19+poolForwardList nrows ncols srows scols inRows inCols outputRows outputCols ms =
20+ let starts = fittingStarts inRows nrows srows inCols ncols scols
21+ in poolForwardFit starts nrows ncols outputRows outputCols <$> ms
22+
23+poolForwardFit :: [(Int,Int)] -> Int -> Int -> Int -> Int -> Matrix Double -> Matrix Double
24+poolForwardFit starts nrows ncols _ outputCols m =
25+ let els = fmap (\start -> maxElement $ subMatrix start (nrows, ncols) m) starts
26+ in LA.matrix outputCols els
27+
28+poolBackward :: Int -> Int -> Int -> Int -> Matrix Double -> Matrix Double -> Matrix Double
29+poolBackward krows kcols srows scols inputMatrix gradientMatrix =
30+ let inRows = rows inputMatrix
31+ inCols = cols inputMatrix
32+ starts = fittingStarts inRows krows srows inCols kcols scols
33+ in poolBackwardFit starts krows kcols inputMatrix gradientMatrix
34+
35+poolBackwardList :: Functor f => Int -> Int -> Int -> Int -> Int -> Int -> f (Matrix Double, Matrix Double) -> f (Matrix Double)
36+poolBackwardList krows kcols srows scols inRows inCols inputMatrices =
37+ let starts = fittingStarts inRows krows srows inCols kcols scols
38+ in uncurry (poolBackwardFit starts krows kcols) <$> inputMatrices
39+
40+poolBackwardFit :: [(Int,Int)] -> Int -> Int -> Matrix Double -> Matrix Double -> Matrix Double
41+poolBackwardFit starts krows kcols inputMatrix gradientMatrix =
42+ let inRows = rows inputMatrix
43+ inCols = cols inputMatrix
44+ inds = fmap (\start -> maxIndex $ subMatrix start (krows, kcols) inputMatrix) starts
45+ grads = toList $ flatten gradientMatrix
46+ grads' = zip3 starts grads inds
47+ accums = fmap (\((stx',sty'),grad,(inx, iny)) -> ((stx' + inx, sty' + iny), grad)) grads'
48+ in accum (LA.konst 0 (inRows, inCols)) (+) accums
src/Grenade/Layers/Pooling.hs+2−45
@@ -24,10 +24,8 @@ import GHC.TypeLits
24import Grenade.Core.Network
24import Grenade.Core.Network
25import Grenade.Core.Shape
25import Grenade.Core.Shape
26import Grenade.Core.Vector
26import Grenade.Core.Vector
27−import Grenade.Layers.Convolution.Internal
27+import Grenade.Layers.Internal.Pooling
28
28
29−import Numeric.LinearAlgebra hiding (uniformSample)
30−import qualified Numeric.LinearAlgebra as LA
31import Numeric.LinearAlgebra.Static as LAS hiding ((|||), build, toRows)
29import Numeric.LinearAlgebra.Static as LAS hiding ((|||), build, toRows)
32
30
33-- | A pooling layer for a neural network.
31-- | A pooling layer for a neural network.
@@ -37,16 +35,12 @@ import Numeric.LinearAlgebra.Static as LAS hiding ((|||), build, toRow
37-- The kernel size dictates which input and output sizes will "fit". Fitting the equation:
35-- The kernel size dictates which input and output sizes will "fit". Fitting the equation:
38-- `out = (in - kernel) / stride + 1` for both dimensions.
36-- `out = (in - kernel) / stride + 1` for both dimensions.
39--
37--
40−data Pooling :: Nat
38+data Pooling :: Nat -> Nat -> Nat -> Nat -> * where
41− -> Nat
42− -> Nat
43− -> Nat -> * where
44 Pooling :: Pooling kernelRows kernelColumns strideRows strideColumns
39 Pooling :: Pooling kernelRows kernelColumns strideRows strideColumns
45
40
46instance Show (Pooling k k' s s') where
41instance Show (Pooling k k' s s') where
47 show Pooling = "Pooling"
42 show Pooling = "Pooling"
48
43
49−
50instance UpdateLayer (Pooling kernelRows kernelColumns strideRows strideColumns) where
44instance UpdateLayer (Pooling kernelRows kernelColumns strideRows strideColumns) where
51 type Gradient (Pooling kr kc sr sc) = ()
45 type Gradient (Pooling kr kc sr sc) = ()
52 runUpdate _ Pooling _ = Pooling
46 runUpdate _ Pooling _ = Pooling
@@ -123,40 +117,3 @@ instance ( KnownNat kernelRows
123 ez = vectorZip (,) ex eo
117 ez = vectorZip (,) ex eo
124 vs = poolBackwardList kx ky sx sy ix iy ez
118 vs = poolBackwardList kx ky sx sy ix iy ez
125 in ((), S3D' . fmap (fromJust . create) $ vs)
119 in ((), S3D' . fmap (fromJust . create) $ vs)
126−
127−poolForward :: Int -> Int -> Int -> Int -> Int -> Int -> Matrix Double -> Matrix Double
128−poolForward nrows ncols srows scols outputRows outputCols m =
129− let starts = fittingStarts (rows m) nrows srows (cols m) ncols scols
130− in poolForwardFit starts nrows ncols outputRows outputCols m
131−
132−poolForwardList :: Functor f => Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> f (Matrix Double) -> f (Matrix Double)
133−poolForwardList nrows ncols srows scols inRows inCols outputRows outputCols ms =
134− let starts = fittingStarts inRows nrows srows inCols ncols scols
135− in poolForwardFit starts nrows ncols outputRows outputCols <$> ms
136−
137−poolForwardFit :: [(Int,Int)] -> Int -> Int -> Int -> Int -> Matrix Double -> Matrix Double
138−poolForwardFit starts nrows ncols _ outputCols m =
139− let els = fmap (\start -> maxElement $ subMatrix start (nrows, ncols) m) starts
140− in LA.matrix outputCols els
141−
142−poolBackward :: Int -> Int -> Int -> Int -> Matrix Double -> Matrix Double -> Matrix Double
143−poolBackward krows kcols srows scols inputMatrix gradientMatrix =
144− let inRows = (rows inputMatrix)
145− inCols = (cols inputMatrix)
146− starts = fittingStarts inRows krows srows inCols kcols scols
147− in poolBackwardFit starts krows kcols inputMatrix gradientMatrix
148−
149−poolBackwardList :: Functor f => Int -> Int -> Int -> Int -> Int -> Int -> f (Matrix Double, Matrix Double) -> f (Matrix Double)
150−poolBackwardList krows kcols srows scols inRows inCols inputMatrices =
151− let starts = fittingStarts inRows krows srows inCols kcols scols
152− in (uncurry $ poolBackwardFit starts krows kcols) <$> inputMatrices
153−
154−poolBackwardFit :: [(Int,Int)] -> Int -> Int -> Matrix Double -> Matrix Double -> Matrix Double
155−poolBackwardFit starts krows kcols inputMatrix gradientMatrix =
156− let inRows = (rows inputMatrix)
157− inCols = (cols inputMatrix)
158− inds = fmap (\start -> maxIndex $ subMatrix start (krows, kcols) inputMatrix) starts
159− grads = toList $ flatten gradientMatrix
160− grads' = zip3 starts grads inds
161− accums = fmap (\((stx',sty'),grad,(inx, iny)) -> ((stx' + inx, sty' + iny), grad)) grads'
162− in accum (LA.konst 0 (inRows, inCols)) (+) accums
test/Test/Grenade/Layers/Convolution.hs+7−7
@@ -8,7 +8,7 @@ import Grenade.Core.Shape
8import Grenade.Core.Vector as Grenade
8import Grenade.Core.Vector as Grenade
9import Grenade.Core.Network
9import Grenade.Core.Network
10import Grenade.Layers.Convolution
10import Grenade.Layers.Convolution
11−import Grenade.Layers.Convolution.Internal
11+import Grenade.Layers.Internal.Convolution
12
12
13import Numeric.LinearAlgebra hiding (uniformSample, konst, (===))
13import Numeric.LinearAlgebra hiding (uniformSample, konst, (===))
14import qualified Numeric.LinearAlgebra.Static as HStatic
14import qualified Numeric.LinearAlgebra.Static as HStatic
@@ -51,7 +51,7 @@ prop_im2col_other = once $
51 expected = (2><6)
51 expected = (2><6)
52 [ 1.0, 2.0, 5.0, 6.0 , 9.0, 10.0
52 [ 1.0, 2.0, 5.0, 6.0 , 9.0, 10.0
53 , 3.0, 4.0, 7.0, 8.0 , 11.0 ,12.0 ]
53 , 3.0, 4.0, 7.0, 8.0 , 11.0 ,12.0 ]
54− out = im2col 3 2 1 2 input
54+ out = im2colUnsafe 3 2 1 2 input
55 in expected === out
55 in expected === out
56
56
57-- If there's no overlap (stride is the same size as the kernel)
57-- If there's no overlap (stride is the same size as the kernel)
@@ -71,7 +71,7 @@ prop_im2colunsafe_sym_on_same_stride = once $
71 [ 1.0, 2.0, 3.0, 4.0
71 [ 1.0, 2.0, 3.0, 4.0
72 , 5.0, 6.0, 7.0, 8.0
72 , 5.0, 6.0, 7.0, 8.0
73 , 9.0, 10.0, 11.0, 12.0 ]
73 , 9.0, 10.0, 11.0, 12.0 ]
74− out = col2imUnsafe 3 2 3 2 3 4 . im2colUnsafe 3 2 3 2 3 4 $ input
74+ out = col2imUnsafe 3 2 3 2 3 4 . im2colUnsafe 3 2 3 2 $ input
75 in input === out
75 in input === out
76
76
77
77
@@ -86,7 +86,7 @@ prop_im2col_col2im_additive = once $
86 [ 1.0, 2.0, 2.0, 1.0
86 [ 1.0, 2.0, 2.0, 1.0
87 , 2.0, 4.0, 4.0, 2.0
87 , 2.0, 4.0, 4.0, 2.0
88 , 1.0, 2.0, 2.0, 1.0 ]
88 , 1.0, 2.0, 2.0, 1.0 ]
89− out = col2im 2 2 1 1 3 4 . im2col 2 2 1 1 $ input
89+ out = col2imUnsafe 2 2 1 1 3 4 . im2colUnsafe 2 2 1 1 $ input
90 in expected === out
90 in expected === out
91
91
92prop_simple_conv_forwards = once $
92prop_simple_conv_forwards = once $
@@ -166,7 +166,7 @@ prop_vid2col_no_stride = once $
166 , 5.0, 6.0, 9.0, 10.0 , 25.0, 26.0, 29.0, 30.0
166 , 5.0, 6.0, 9.0, 10.0 , 25.0, 26.0, 29.0, 30.0
167 , 6.0, 7.0, 10.0, 11.0 , 26.0, 27.0, 30.0, 31.0
167 , 6.0, 7.0, 10.0, 11.0 , 26.0, 27.0, 30.0, 31.0
168 , 7.0, 8.0, 11.0, 12.0 , 27.0, 28.0, 31.0, 32.0 ]
168 , 7.0, 8.0, 11.0, 12.0 , 27.0, 28.0, 31.0, 32.0 ]
169− out = vid2col 2 2 1 1 3 4 input
169+ out = vid2colUnsafe 2 2 1 1 3 4 input
170 in expected === out
170 in expected === out
171
171
172prop_vid2col_stride = once $
172prop_vid2col_stride = once $
@@ -183,7 +183,7 @@ prop_vid2col_stride = once $
183 , 3.0, 4.0, 7.0, 8.0 , 23.0, 24.0, 27.0, 28.0
183 , 3.0, 4.0, 7.0, 8.0 , 23.0, 24.0, 27.0, 28.0
184 , 5.0, 6.0, 9.0, 10.0 , 25.0, 26.0, 29.0, 30.0
184 , 5.0, 6.0, 9.0, 10.0 , 25.0, 26.0, 29.0, 30.0
185 , 7.0, 8.0, 11.0, 12.0 , 27.0, 28.0, 31.0, 32.0 ]
185 , 7.0, 8.0, 11.0, 12.0 , 27.0, 28.0, 31.0, 32.0 ]
186− out = vid2col 2 2 1 2 3 4 input
186+ out = vid2colUnsafe 2 2 1 2 3 4 input
187 in expected === out
187 in expected === out
188
188
189
189
@@ -208,7 +208,7 @@ prop_vid2col_invert_unsafe = once $
208 [ 21.0, 22.0, 23.0, 24.0
208 [ 21.0, 22.0, 23.0, 24.0
209 , 25.0, 26.0, 27.0, 28.0
209 , 25.0, 26.0, 27.0, 28.0
210 , 29.0, 30.0, 31.0, 32.0 ] ]
210 , 29.0, 30.0, 31.0, 32.0 ] ]
211− out = col2vidUnsafe 3 2 3 2 3 4 . vid2colUnsafe 2 3 2 3 2 3 4 $ input
211+ out = col2vidUnsafe 3 2 3 2 3 4 . vid2colUnsafe 3 2 3 2 3 4 $ input
212 in input === out
212 in input === out
213
213
214
214