Introducing Tensorflow Ruby API

TensorFlow is an extraordinary open source software library for numerical computation using data flow graphs. It was originally developed by researchers and engineers working on the Google Brain Team within Google’s Machine Intelligence research organisation for the purpose of conducting machine learning and deep neural networks research, but the system is general enough to be applicable in a wide variety of other domains as well.

TensorFlow comes with an easy to use Python interface and a C++ interface to build and execute your computational graphs. However, Tensorflow is available only in Python, and due to the strong interest from the Ruby community, I took an interest in porting it. I started working on Ruby API with support from Somatic.io and SciRuby foundation and came across some cool things that I would like to share with you. I am a student at Indian Institute of Technology, Kharagpur. I extremely fascinated with open source and Machine learning and decided to take this project for fun.

Project

I developed a simple gem tensorflow.rb and started with making use of SWIG. I have tried countless different wrapper gems and different ideas in many permutations and combinations to finally come up with something that works. I will start the blog with a few introductory examples to give people an idea about what is possible currently and soon enough it would be easy for users to make extensive use of the Tensorflow to accomplish extraordinary tasks such as Image recognition or basic neural networks and much more.

Installation

To install the gem follow the steps here. Now I will try to show you an example of how you can make use of Tensorflow.

Creating and running the graph in ruby

If everything works fine for you then you can run this file.

This program prints the output [[6.0, 5.5], [57.0, 7.4]] which is the result of adding two tensors.

The simplest explanation for this is:

graph = Tensorflow::Graph.new
tensor_1 = Tensorflow::Tensor.new([[2, 2.3], [ 10, 6.2]])
tensor_2 = Tensorflow::Tensor.new([[4, 3.2], [ 47, 1.2]])
placeholder_1 = graph.placeholder('tensor1', tensor_1.type_num)
placeholder_2 = graph.placeholder('tensor2', tensor_2.type_num)

Here we define two tensors and then we define two placeholders corresponding to those tensors.

opspec = Tensorflow::OpSpec.new(‘Addition_of_tensors’, ‘Add’, nil, [placeholder_1, placeholder_2])
op = graph.AddOperation(opspec)

Then we specify an operation to add the two placeholders

session_op = Tensorflow::Session_options.new
session = Tensorflow::Session.new(graph, session_op)

Then start a new tensorflow session

hash = {}
hash[placeholder_1] = tensor_1
hash[placeholder_2] = tensor_2
result = session.run(hash, [op.output(0)], [])

Then we define a new hash in ruby with key as the placeholder corresponding to the tensor and value as the tensor and then run the session to get results.

The syntax is very easy to understand as well as produces the right result , so anybody can use it with basic knowledge of ruby / tensorflow. You can also read the documentation.

Is That All ?

Almost everyone can see that the above example simply didn’t live up to the hype, I had been talking about for a while, so I will show you another interesting example of Ruby - Tensorflow.

This example shows you how to get the determinant of a batch of matrices. If you look closely, this is very similar to the previous example with the difference being that I only have a single input and the op used is BatchMatrixDeterminant. The resultant is [[-45.0, -513.0, 1.0]] which is the determinant for the first, second and third matrix. Actually you can do a LOT of good things such as

  1. Arithmetic Operators
    1. Addition 
    2. Subtraction 
    3. Element wise multiplication
    4. Element wise Mod etc.
    ….
  2. Basic Math Functions
    1. Element wise exponent 
    2. Element wise power
    3. Element wise Log
    4. Trigonometric operations like tan, sin, cos 
    ….
  3. Matrix Functions (These are the best)
    1. Matrix Inversion
    2. Matrix multiplication
    3. Determinants, diagonal, trace
    4. Solving a system of linear equations
    5. cholesky decomposition etc.
    ….
    ….

Actually, everything mentioned here in Arithmetic Operators, Basic Math functions and matrix functions is also possible in ruby tensorflow.

You can also do Complex number functions too (like multiplying complex matrices). If you wish to see how these functions are used, take a look at this spec file. Also you can understand the usage of ops by looking at this file.

Aside from this, you can take a look at tutorials on image recognition and protocol buffers in tensorflow.rb

Note for Developers

I researched how the Python libs works internally, and basically, the plan is to generate the graph and plan how to execute it is managed from Python that sends all the graph to be executed to the C++ libraries, this libs take the graph and executes all the nodes of the graph. Therefore, what we need to do is to port the graph generation, and planning code from Python to Ruby, and relying on the same C++ libraries for execution.

There are a lot of useful ideas that I would like to share with developers in my upcoming blogs. If you find a conflicting definition of anything, feel free to comment below. I would love to have a discussion with tensorflow people.

Acknowledgements

Special Thanks to Jason toy (Founder somatic), Soon Hin Khor (Phd. Univ. of Tokyo) and Sameer Deshmukh (Founder Daru and member of Sciruby) for being the the mentors for this project. They have been very supportive to me with everything, and I am very grateful to them.

List of Contributors

  1. Christian Hansen
  2. Geoffrey Litt
  3. Sebastian Deutsch
  4. Victor Shepelev