Skip to content

A Haskell framework to define valid deep learning models and export them to other frameworks like TensorFlow JS or Keras.

License

Notifications You must be signed in to change notification settings

leopiney/tensor-safe

Repository files navigation


Tensor Safe

tensor-safeis a dependently typed framework to define deep learning models whose structure is verified at compilation time. If the models are valid, these can be compiled to external frameworks, such as Keras framework in Python or JavaScript.

Install instructions

  1. Installtensor-safeexecutable withcabal new-install

    cabal new-install tensor-safe

  2. Installtensor-safelibrary

    cabal new-install tensor-safe --lib

Building instructions and development tools

  1. Installghc-mod,hpackandstylish-haskellwithstack install

    cd ~
    stack install ghc-mod hpack stylish-haskell
    
  2. Runstack buildin project folder

  3. InstallIntero

    Runstack build interoin the project folder

    Ref:https://gitlab /vannnns/haskero/blob/master/client/doc/installation.md

Generate.cabalfile

Runhpackin the root of the project and the filetensor-safe.cabalwill be generated

Model definition

Models can be defined as a type using theMkINetworktype function. TheMkINetworkdefines a valid instance of a Network model given a list ofLayersand a spected input and iutputShapes.

Here's an example of how to define a simple model for theMNISTdataset, usingDenselayers:

typeMNIST=MkINetwork
'[
Flatten,
Dense78442,
Relu,
Dense4210,
Sigmoid
]
('D328281)--Input
('D110)--Output

After that, variable with the model type can be verified with the functionmkINetworklike this:

mnist::MNIST
mnist=mkINetwork

Nesting networks definitions

You can nest networks definitions easily by adding the networks as layers. For example, in the case of theMNISTmodel defined above, we can abstract the use of Dense and a activation function like this:

typeDenseReluio=
MkINetwork'[Denseio,Relu] ('D1i) ('D1o)

typeDenseSigmoidio=
MkINetwork'[Denseio,Sigmoid] ('D1i) ('D1o)

typeMNIST=MkINetwork
'[
Flatten,
DenseRelu78442,
DenseSigmoid4210
]
('D328281)--Input
('D110)--Output

How to extend layers definitions

Since this library only implements a subset of features that Keras implement, it's likely that for new projects you'll need to add new layers. Due to the modularization of the library, this can be done by adding the layer definitions in specific locations of the project:

  1. First, add a new auxiliary layer entry for the data typeDLayerinTensorSafe.Compile.Expr. This will make possible the compilation of the layer for all instances ofGenerator.Also, add to theLayerGeneratorentry for the newly added layer.
  2. Secondly, add the layer definition to theTensorSafe/Layersfolder. You can copy the definitions from the currently defined layers.
  3. Then, import and expose your layer definition in theTensorSafe.Layersmodule.
  4. Finally, declare how your layer transforms a specific Shape in theOuttype function.

Command line interface

This interface will change in the near future

You can installtensor-safecommand line tool by runningstack build.Then you can use it by usingstack exec tensor-safe -- check --path./path-to-model.hsorstack exec tensor-safe -- compile --path./path-to-model.hs --module-name SomeModule.

Tools for JavaScript environment

Add as development dependency the packagesbabel-plugin-tensor-safeandeslint-plugin-tensor-safe.These can be found in theextra/javascriptfolder in this project.

You can add them directly from this project like this:

yarn add --dev file/:<path-to-tensor-safe>/extra/javascript/babel-plugin-tensor-safe

yarn add --dev file/:<path-to-tensor-safe>/extra/javascript/eslint-plugin-tensor-safe

Then add to the.eslintrc.jsfile in your JavaScript project the plugintensor-safeand the ruletensor-safe-model-invalidlike this:

module.exports={
plugins:[
...
"tensor-safe"
],
...
rules:{
...
"tensor-safe/invalid-model":1
...
}
};

And for the Babel plugin add"@babel/plugin-tensor-safe"to the plugins list in the.babelrcfile inside your JavaScript project.

Then, you can write your deep learning model inside your JS files as in the following example:

functioncreateConvModel(){
safeModel`
'[
Conv2D 1 16 3 3 1 1,
Relu,
MaxPooling 2 2 2 2,
Conv2D 16 32 3 3 1 1,
Relu,
MaxPooling 2 2 2 2,
Conv2D 32 32 3 3 1 1,
Relu,
Flatten,
Dense 288 64,
Sigmoid,
Dense 64 10,
Sigmoid
]
('D3 28 28 1) -- Input
('D1 10) -- Output
`;

returnmodel;
}

Related projects

This project was highly influenced byGrenade💣. Grenade is a cool library to define deep neural networks which are validated using dependent types. What differences TensorSafe from Grenade the most is that TensorSafe doesn't run nor train the models, instead, it compiles the model to external languages that are capable of performing all computations – like Keras for Python or JavaScript. Also, TensorSafe doesn't need to specifically declare all Shapes transformations for all the model layers, instead, it just needs the input and output Shapes to validate the model.

Another worth looking library isTensorFlow for Haskell. This library has all bindings for TensorFlow in C. The issue with this is that it doesn't perform a lot of type checkings at compilation time. However, there's an open branch that uses dependent types to solve many of these issues:https://github /helq/tensorflow-haskell-deptyped,but the solution still seems rather complicated for real use.