packages feed

rc (empty) → 0.1.0.0

raw patch · 9 files changed

+414/−0 lines, 9 filesdep +Learningdep +basedep +ddesetup-changed

Dependencies added: Learning, base, dde, hmatrix, random, rc, vector

Files

+ ChangeLog.md view
@@ -0,0 +1,3 @@+# Changelog for rc++## Unreleased changes
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Bogdan Penkovsky (c) 2018++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Bogdan Penkovsky nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,28 @@+# Reservoir Computing++Facilitating RC research++## Features++* [Nonlinear transient computing (NTC)](https://github.com/masterdezign/rc/tree/master/examples/NTC)+++## Getting Started++Use [Stack](http://haskellstack.org).++     $ git clone https://github.com/masterdezign/rc.git && cd rc+     $ stack build --install-ghc++### [Example 1](https://github.com/masterdezign/rc/tree/master/examples/NTC). NTC+++     $ stack exec ntc++     Error: 3.1103181863915367e-3++[Here](https://raw.githubusercontent.com/masterdezign/rc/master/examples/NTC/mg-prediction.png) is visualized prediction result.++++Great!
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ examples/NTC/Main.hs view
@@ -0,0 +1,59 @@+import           Numeric.LinearAlgebra+import           System.Random ( mkStdGen )+import           Learning ( nrmse )++import           RC.NTC as RC++-- Get training data+takePast :: Int -> Matrix Double -> Matrix Double+takePast horizon xs = xs ?? (All, Take (len - horizon))+  where+    len = cols xs++-- Get teacher data+takeFuture :: Int -> Matrix Double -> Matrix Double+takeFuture horizon = (?? (All, Drop horizon))++main = do+  -- Load and transpose time series to predict+  dta <- tr <$> loadMatrix "examples/data/mg.txt"++  let splitRatio = 0.50  -- Train on 50% of data+      total = cols dta+      spl = round $ splitRatio * fromIntegral total+      -- Split the data+      train = dta ?? (All, Take spl)+      validate = dta ?? (All, Drop spl)++  -- Configure new NTC network+  let p = RC.par0 { RC._inputWeightsRange = (0.1, 0.3) }+      g = mkStdGen 1111+      ntc = RC.new g p (1, 1000, 1)++  -- 20 steps ahead prediction horizon+  let horizon = 20++  let train' = takePast horizon train  -- Past series+      trainTeacher = takeFuture horizon train  -- Predicted series++  let forgetPts = 300  -- Washout++  -- Train+  case RC.learn ntc forgetPts train' trainTeacher of+    Left s -> error s+    Right ntc' -> do+      let target = (takeFuture horizon validate) ?? (All, Drop forgetPts)++      -- Predict+      case RC.predict ntc' forgetPts (takePast horizon validate) of+        Left s -> error s+        Right prediction -> do+          let tgt' = flatten target+              predic' = flatten prediction+              err = nrmse tgt' predic'++          putStrLn $ "Error: " ++ show err++          let result = (tr target) ||| (tr prediction)++          saveMatrix "examples/NTC/result.txt" "%g" result
+ rc.cabal view
@@ -0,0 +1,79 @@+-- This file has been generated from package.yaml by hpack version 0.20.0.+--+-- see: https://github.com/sol/hpack+--+-- hash: 32b8af1a3f4db71e5262f476ae36f22cd703e7dfd8e047f0c0d7b61b9ee1f3e8++name:           rc+version:        0.1.0.0+synopsis:       Reservoir Computing, fast RNNs+description:    Please see the README on Github at <https://github.com/masterdezign/rc#readme>+category:       Machine Learning+homepage:       https://github.com/masterdezign/rc#readme+bug-reports:    https://github.com/masterdezign/rc/issues+author:         Bogdan Penkovsky+maintainer:     dev () penkovsky dot com+copyright:      Bogdan Penkovsky+license:        BSD3+license-file:   LICENSE+build-type:     Simple+cabal-version:  >= 1.10++extra-source-files:+    ChangeLog.md+    README.md++source-repository head+  type: git+  location: https://github.com/masterdezign/rc++library+  hs-source-dirs:+      rc+  build-depends:+      Learning+    , base >=4.7 && <5+    , dde ==0.0.0+    , hmatrix >=0.18.0.0+    , random+    , vector+  exposed-modules:+      RC.Helpers+      RC.NTC+  other-modules:+      Paths_rc+  default-language: Haskell2010++executable ntc+  main-is: Main.hs+  hs-source-dirs:+      examples/NTC+  build-depends:+      Learning+    , base >=4.7 && <5+    , dde ==0.0.0+    , hmatrix >=0.18.0.0+    , random+    , rc+    , vector+  other-modules:+      Paths_rc+  default-language: Haskell2010++test-suite rc-test+  type: exitcode-stdio-1.0+  main-is: Spec.hs+  hs-source-dirs:+      test+  ghc-options: -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      Learning+    , base >=4.7 && <5+    , dde ==0.0.0+    , hmatrix >=0.18.0.0+    , random+    , rc+    , vector+  other-modules:+      Paths_rc+  default-language: Haskell2010
+ rc/RC/Helpers.hs view
@@ -0,0 +1,65 @@+module RC.Helpers+  ( addBiases+  , randList+  , randMatrix+  , randSparse+  , hsigmoid+  ) where++import           System.Random+import           Data.List ( unfoldr )+import qualified Numeric.LinearAlgebra as LA++-- | Hard sigmoid+hsigmoid :: (Fractional a, Ord a)+         => (a, a, a)+         -- ^ Vertical scaling, width, offset+         -> a+         -> a+hsigmoid (β, width, offset) x = f+  where+    f | x < offset = 0.0+      | x < width = β * (x - offset)+      | otherwise = β * (width - offset)++-- | Prepend a row of ones+-- >>> addBiases $ (2><3) [20..26]+-- (3><3)+--  [  1.0,  1.0,  1.0+--  , 20.0, 21.0, 22.0+--  , 23.0, 24.0, 25.0 ]+addBiases :: LA.Matrix Double -> LA.Matrix Double+addBiases m = let no = LA.cols m+                  m' = LA.konst 1.0 (1, no)+              in m' LA.=== m++-- | Random matrix with elements in the range of [minVal; maxVal]+randMatrix+  :: StdGen+     -> (Int, Int)+     -- ^ Number of rows and columns+     -> (Double, Double)+     -- ^ Minimal and maximal values+     -> LA.Matrix Double+randMatrix seed (rows', cols') (minVal, maxVal) = (LA.reshape cols'. LA.vector) xs+  where+    xs = f <$> randList (rows' * cols') seed+    f x = (maxVal - minVal) * x + minVal++-- | Random sparse matrix+--+-- NB: at the moment, the matrix is stored in memory as+-- an ordinary (dense) matrix.+randSparse g (rows', cols') (minVal, maxVal) connectivity =+    LA.reshape cols' $ LA.vector xs+  where+    (g1, g2) = split g+    rlist = randList (rows' * cols')+    xs = zipWith f (rlist g1) (rlist g2)+    f lv rv | lv < connectivity = (maxVal - minVal) * rv + minVal+            | otherwise = 0.0++randList :: (Random a, Floating a) => Int -> StdGen -> [a]+randList n = take n. unfoldr (Just. random)+{-# SPECIALISE randList :: Int -> StdGen -> [Float] #-}+{-# SPECIALISE randList :: Int -> StdGen -> [Double] #-}
+ rc/RC/NTC.hs view
@@ -0,0 +1,146 @@+-- = Nonlinear transient computing+--+-- This module was developed as a part of author's PhD project:+-- https://www.researchgate.net/project/Theory-and-Modeling-of-Complex-Nonlinear-Delay-Dynamics-Applied-to-Neuromorphic-Computing+--++{-# LANGUAGE BangPatterns #-}++module RC.NTC+  ( new+  , learn+  , predict+  , par0+  , NTCParameters (..)+  , DDEModel.Par (..)+  , DDEModel.BandpassFiltering (..)+  ) where++import           Numeric.LinearAlgebra+import           System.Random ( StdGen+                               , split+                               )+import qualified Data.Vector.Storable as V+import qualified Learning+import qualified Numeric.DDE as DDE+import qualified Numeric.DDE.Model as DDEModel++import qualified RC.Helpers as H++-- | DDE reservoir abstraction+newtype Reservoir = Reservoir { _transform :: Matrix Double -> Matrix Double }++data NTCParameters = Par+  { _preprocess :: Matrix Double -> Matrix Double+    -- ^ Modify data before masking (e.g. compression)+  , _inputWeightsRange :: (Double, Double)  -- ^ Input weights (mask) range+  , _inputWeightsGenerator :: StdGen -> (Int, Int) -> (Double, Double) -> Matrix Double+  , _postprocess :: Matrix Double -> Matrix Double+  -- ^ Modify data before training or prediction (e.g. add biases)+  , _reservoirModel :: DDEModel.Par+  }++data NTC = NTC+  { _inputWeights :: Matrix Double+  , _reservoir :: Reservoir+  , _outputWeights :: Maybe (Matrix Double)+  -- ^ Trainable part of NTC+  , _par :: NTCParameters+  }++new+  :: StdGen+  -> NTCParameters+  -> (Int, Int, Int)+  -- ^ Input dimension, network nodes, and output dimension+  -> NTC+new g par (ind, nodes, out) =+  let iwgen = _inputWeightsGenerator par+      iw = iwgen g (nodes, ind) (_inputWeightsRange par)+      ntc = NTC { _inputWeights = iw+                , _reservoir = genReservoir (_reservoirModel par)+                , _outputWeights = Nothing+                , _par = par+                }+  in ntc++-- | Default NTC parameters+par0 :: NTCParameters+par0 = Par+  { _preprocess = id+  , _inputWeightsGenerator = H.randMatrix+  , _postprocess = H.addBiases  -- Usually `id` will work+  , _inputWeightsRange = undefined  -- To be manually set, e.g. (-1, 1)+  , _reservoirModel = DDEModel.RC { DDEModel._filt = filt'+                                  , DDEModel._rho = 3.25+                                  , DDEModel._fnl = H.hsigmoid (1.09375, 1.5, 0.0)+                                  }+  }+  where+    filt' = DDEModel.BandpassFiltering {+              DDEModel._tau = 7.8125e-3+            , DDEModel._theta = recip 0.34375+            }++genReservoir :: DDEModel.Par -> Reservoir+genReservoir par = Reservoir _r+  where+    _r sample = unflatten response+      where+        flatten' = flatten. tr+        unflatten = tr. reshape nodes++        oversampling = 1 :: Int  -- No oversampling+        detuning = 1.0 :: Double  -- Delay detuning factor, 1 = no detuning+        nodes = rows sample+        delaySamples = round $ detuning * fromIntegral (oversampling * nodes)++        -- Matrix to timetrace+        trace1 = flatten' sample++        -- Duplicate the last element (DDE.integHeun2_2D consumes one extra input)+        trace = trace1 V.++ V.singleton (V.last trace1)++        tau = DDEModel._tau $ DDEModel._filt par+        hStep = tau / 2++        !(_, !response) = DDE.integHeun2_2D delaySamples hStep (DDEModel.rhs par) (DDE.Input trace)++forwardPass :: NTC -> Matrix Double -> Matrix Double+forwardPass NTC { _par = Par { _preprocess = prep, _postprocess = post }+                , _inputWeights = iw+                , _reservoir = Reservoir res+                } sample =+  let pipeline = post. res. (iw <>). prep+  in pipeline sample++-- | Offline NTC training+learn+  :: NTC+  -> Int+  -- ^ Discard the first N points+  -> Matrix Double+  -- ^ Input matrix of features rows and observations columns+  -> Matrix Double+  -- ^ Desired output matrix of observations columns+  -> Either String NTC+learn ntc forgetPts inp out = ntc'+  where+    state' = (forwardPass ntc inp) ?? (All, Drop forgetPts)+    teacher' = out ?? (All, Drop forgetPts)+    ntc' = case Learning.learn' state' teacher' of+      Nothing -> Left "Cannot create a readout matrix"+      w -> Right $ ntc { _outputWeights = w }++predict :: NTC+        -> Int+        -> Matrix Double+        -> Either String (Matrix Double)+predict ntc@NTC { _outputWeights = ow+                } forgetPts inp =+  case ow of+    Nothing -> Left "Please train the NTC first"+    Just w -> let y = forwardPass ntc inp+                  y2 = y ?? (All, Drop forgetPts)+                  prediction = w <> y2+              in Right prediction
+ test/Spec.hs view
@@ -0,0 +1,2 @@+main :: IO ()+main = putStrLn "Test suite not yet implemented"