@@ -1,7 +1,5 @@
1−{-# LANGUAGE BangPatterns #-}
2{-# LANGUAGE DataKinds #-}
1{-# LANGUAGE DataKinds #-}
3{-# LANGUAGE ScopedTypeVariables #-}
2{-# LANGUAGE ScopedTypeVariables #-}
4−{-# LANGUAGE StandaloneDeriving #-}
5{-# LANGUAGE RecordWildCards #-}
3{-# LANGUAGE RecordWildCards #-}
6{-# LANGUAGE GADTs #-}
4{-# LANGUAGE GADTs #-}
7{-# LANGUAGE TypeOperators #-}
5{-# LANGUAGE TypeOperators #-}
@@ -9,9 +7,6 @@
9{-# LANGUAGE MultiParamTypeClasses #-}
7{-# LANGUAGE MultiParamTypeClasses #-}
10{-# LANGUAGE FlexibleInstances #-}
8{-# LANGUAGE FlexibleInstances #-}
11{-# LANGUAGE FlexibleContexts #-}
9{-# LANGUAGE FlexibleContexts #-}
12−{-# LANGUAGE PolyKinds #-}
13−{-# LANGUAGE PatternGuards #-}
15module Grenade.Layers.Convolution (
10module Grenade.Layers.Convolution (
16 Convolution (..)
11 Convolution (..)
17 , Convolution' (..)
12 , Convolution' (..)
@@ -31,6 +26,7 @@ import Numeric.LinearAlgebra.Static hiding ((|||), build, toRows)
31import Grenade.Core.Network
26import Grenade.Core.Network
32import Grenade.Core.Shape
27import Grenade.Core.Shape
33import Grenade.Layers.Internal.Convolution
28import Grenade.Layers.Internal.Convolution
29+import Grenade.Layers.Internal.Update
35-- | A convolution layer for a neural network.
31-- | A convolution layer for a neural network.
36-- This uses the im2col convolution trick popularised by Caffe, which essentially turns the
32-- This uses the im2col convolution trick popularised by Caffe, which essentially turns the
@@ -43,12 +39,12 @@ import Grenade.Layers.Internal.Convolution
43-- `out = (in - kernel) / stride + 1` for both dimensions.
39-- `out = (in - kernel) / stride + 1` for both dimensions.
45-- One probably shouldn't build their own layer, but rather use the randomConvolution function.
41-- One probably shouldn't build their own layer, but rather use the randomConvolution function.
46−data Convolution :: Nat -- ^ Number of channels, for the first layer this could be RGB for instance.
42+data Convolution :: Nat -- Number of channels, for the first layer this could be RGB for instance.
47− -> Nat -- ^ Number of filters, this is the number of channels output by the layer.
43+ -> Nat -- Number of filters, this is the number of channels output by the layer.
48− -> Nat -- ^ The number of rows in the kernel filter
44+ -> Nat -- The number of rows in the kernel filter
49− -> Nat -- ^ The number of column in the kernel filter
45+ -> Nat -- The number of column in the kernel filter
50− -> Nat -- ^ The row stride of the convolution filter
46+ -> Nat -- The row stride of the convolution filter
51− -> Nat -- ^ The columns stride of the convolution filter
47+ -> Nat -- The columns stride of the convolution filter
52 -> * where
48 -> * where
53 Convolution :: ( KnownNat channels
49 Convolution :: ( KnownNat channels
54 , KnownNat filters
50 , KnownNat filters
@@ -58,16 +54,16 @@ data Convolution :: Nat -- ^ Number of channels, for the first layer this could
58 , KnownNat strideColumns
54 , KnownNat strideColumns
59 , KnownNat kernelFlattened
55 , KnownNat kernelFlattened
60 , kernelFlattened ~ (kernelRows * kernelColumns * channels))
56 , kernelFlattened ~ (kernelRows * kernelColumns * channels))
61− => !(L kernelFlattened filters) -- ^ The kernel filter weights
57+ => !(L kernelFlattened filters) -- The kernel filter weights
62− -> !(L kernelFlattened filters) -- ^ The last kernel update (or momentum)
58+ -> !(L kernelFlattened filters) -- The last kernel update (or momentum)
63 -> Convolution channels filters kernelRows kernelColumns strideRows strideColumns
59 -> Convolution channels filters kernelRows kernelColumns strideRows strideColumns
65−data Convolution' :: Nat -- ^ Number of channels, for the first layer this could be RGB for instance.
61+data Convolution' :: Nat -- Number of channels, for the first layer this could be RGB for instance.
66− -> Nat -- ^ Number of filters, this is the number of channels output by the layer.
62+ -> Nat -- Number of filters, this is the number of channels output by the layer.
67− -> Nat -- ^ The number of rows in the kernel filter
63+ -> Nat -- The number of rows in the kernel filter
68− -> Nat -- ^ The number of column in the kernel filter
64+ -> Nat -- The number of column in the kernel filter
69− -> Nat -- ^ The row stride of the convolution filter
65+ -> Nat -- The row stride of the convolution filter
70− -> Nat -- ^ The columns stride of the convolution filter
66+ -> Nat -- The columns stride of the convolution filter
71 -> * where
67 -> * where
72 Convolution' :: ( KnownNat channels
68 Convolution' :: ( KnownNat channels
73 , KnownNat filters
69 , KnownNat filters
@@ -77,7 +73,7 @@ data Convolution' :: Nat -- ^ Number of channels, for the first layer this could
77 , KnownNat strideColumns
73 , KnownNat strideColumns
78 , KnownNat kernelFlattened
74 , KnownNat kernelFlattened
79 , kernelFlattened ~ (kernelRows * kernelColumns * channels))
75 , kernelFlattened ~ (kernelRows * kernelColumns * channels))
80− => !(L kernelFlattened filters) -- ^ The kernel filter gradient
76+ => !(L kernelFlattened filters) -- The kernel filter gradient
81 -> Convolution' channels filters kernelRows kernelColumns strideRows strideColumns
77 -> Convolution' channels filters kernelRows kernelColumns strideRows strideColumns
83instance Show (Convolution c f k k' s s') where
79instance Show (Convolution c f k k' s s') where
@@ -109,7 +105,7 @@ randomConvolution :: ( MonadRandom m
109 , kernelFlattened ~ (kernelRows * kernelColumns * channels))
105 , kernelFlattened ~ (kernelRows * kernelColumns * channels))
110 => m (Convolution channels filters kernelRows kernelColumns strideRows strideColumns)
106 => m (Convolution channels filters kernelRows kernelColumns strideRows strideColumns)
111randomConvolution = do
107randomConvolution = do
112− s :: Int <- getRandom
108+ s <- getRandom
113 let wN = uniformSample s (-1) 1
109 let wN = uniformSample s (-1) 1
114 mm = konst 0
110 mm = konst 0
115 return $ Convolution wN mm
111 return $ Convolution wN mm
@@ -124,9 +120,7 @@ instance ( KnownNat channels
124 ) => UpdateLayer (Convolution channels filters kernelRows kernelColumns strideRows strideColumns) where
120 ) => UpdateLayer (Convolution channels filters kernelRows kernelColumns strideRows strideColumns) where
125 type Gradient (Convolution channels filters kernelRows kernelCols strideRows strideCols) = (Convolution' channels filters kernelRows kernelCols strideRows strideCols)
121 type Gradient (Convolution channels filters kernelRows kernelCols strideRows strideCols) = (Convolution' channels filters kernelRows kernelCols strideRows strideCols)
126 runUpdate LearningParameters {..} (Convolution oldKernel oldMomentum) (Convolution' kernelGradient) =
122 runUpdate LearningParameters {..} (Convolution oldKernel oldMomentum) (Convolution' kernelGradient) =
127− let newMomentum = konst learningMomentum * oldMomentum - konst learningRate * kernelGradient
123+ let (newKernel, newMomentum) = decendMatrix learningRate learningMomentum learningRegulariser oldKernel kernelGradient oldMomentum
128− regulariser = konst (learningRegulariser * learningRate) * oldKernel
129− newKernel = oldKernel + newMomentum - regulariser
130 in Convolution newKernel newMomentum
124 in Convolution newKernel newMomentum
132 createRandom = randomConvolution
126 createRandom = randomConvolution
@@ -146,7 +140,7 @@ instance ( KnownNat kernelRows
146 , KnownNat (kernelRows * kernelCols * 1)
140 , KnownNat (kernelRows * kernelCols * 1)
147 , KnownNat (outputRows * filters)
141 , KnownNat (outputRows * filters)
148 ) => Layer (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
149− runForwards (Convolution kernel _) (S2D' input) =
143+ runForwards (Convolution kernel _) (S2D input) =
150 let ex = extract input
144 let ex = extract input
151 ek = extract kernel
145 ek = extract kernel
152 kx = fromIntegral $ natVal (Proxy :: Proxy kernelRows)
146 kx = fromIntegral $ natVal (Proxy :: Proxy kernelRows)
@@ -159,9 +153,9 @@ instance ( KnownNat kernelRows
159 mt = c LA.<> ek
153 mt = c LA.<> ek
160 r = col2vid 1 1 1 1 ox oy mt
154 r = col2vid 1 1 1 1 ox oy mt
161 rs = fromJust . create $ r
155 rs = fromJust . create $ r
162− in S3D' rs
156+ in S3D rs
164− runBackwards (Convolution kernel _) (S2D' input) (S3D' dEdy) =
158+ runBackwards (Convolution kernel _) (S2D input) (S3D dEdy) =
165 let ex = extract input
159 let ex = extract input
166 ix = fromIntegral $ natVal (Proxy :: Proxy inputRows)
160 ix = fromIntegral $ natVal (Proxy :: Proxy inputRows)
167 iy = fromIntegral $ natVal (Proxy :: Proxy inputCols)
161 iy = fromIntegral $ natVal (Proxy :: Proxy inputCols)
@@ -183,7 +177,7 @@ instance ( KnownNat kernelRows
183 dW = vs LA.<> tr ek
177 dW = vs LA.<> tr ek
185 xW = col2im kx ky sx sy ix iy dW
179 xW = col2im kx ky sx sy ix iy dW
186− in (Convolution' kN, S2D' . fromJust . create $ xW)
180+ in (Convolution' kN, S2D . fromJust . create $ xW)
189-- | A three dimensional image (or 2d with many channels) can have
183-- | A three dimensional image (or 2d with many channels) can have
@@ -203,7 +197,7 @@ instance ( KnownNat kernelRows
203 , KnownNat (kernelRows * kernelCols * channels)
197 , KnownNat (kernelRows * kernelCols * channels)
204 , KnownNat (outputRows * filters)
198 , KnownNat (outputRows * filters)
205 ) => Layer (Convolution channels filters kernelRows kernelCols strideRows strideCols) ('D3 inputRows inputCols channels) ('D3 outputRows outputCols filters) where
199 ) => Layer (Convolution channels filters kernelRows kernelCols strideRows strideCols) ('D3 inputRows inputCols channels) ('D3 outputRows outputCols filters) where
206− runForwards (Convolution kernel _) (S3D' input) =
200+ runForwards (Convolution kernel _) (S3D input) =
207 let ex = extract input
201 let ex = extract input
208 ek = extract kernel
202 ek = extract kernel
209 ix = fromIntegral $ natVal (Proxy :: Proxy inputRows)
203 ix = fromIntegral $ natVal (Proxy :: Proxy inputRows)
@@ -219,8 +213,8 @@ instance ( KnownNat kernelRows
219 mt = c LA.<> ek
213 mt = c LA.<> ek
220 r = col2vid 1 1 1 1 ox oy mt
214 r = col2vid 1 1 1 1 ox oy mt
221 rs = fromJust . create $ r
215 rs = fromJust . create $ r
222− in S3D' rs
216+ in S3D rs
223− runBackwards (Convolution kernel _) (S3D' input) (S3D' dEdy) =
217+ runBackwards (Convolution kernel _) (S3D input) (S3D dEdy) =
224 let ex = extract input
218 let ex = extract input
225 ix = fromIntegral $ natVal (Proxy :: Proxy inputRows)
219 ix = fromIntegral $ natVal (Proxy :: Proxy inputRows)
226 iy = fromIntegral $ natVal (Proxy :: Proxy inputCols)
220 iy = fromIntegral $ natVal (Proxy :: Proxy inputCols)
@@ -243,4 +237,4 @@ instance ( KnownNat kernelRows
243 dW = vs LA.<> tr ek
237 dW = vs LA.<> tr ek
245 xW = col2vid kx ky sx sy ix iy dW
239 xW = col2vid kx ky sx sy ix iy dW
246− in (Convolution' kN, S3D' . fromJust . create $ xW)
240+ in (Convolution' kN, S3D . fromJust . create $ xW)