on master help sign in
Add faster maxIndex and maxElement for matrices
commit24289dba41f14e36d8469b540539ebd6294037ec authorHuw Campbell <huw.campbell@ambiata.com> dateThu 8 Dec 2016, 21:07 (10 years ago) parentff20855
4 files changed+61−51
src/Grenade/Layers/Internal/Pooling.hs+17−2 src/Grenade/Layers/Pooling.hs−2 test/Test/Grenade/Layers/Convolution.hs+41−44 test/Test/Grenade/Layers/Pooling.hs+3−3
src/Grenade/Layers/Internal/Pooling.hs+17−2
@@ -5,8 +5,13 @@ module Grenade.Layers.Internal.Pooling (
55 , poolBackwardList
66 ) where
77
8+import Data.Function ( on )
9+import Data.List ( maximumBy )
10+
811import Numeric.LinearAlgebra hiding ( uniformSample, konst )
912import qualified Numeric.LinearAlgebra as LA
13+import qualified Numeric.LinearAlgebra.Devel as U
14+
1015
1116import Grenade.Layers.Internal.Convolution
1217
@@ -22,7 +27,7 @@ poolForwardList nrows ncols srows scols inRows inCols outputRows outputCols ms =
2227
2328poolForwardFit :: [(Int,Int)] -> Int -> Int -> Int -> Int -> Matrix Double -> Matrix Double
2429poolForwardFit starts nrows ncols _ outputCols m =
25− let els = fmap (\start -> maxElement $ subMatrix start (nrows, ncols) m) starts
30+ let els = fmap (\start -> unsafeMaxElement $ subMatrix start (nrows, ncols) m) starts
2631 in LA.matrix outputCols els
2732
2833poolBackward :: Int -> Int -> Int -> Int -> Matrix Double -> Matrix Double -> Matrix Double
@@ -41,8 +46,18 @@ poolBackwardFit :: [(Int,Int)] -> Int -> Int -> Matrix Double -> Matrix Double -
4146poolBackwardFit starts krows kcols inputMatrix gradientMatrix =
4247 let inRows = rows inputMatrix
4348 inCols = cols inputMatrix
44− inds = fmap (\start -> maxIndex $ subMatrix start (krows, kcols) inputMatrix) starts
49+ inds = fmap (\start -> unsafeMaxIndex $ subMatrix start (krows, kcols) inputMatrix) starts
4550 grads = toList $ flatten gradientMatrix
4651 grads' = zip3 starts grads inds
4752 accums = fmap (\((stx',sty'),grad,(inx, iny)) -> ((stx' + inx, sty' + iny), grad)) grads'
4853 in accum (LA.konst 0 (inRows, inCols)) (+) accums
54+
55+unsafeMaxElement :: Matrix Double -> Double
56+unsafeMaxElement m = uncurry (U.atM' m) $ unsafeMaxIndex m
57+
58+unsafeMaxIndex :: Matrix Double -> (Int, Int)
59+unsafeMaxIndex m =
60+ let mrows = [0 .. rows m - 1]
61+ mcols = [0 .. cols m - 1]
62+ pairs = concatMap ( \r -> fmap (\c -> (r , c)) mcols ) mrows
63+ in maximumBy (compare `on` uncurry (U.atM' m)) pairs
src/Grenade/Layers/Pooling.hs−2
@@ -12,8 +12,6 @@
1212
1313module Grenade.Layers.Pooling (
1414 Pooling (..)
15− , poolForward
16− , poolBackward
1715 ) where
1816
1917import Data.Maybe
test/Test/Grenade/Layers/Convolution.hs+41−44
@@ -93,22 +93,22 @@ prop_simple_conv_forwards = once $
9393 -- Create a convolution kernel with 4 filters.
9494 -- [ 1, 0 [ 0, 1 [ 0, 1 [ 0, 0
9595 -- , 0,-1 ] ,-1, 0 ] , 1, 0 ] ,-1,-1 ]
96− let myKernel = (HStatic.matrix
96+ let myKernel = HStatic.matrix
9797 [ 1.0, 0.0, 0.0, 0.0
9898 , 0.0, 1.0, 1.0, 0.0
9999 , 0.0, -1.0, 1.0, -1.0
100− ,-1.0, 0.0, 0.0, -1.0 ] :: HStatic.L 4 4)
101− zeroKernel = (HStatic.matrix
100+ ,-1.0, 0.0, 0.0, -1.0 ] :: HStatic.L 4 4
101+ zeroKernel = HStatic.matrix
102102 [ 0.0, 0.0, 0.0, 0.0
103103 , 0.0, 0.0, 0.0, 0.0
104104 , 0.0, 0.0, 0.0, 0.0
105− , 0.0, 0.0, 0.0, 0.0 ] :: HStatic.L 4 4)
105+ , 0.0, 0.0, 0.0, 0.0 ] :: HStatic.L 4 4
106106
107− expectedGradient = (HStatic.matrix
107+ expectedGradient = HStatic.matrix
108108 [ 1.0, 0.0, 0.0, 2.0
109109 , 2.0, 0.0, 0.0, 5.0
110110 , 3.0, 0.0, 0.0, 4.0
111− , 4.0, 0.0, 0.0, 6.0 ] :: HStatic.L 4 4)
111+ , 4.0, 0.0, 0.0, 6.0 ] :: HStatic.L 4 4
112112
113113 convLayer = Convolution myKernel zeroKernel :: Convolution 1 4 2 2 1 1
114114
@@ -116,25 +116,25 @@ prop_simple_conv_forwards = once $
116116 [ 1.0, 2.0, 5.0
117117 , 3.0, 4.0, 6.0] :: HStatic.L 2 3)
118118
119− expect = ([(HStatic.matrix
120− [ -3.0 , -4.0 ] :: HStatic.L 1 2)
121− ,(HStatic.matrix
122− [ -1.0 , 1.0 ] :: HStatic.L 1 2)
123− ,(HStatic.matrix
124− [ 5.0 , 9.0 ] :: HStatic.L 1 2)
125− ,(HStatic.matrix
126− [ -7.0 , -10.0 ] :: HStatic.L 1 2)]) :: [HStatic.L 1 2]
119+ expect = [ HStatic.matrix
120+ [ -3.0 , -4.0 ] :: HStatic.L 1 2
121+ , HStatic.matrix
122+ [ -1.0 , 1.0 ] :: HStatic.L 1 2
123+ , HStatic.matrix
124+ [ 5.0 , 9.0 ] :: HStatic.L 1 2
125+ , HStatic.matrix
126+ [ -7.0 , -10.0 ] :: HStatic.L 1 2] :: [HStatic.L 1 2]
127127 out = runForwards convLayer input :: S' ('D3 1 2 4)
128128
129129 grad = S3D' ( mkVector
130− [(HStatic.matrix
131− [ 1 , 0 ] :: HStatic.L 1 2)
132− ,(HStatic.matrix
133− [ 0 , 0 ] :: HStatic.L 1 2)
134− ,(HStatic.matrix
135− [ 0 , 0 ] :: HStatic.L 1 2)
136− ,(HStatic.matrix
137− [ 0 , 1 ] :: HStatic.L 1 2)] ) :: S' ('D3 1 2 4)
130+ [ HStatic.matrix
131+ [ 1 , 0 ] :: HStatic.L 1 2
132+ , HStatic.matrix
133+ [ 0 , 0 ] :: HStatic.L 1 2
134+ , HStatic.matrix
135+ [ 0 , 0 ] :: HStatic.L 1 2
136+ , HStatic.matrix
137+ [ 0 , 1 ] :: HStatic.L 1 2] ) :: S' ('D3 1 2 4)
138138
139139 expectBack = (HStatic.matrix
140140 [ 1.0, 0.0, 0.0
@@ -144,11 +144,8 @@ prop_simple_conv_forwards = once $
144144 in case (out, inX, nc) of
145145 (S3D' out' , S2D' inX', Convolution' backGrad)
146146 -> ((HStatic.extract <$> expect) === (HStatic.extract <$> vecToList out'))
147− .&&. ((HStatic.extract expectBack) === (HStatic.extract inX'))
148− .&&. ((HStatic.extract expectedGradient) === (HStatic.extract backGrad))
149− -- Temporarily disabled, as l2 adjustment puts in off 5%
150− -- .&&. HStatic.extract expectedKernel === HStatic.extract kernel'
151−
147+ .&&. (HStatic.extract expectBack === HStatic.extract inX')
148+ .&&. (HStatic.extract expectedGradient === HStatic.extract backGrad)
152149
153150prop_vid2col_no_stride = once $
154151 let input = [(3><4)
@@ -228,25 +225,25 @@ prop_single_conv_forwards = once $
228225 [ 1.0, 2.0, 5.0
229226 , 3.0, 4.0, 6.0] :: HStatic.L 2 3] ) :: S' ('D3 2 3 1)
230227
231− expect = ([(HStatic.matrix
232− [ -3.0 , -4.0 ] :: HStatic.L 1 2)
233− ,(HStatic.matrix
234− [ -1.0 , 1.0 ] :: HStatic.L 1 2)
235− ,(HStatic.matrix
236− [ 5.0 , 9.0 ] :: HStatic.L 1 2)
237− ,(HStatic.matrix
238− [ -7.0 , -10.0 ] :: HStatic.L 1 2)]) :: [HStatic.L 1 2]
228+ expect = [HStatic.matrix
229+ [ -3.0 , -4.0 ] :: HStatic.L 1 2
230+ ,HStatic.matrix
231+ [ -1.0 , 1.0 ] :: HStatic.L 1 2
232+ ,HStatic.matrix
233+ [ 5.0 , 9.0 ] :: HStatic.L 1 2
234+ ,HStatic.matrix
235+ [ -7.0 , -10.0 ] :: HStatic.L 1 2] :: [HStatic.L 1 2]
239236 out = runForwards convLayer input :: S' ('D3 1 2 4)
240237
241238 grad = S3D' ( mkVector
242− [(HStatic.matrix
243− [ 1 , 0 ] :: HStatic.L 1 2)
244− ,(HStatic.matrix
245− [ 0 , 0 ] :: HStatic.L 1 2)
246− ,(HStatic.matrix
247− [ 0 , 0 ] :: HStatic.L 1 2)
248− ,(HStatic.matrix
249− [ 0 , 1 ] :: HStatic.L 1 2)] ) :: S' ('D3 1 2 4)
239+ [HStatic.matrix
240+ [ 1 , 0 ] :: HStatic.L 1 2
241+ ,HStatic.matrix
242+ [ 0 , 0 ] :: HStatic.L 1 2
243+ ,HStatic.matrix
244+ [ 0 , 0 ] :: HStatic.L 1 2
245+ ,HStatic.matrix
246+ [ 0 , 1 ] :: HStatic.L 1 2] ) :: S' ('D3 1 2 4)
250247
251248 expectBack = (HStatic.matrix
252249 [ 1.0, 0.0, 0.0
@@ -257,7 +254,7 @@ prop_single_conv_forwards = once $
257254 (S3D' out' , S3D' inX', Convolution' backGrad)
258255 -> ((HStatic.extract <$> expect) === (HStatic.extract <$> vecToList out'))
259256 .&&. ([HStatic.extract expectBack] === (HStatic.extract <$> vecToList inX'))
260− .&&. ((HStatic.extract expectedGradient) === (HStatic.extract backGrad))
257+ .&&. (HStatic.extract expectedGradient === HStatic.extract backGrad)
261258
262259return []
263260tests :: IO Bool
test/Test/Grenade/Layers/Pooling.hs+3−3
@@ -4,7 +4,7 @@
44{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
55module Test.Grenade.Layers.Pooling where
66
7−import Grenade.Layers.Pooling
7+import Grenade.Layers.Internal.Pooling
88
99import Numeric.LinearAlgebra hiding (uniformSample, konst, (===))
1010
@@ -12,11 +12,11 @@ import Test.QuickCheck hiding ((><))
1212
1313prop_pool = once $
1414 let input = (3><4)
15− [ 1.0, 2.0, 3.0, 4.0
15+ [ 1.0, 14.0, 3.0, 4.0
1616 , 5.0, 6.0, 7.0, 8.0
1717 , 9.0, 10.0, 11.0, 12.0 ]
1818 expected = (2><3)
19− [ 6.0, 7.0, 8.0
19+ [ 14.0, 14.0, 8.0
2020 , 10.0, 11.0, 12.0 ]
2121 out = poolForward 2 2 1 1 2 3 input
2222 in expected === out