ONNX interop for Elixir
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
config
lib
test
.formatter.exs
.gitignore
.travis.yml
LICENSE
README.md
mix.exs
mix.lock

README.md

ONNXS

Hex.pm Build Status

ONNXS

/ON-eks-ESS/

noun

1. ONNX interop for Elixir

2. The twenty-first century's yesterday

Overview

The Open Neural Network eXchange format(ONNX) is an open format for representing deep learning models. Because it's an open format supported by various deep learning frameworks, it enables greater interoperation between different toolchains.

ONNXS allows you to decode trained neural network models produced by deep learning frameworks, modify them, and encode them back into the standard ONNX format.

Installation

The package can be installed by adding onnxs to your list of dependencies in mix.exs:

def deps do
  [
    {:onnxs, "~> 0.2.0"}
  ]
end

Usage

ONNXS allows you to decode saved ONNX models into Elixir structs.

iex(1)> {:ok, mnist_data} = File.read "./test/examples/mnist.onnx" 
{:ok,
 <<8, 3, 18, 4, 67, 78, 84, 75, 26, 3, 50, 46, 52, 40, 1, 58, 227, 206, 1, 10,
   199, 80, 18, 12, 80, 97, 114, 97, 109, 101, 116, 101, 114, 49, 57, 51, 26,
   12, 80, 97, 114, 97, 109, 101, 116, 101, 114, 49, ...>>}                 
iex(2)> mnist_struct = Onnx.ModelProto.decode(mnist_data)
%Onnx.ModelProto{
  doc_string: nil,
  domain: nil,
  graph: %Onnx.GraphProto{
    doc_string: nil,
    initializer: [],
    input: [
      %Onnx.ValueInfoProto{
        doc_string: nil,
        name: "Input3",
        type: %Onnx.TypeProto{ 
          value: {:tensor_type,
           %Onnx.TypeProto.Tensor{
             elem_type: 1,
             shape: %Onnx.TensorShapeProto
...
  ir_version: 3,
  metadata_props: [],
  model_version: 1,
  opset_import: [%Onnx.OperatorSetIdProto{domain: "", version: 1}],
  producer_name: "CNTK",
  producer_version: "2.4"
}

Once converted to structs, the models can be modified like any other Elixir struct.

iex(3)> mnist_updated = %{mnist_struct | model_version: 2}

Finally, ONNXS allows you define Elixir data as a struct that can be encoded to valid ONNX.

iex(4)> mnist_map = Map.from_struct(mnist_updated)        
%{
  doc_string: nil,
  domain: nil,
...
  model_version: 2,
  opset_import: [%Onnx.OperatorSetIdProto{domain: "", version: 1}],
  producer_name: "CNTK",
  producer_version: "2.4"
}
iex(5)> new_mnist_struct = Onnx.ModelProto.new(mnist_map)
%Onnx.ModelProto{
  doc_string: nil,
  domain: nil,
...
  producer_name: "CNTK",
  producer_version: "2.4"
}
iex(6)> encoded_mnist = Onnx.ModelProto.encode(new_mnist_struct)         
<<8, 3, 18, 4, 67, 78, 84, 75, 26, 3, 50, 46, 52, 40, 2, 58, 227, 206, 1, 10,
  199, 80, 18, 12, 80, 97, 114, 97, 109, 101, 116, 101, 114, 49, 57, 51, 26, 12,
  80, 97, 114, 97, 109, 101, 116, 101, 114, 49, 57, 51, ...>>
iex(7)> {:ok, file} = File.open "/tmp/mnist_v2.proto", [:write]
{:ok, #PID<0.229.0>}
iex(8)> IO.binwrite file, encoded_mnist
:ok
iex(9)> File.close file
:ok

Implementation

This implementation uses Bing Tony Han's protobuf-elixir library to generate Elixir code from the ONNX proto file.