neural-network-hmatrix-0.1.0.0: Data/NeuralNetwork/Backend/HMatrix.hs
{-# LANGUAGE MultiParamTypeClasses, FlexibleContexts, FlexibleInstances #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}
module Data.NeuralNetwork.Backend.HMatrix (
module Data.NeuralNetwork.Backend.HMatrix.Layers,
ByHmatrix(..),
ErrCode(..)
) where
import Data.NeuralNetwork
import Data.NeuralNetwork.Backend.HMatrix.Utils
import Data.NeuralNetwork.Backend.HMatrix.Layers
import Numeric.LinearAlgebra (Vector, Matrix)
import Control.Monad.Except
import Data.Functor.Identity
data ErrCode = ErrMismatch
type Err = ExceptT ErrCode IO
-- the backend type
data ByHmatrix = ByHmatrix
-- with 1D input
instance (TranslateBody s, Component (RunLayer (SpecToTag s))) =>
Backend ByHmatrix (SpecIn1D :++ s) where
type Env ByHmatrix = Err
type ConvertFromSpec (SpecIn1D :++ s) = RunLayer (SpecToTag s)
compile _ (a :++ l)= trans (size Nothing a) l
-- with 2D input
instance (TranslateBody s, Component (RunLayer (SpecToTag s))) =>
Backend ByHmatrix (SpecIn2D :++ s) where
type Env ByHmatrix = Err
type ConvertFromSpec (SpecIn2D :++ s) = RunLayer (SpecToTag s)
compile _ (a :++ l)= trans (size Nothing a) l
instance RunInEnv Identity Err where
run = return . runIdentity
-- It is necessary to propagate the size along the layers,
-- because fullconnect and convolution need to know
-- the previous size.
data Size = D1 Int | D2 Int Int Int
class ComputeSize l where
size :: Maybe Size -> l -> Size
instance ComputeSize SpecIn1D where
size Nothing (In1D n) = D1 n
instance ComputeSize SpecIn2D where
size Nothing (In2D m n) = D2 1 m n
instance ComputeSize SpecReshape2DAs1D where
size (Just (D2 k m n)) _ = D1 (k*m*n)
instance ComputeSize SpecFullConnect where
size _ (FullConnect n) = D1 n
instance ComputeSize SpecConvolution where
size (Just (D2 _ m n)) (Convolution k f p) = D2 k (m+2*p-f+1) (n+2*p-f+1)
instance ComputeSize SpecMaxPooling where
size (Just (D2 k m n)) (MaxPooling s) = D2 k (m `div` s) (n `div` s)
-- translate the body of specification
class TranslateBody s where
type SpecToTag s
trans :: Size -> s -> Err (RunLayer (SpecToTag s))
instance TranslateBody SpecFullConnect where
type SpecToTag SpecFullConnect = S F (T (SinglC :. Vector))
trans (D1 s) (FullConnect n) = do u <- lift $ newFLayer s n
return $ Stack u (Activation (relu, relu'))
trans _ _ = throwError ErrMismatch
instance TranslateBody SpecConvolution where
type SpecToTag SpecConvolution = S C (T (MultiC :. Matrix))
trans (D2 k s t) (Convolution n f p) = do u <- lift $ newCLayer k n f p
return $ Stack u (Activation (relu, relu'))
trans _ _ = throwError ErrMismatch
instance TranslateBody SpecReshape2DAs1D where
type SpecToTag SpecReshape2DAs1D = A
trans (D2 _ _ _) _ = return As1D
trans (D1 _) _ = throwError ErrMismatch
instance TranslateBody SpecMaxPooling where
type SpecToTag SpecMaxPooling = M
trans (D2 _ _ _) (MaxPooling n) = return (MaxP n)
trans (D1 _) _ = throwError ErrMismatch
instance (TranslateBody a, TranslateBody c, ComputeSize a) => TranslateBody (a :++ c) where
type SpecToTag (a :++ b) = S (SpecToTag a) (SpecToTag b)
trans s (a :++ c) = do u <- trans s a
v <- trans (size (Just s) a) c
return $ Stack u v