The tensorflow-ocaml project provides some OCaml bindings for TensorFlow.
An experimental ocaml binding for TensorFlow Eager mode can be found in the ocaml-tensorflow-eager repo.
Use opam to install the tensorflow-ocaml package.
opam install tensorflow
The opam package starting from version 0.0.8 requires the version 1.0 of the TensorFlow library to be installed on your system under the name libtensorflow.so
. The current github tip requires 1.8.
Two possible ways to obtain it are:
-
Build the library from source. Perform the following steps:
-
Install the Bazel build system.
-
Clone the TensorFlow repo:
git clone --recurse-submodules -b r1.0 https://github.com/tensorflow/tensorflow
-
Configure the build (you will be asked if you want to enable CUDA support):
cd tensorflow/ ./configure
-
Compile the library:
bazel build -c opt tensorflow:libtensorflow.so
The binary should appear under
bazel-bin/tensorflow/libtensorflow.so
.
-
-
Use prebuilt binaries from Google. The releases are available for download in URLs of the form:
https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-TYPE-OS-ARCH-VERSION.tar.gz
. For example:
Once you have obtained the library, you should install it system-wise, or add it to the environment variables LIBRARY_PATH
and LD_LIBRARY_PATH
:
export LIBRARY_PATH={path_to_folder_with_libtensorflow.so}:$LIBRARY_PATH
export LD_LIBRARY_PATH={path_to_folder_with_libtensorflow.so}:$LD_LIBRARY_PATH
Download a very simple example and compile it with the following command:
ocamlbuild forty_two.native -use-ocamlfind -pkg tensorflow -tag thread
Then run it via ./forty_two.native
. You should now be all set up, enjoy!
-
When compiling the example with ocamlbuild, I get the following error:
/usr/bin/ld: cannot find -ltensorflow
You should adjust your
LIBRARY_PATH
environment variable to include the directory in which you have addedlibtensorflow.so
. E.g. run:LIBRARY_PATH=/path/to/lib:$LIBRARY_PATH ocamlbuild forty_two.native -use-ocamlfind -pkg tensorflow -tag thread
-
When running
forty_two.native
, I get the following error:./forty_two.native: error while loading shared libraries: libtensorflow.so: cannot open shared object file: No such file or directory
You should adjust your
LD_LIBRARY_PATH
environment variable in the same wayLIBRARY_PATH
was adjusted in the previous case. E.g. run:LD_LIBRARY_PATH=/path/to/lib:$LD_LIBRARY_PATH ./forty_two.native
Note that on OS X, you should adjust your
DYLD_LIBRARY_PATH
environment variable.
Tensorflow-ocaml includes two different APIs to write graphs.
The graph API is very close to the original TensorFlow API.
- Some MNIST based tutorials are available in the examples directory.
examples/load/load.ml
contains a simple example where the TensorFlow graph is loaded from a file (this graph has been generated byexamples/load.py
),examples/basics
contains some curve fitting examples. You will need gnuplot to be installed via opam to run the gnuplot versions.
The FNN API is a layer based API to easily build neural-networks. A linear classifier could be defined and trained in a couple lines:
let input, input_id = Fnn.input ~shape:(D1 image_dim) in
let model =
Fnn.dense label_count input
|> Fnn.softmax
|> Fnn.Model.create Float
in
Fnn.Model.fit model
~loss:(Fnn.Loss.cross_entropy `mean)
~optimizer:(Fnn.Optimizer.gradient_descent ~learning_rate:8.)
~epochs
~input_id
~xs:train_images
~ys:train_labels;
A complete VGG-19 model can be defined as follows:
let vgg19 () =
let block iter ~block_idx ~out_channels x =
List.init iter ~f:Fn.id
|> List.fold ~init:x ~f:(fun acc idx ->
Fnn.conv2d () acc
~name:(sprintf "conv%d_%d" block_idx (idx+1))
~w_init:(`normal 0.1) ~filter:(3, 3) ~strides:(1, 1) ~padding:`same ~out_channels
|> Fnn.relu)
|> Fnn.max_pool ~filter:(2, 2) ~strides:(2, 2) ~padding:`same
in
let input, input_id = Fnn.input ~shape:(D3 (img_size, img_size, 3)) in
let model =
Fnn.reshape input ~shape:(D3 (img_size, img_size, 3))
|> block 2 ~block_idx:1 ~out_channels:64
|> block 2 ~block_idx:2 ~out_channels:128
|> block 4 ~block_idx:3 ~out_channels:256
|> block 4 ~block_idx:4 ~out_channels:512
|> block 4 ~block_idx:5 ~out_channels:512
|> Fnn.flatten
|> Fnn.dense ~name:"fc6" ~w_init:(`normal 0.1) 4096
|> Fnn.relu
|> Fnn.dense ~name:"fc7" ~w_init:(`normal 0.1) 4096
|> Fnn.relu
|> Fnn.dense ~name:"fc8" ~w_init:(`normal 0.1) 1000
|> Fnn.softmax
|> Fnn.Model.create Float
in
input_id, model
This model is used in the following example to classify an input image. In order to use it you will have to download the pre-trained weights.
There are also some MNIST based examples.
A simplified version of char-rnn can also be found in the examples directory which contains additional details.
A stand-alone example of Neural Style transfer can be found in the examples directory.
- jbuilder is used as a build system.
- ocaml-ctypes is used for the C bindings.
- Base is only necessary when generating the TensorFlow graph from OCaml, the wrapper itself does not need it.
- The code in the piqi directory comes from the Piqi project. There is no need to install piqi though.
- Cmdliner is used for command line interfaces.
- Gnuplot-ocaml is an optional dependency used by a couple examples.
- npy-ocaml is used to read/write from npy/npz files.
- camlimages handles loading and writing image files in jpeg/png format.