Advertisement
Guest User

nn

a guest
Feb 25th, 2018
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. module NeuralNetwork
  2.   () where
  3.  
  4. import           Control.Monad         (mapM)
  5. import qualified Data.Sequence         as Seq
  6. import           Numeric.LinearAlgebra ((<>), (><))
  7. import qualified Numeric.LinearAlgebra as LA
  8. import Debug.Trace
  9.  
  10. type MatrixNum = LA.Matrix Double
  11. type Cache = ((MatrixNum, MatrixNum, MatrixNum), MatrixNum)
  12.  
  13. data Parameter = Parameter
  14.   { weightsParam :: MatrixNum
  15.   , biasesParam  :: MatrixNum
  16.   }
  17.  
  18. -- Utils
  19. emptyx :: MatrixNum
  20. emptyx = (0><0) []
  21.  
  22. emptyCache :: Cache
  23. emptyCache = ((emptyx, emptyx, emptyx), emptyx)
  24.  
  25. -- Activation functions
  26. relu :: MatrixNum -> MatrixNum
  27. relu = LA.cmap (max 0)
  28.  
  29. sigmoid :: MatrixNum -> MatrixNum
  30. sigmoid = LA.cmap (\x -> (1 / (1 + exp (-1 * x))))
  31.  
  32. relu' :: MatrixNum -> MatrixNum
  33. relu' = LA.cmap f
  34.   where
  35.     f x | x < 0 = 0
  36.         | otherwise = 1
  37.  
  38. sigmoid' :: MatrixNum -> MatrixNum
  39. sigmoid' xw = (sigmoid xw) * (1 - sigmoid xw)
  40.  
  41. -- | Initialize parameters. Randomize weights and zeroes biases
  42. initParams :: [Int] -> IO [Parameter]
  43. initParams layerDims =
  44.   (fmap . fmap) (\(bx, wx) -> Parameter wx bx) ((zip biases) <$> weights)
  45.     where
  46.       weights = mapM genParams layerDims'
  47.      layerDims' = (zip layerDims (tail layerDims))
  48.       genParams (prevDim, currentDim) = LA.randn currentDim prevDim
  49.       biases =
  50.         fmap
  51.         (\(_, currentDim) -> (currentDim><1) (replicate currentDim 0))
  52.         layerDims'
  53.  
  54. -- | Propagate forward to next layer. Calulates next a
  55. linearForward axPrev wx bx activationFun =
  56.  let zx = linearForward' axPrev wx bx
  57.       ax = activationFun zx
  58.       cache = ((axPrev, wx, bx), zx)
  59.       linearForward' axPrev wx bx = (wx <> axPrev) + bx :: MatrixNum
  60.  in  (ax, cache)
  61.  
  62. -- | Complete forward propagation. Calculates final ax
  63. propagateForward :: MatrixNum
  64.                 -> [Parameter]
  65.                 -> (MatrixNum, [Cache])
  66. propagateForward xx params  =
  67.  (outputAx, hiddenCache ++ [outputCache])
  68.    where
  69.      params' = take ((length params) - 1) params
  70.       f (aPrev, _) (Parameter wx bx) = linearForward aPrev wx bx relu
  71.       hidden = scanl f (xx, emptyCache) params'
  72.      hiddenCache = drop 1 (fmap snd hidden)
  73.      (lastHiddenAx, _) = last hidden
  74.      Parameter wxLast bxLast = last params
  75.      (outputAx, outputCache) = linearForward lastHiddenAx wxLast bxLast sigmoid
  76.  
  77.  
  78. -- | Propagate backward to previous layer
  79. linearBackward :: MatrixNum -> Cache -> (MatrixNum -> MatrixNum)
  80.               -> (MatrixNum, MatrixNum, MatrixNum)
  81. linearBackward dax ((axPrev, wx, bx), zx) af' =
  82.   (daxPrev, dwx, dbx)
  83.     where
  84.       dzx = dax * af' zx
  85.      m = fromIntegral $ (snd . LA.size) axPrev
  86.      dwx = (dzx <> (LA.tr axPrev)) / m
  87.      sums = fmap sum (LA.toLists dzx)
  88.      layerSize = (fst . LA.size) wx
  89.      dbx = ((layerSize><1) sums) / m
  90.      daxPrev = (LA.tr wx) <> dzx
  91.  
  92. test = do
  93.  params <- initParams [3, 5, 4, 1]
  94.  let xx = LA.tr $ LA.matrix 3 [6.00, 100, 12, 5.92, 190, 11, 5.58, 170, 12, 5.92, 165, 10, 5.00, 100, 6, 5.50, 150, 8, 5.42, 130, 7, 5.75, 150, 9]
  95.  let yx = LA.vector [0, 0, 0, 0, 1, 1, 1, 1]
  96.  let layerDims = [3, 5, 4, 1]
  97.  let (ax, caches) = propagateForward xx params
  98.  print $ length caches
  99.  let l = length caches
  100.  let yx' = LA.reshape 1 yx
  101.   let daxOut = - (yx' / ax) - ((1 - yx') / (1 - ax))
  102.   let ((axPrev, wx, bx), zx) = last caches
  103.   let dzx = daxOut * sigmoid' zx
  104.  let m = fromIntegral $ (snd . LA.size) axPrev
  105.  let dwx = (dzx <> (LA.tr axPrev)) /m
  106.  let sums = fmap sum (LA.toLists dzx)
  107.  let layerSize = (LA.size . LA.vector) sums
  108.  let dbx = ((layerSize><1) sums) / m
  109.  let daxPrev = (LA.tr wx) <> dzx
  110.  print $ LA.size zx
  111.  print $ LA.size dzx
  112.  --m = fromIntegral $ (snd . LA.size) axPrev
  113.  --dwx = (dzx <> (LA.tr axPrev)) / m
  114.  --dbx = ((layerSize><1) sums) / m
  115.  --sums = fmap sum (LA.toLists dzx)
  116.  --layerSize = (LA.size . LA.vector) sums
  117.  --daxPrev = (LA.tr wx) <> dzx
  118.  -- return gradOut
  119.  
  120. -- | Complete backpropagation. Computes gradients (dax, dwx, dbx)
  121. -- of each layer
  122. propagateBackward :: MatrixNum -> (LA.Vector Double) -> [Cache]
  123.                  -> [(MatrixNum, MatrixNum, MatrixNum)]
  124. propagateBackward axOut yx caches =
  125.  let l = length caches
  126.      yx' = LA.reshape 1 yx
  127.       daxOut = - (yx' / axOut) - ((1 - yx') / (1 - axOut))
  128.       gradOut = linearBackward daxOut (last caches) sigmoid'
  129.      hiddenCaches = reverse $ take (length caches - 1) caches
  130.      grads = scanl f gradOut hiddenCaches
  131.      f (dax, _, _) cache = linearBackward dax cache relu'
  132.   in  reverse grads
  133.  
  134. -- | Perform gradient descent. Computes new decreased gradients (dax, dwx, dbx)
  135. updateParameters :: [Parameter]
  136.                  -> [(MatrixNum, MatrixNum, MatrixNum)]
  137.                  -> Double
  138.                  -> [Parameter]
  139. updateParameters params grads eta = fmap fun (zip params grads)
  140.    where fun ((Parameter wx bx), (_, dwx, dbx)) =
  141.            Parameter
  142.              (wx - (LA.scalar eta) * dwx)
  143.              (bx - (LA.scalar eta) * dbx)
  144.  
  145. train :: MatrixNum
  146.       -> LA.Vector Double
  147.       -> [Int]
  148.       -> Double
  149.       -> Int
  150.       -> IO [Parameter]
  151. train xx yx layerDims eta iterations =
  152.   do
  153.     params <- initParams layerDims
  154.     return $ train' params iterations
  155.  where
  156.    train' params 0 = params
  157.     train' params times =
  158.      let (ax, caches) = propagateForward xx params
  159.          grads = propagateBackward ax yx caches
  160.          newParams = updateParameters params grads eta
  161.      in  train' newParams (times - 1)
  162.  
  163.  
  164.   -- newParams <- train xx yx layerDims 0.003 100
  165.   --print ax
  166.  
  167. --cost ax yx =
  168. --  (-1 / m) * ()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement