[WIP] RubyでONNXフォーマットのDNNの推論を可能にするExtensionを開発

この度、RubyでCPUによるDeep Neural Networkの推論を可能にするExtensionを開発開始しました。

正確には、ONNXフォーマットで出力されたDNNモデルパラメータを用いて推論を行うC++ベースのライブラリInstant(解説記事)のRubyラッパーを開発しています。

機能概要

  • C++ベースのInstantの性能をほぼそのまま活用できる
    • 任意の層のノード値へのアクセスが可能
    • mkl-dnnベースの高速推論
    • バッチサイズ指定により複数画像に対する同時推論が可能
  • 入出力をRubyのデータ型に適切にバインドしている
    • 1バッチあたりの入力はRMagickのImageオブジェクトの配列
    • 推論結果をHash/Array形式で取得可能

Rubyコードの実装例

本家のC++による実装例と同等の処理を、このように書けます。
兎にも角にも実装例をご覧ください。

require 'rmagick'
include Magick

require './instant'

# load ONNX file
onnx_obj = Instant.new("../data/VGG16.onnx")

CONV1_1_IN_NAME = "140326425860192"
FC6_OUT_NAME = "140326200777976"
SOFTMAX_OUT_NAME = "140326200803680"

# load dataset
imagelist = [
  "../data/Light_sussex_hen.jpg",
  "photo/flower.JPG",
  "photo/Vatican.JPG",
  "photo/chocolate.jpg",
  "photo/dog.JPG",
  "photo/formula1car.jpg",
  "photo/laptoppc.JPG",
  "photo/polarbear.JPG",
  "photo/tipa.JPG",
  "photo/cherryblossom.JPG",
  "photo/relakkuma.JPG",
]

# conditions for inference
condition = {
  :batch_size => imagelist.length,
  :channel_num => 3,
  :height => 224,
  :width => 224,
  :input_layer => CONV1_1_IN_NAME,
  :output_layers => [FC6_OUT_NAME, SOFTMAX_OUT_NAME]
}

# prepare dataset
imageset = imagelist.map do |image_filepath|
  image = Image.read(image_filepath).first
  image.resize_to_fill(condition[:width], condition[:height])
end

# make model for inference under 'condition'
model = onnx_obj.make_model(condition)

# execute inference
inference_results = model.inference(imageset)

# load category definition
categories = File.read('../data/synset_words.txt').split("\n")

TOP_K = 5
inference_results.zip(imagelist).each do |inference_result, image_filepath|
  puts "=== Result for #{image_filepath} ==="

  # sort by score
  sorted_result = inference_result[SOFTMAX_OUT_NAME].zip(categories).sort_by{|x| -x[0]}

  # display result
  sorted_result[0, TOP_K].each do |score, category|
  puts "#{category} : #{score}"
  end
end

実行結果(先頭1件分)

$ ruby ./test.rb 
=== Result for ../data/Light_sussex_hen.jpg ===
n01514859 hen : 0.9054788947105408
n01807496 partridge : 0.03229297325015068
n01514668 cock : 0.031027931720018387
n01797886 ruffed grouse, partridge, Bonasa umbellus : 0.014490845613181591
n01798484 prairie chicken, prairie grouse, prairie fowl : 0.0016611808678135276

開発レポジトリ

2018/01/07時点では、InstantのForkとして開発中です。
Instantと本Extensionの実装が落ち着いたらレポジトリを独立にしたうえで、gemによる配布もしたいと考えています。

(進捗に応じてこの記事も編集していきます)

開発TODO

  • ビルド作業の簡略化・自動化
  • 異常系対処の実装

開発の背景

Python系の推論環境はChainerやTensorFlow、PyTorchなどのフレームワークの充実によって多数存在しましたが、Rubyにおける選択肢はスクラッチで再実装するか、プロセスコールやPyCall等を用いて他の言語に依存する手法が一般的でした。
今回、@okdshinさんが
Instantを開発・公開しました。これをRubyから呼び出せるようにすれば様々な可能性が広がると感じたため、開発に着手しました。

今後の展望

Instant作者の@okdshinさんとは、普段私と同じフロアで働く仲なので、今後も連携を強めて展開していきたいと思います!

ONNXフォーマットはMicrosoftとFacebookが提唱し、普及を進めているもので、Chainerもサポートを進めている状況です。学習と推論の分離、フレームワーク間の互換性の向上等、様々な可能性を秘めたフォーマットで、今後も目が離せません。

具体的な推論結果例

下記に上記実装例の実行結果を載せます。

flower.JPG

Category Score
n04522168 vase 0.14624682068824768
n02948072 candle, taper, wax light 0.12000349164009094
n03930313 picket fence, paling 0.10246642678976059
n12620546 hip, rose hip, rosehip 0.043764956295490265
n02206856 bee 0.03839555010199547

Vatican.JPG

Category Score
n03877845 palace 0.9945957064628601
n04486054 triumphal arch 0.0019427633378654718
n03781244 monastery 0.0006744712009094656
n03837869 obelisk 0.00033667951356619596
n02980441 castle 0.0003334969806019217

chocolate.jpg

Category Score
n03314780 face powder 0.27068012952804565
n04019541 puck, hockey puck 0.1563795506954193
n03937543 pill bottle 0.14620213210582733
n02877765 bottlecap 0.10574431717395782
n04116512 rubber eraser, rubber, pencil eraser 0.0716797411441803

dog.JPG

Category Score
n02105505 komondor 0.30265742540359497
n02085936 Maltese dog, Maltese terrier, Maltese 0.10685333609580994
n02098413 Lhasa, Lhasa apso 0.07794724404811859
n02113624 toy poodle 0.06806328147649765
n02105641 Old English sheepdog, bobtail 0.028750602155923843

formula1car.jpg

Category Score
n04037443 racer, race car, racing car 0.22242484986782074
n03977966 police van, police wagon, paddy wagon, patrol wagon, wagon, black Maria 0.10872112214565277
n03417042 garbage truck, dustcart 0.0702013298869133
n03602883 joystick 0.06894396990537643
n03791053 motor scooter, scooter 0.06231105327606201

laptoppc.JPG

Category Score
n03832673 notebook, notebook computer 0.39376965165138245
n03085013 computer keyboard, keypad 0.1367684155702591
n03642806 laptop, laptop computer 0.13363485038280487
n04264628 space bar 0.07292277365922928
n03485407 hand-held computer, hand-held microcomputer 0.054601266980171204

polarbear.JPG

Category Score
n02134084 ice bear, polar bear, Ursus Maritimus, Thalarctos maritimus 0.9999891519546509
n02120079 Arctic fox, white fox, Alopex lagopus 4.301877197576687e-06
n02132136 brown bear, bruin, Ursus arctos 2.4333951387234265e-06
n02114548 white wolf, Arctic wolf, Canis lupus tundrarum 1.4043683904674253e-06
n02104029 kuvasz 1.132186412178271e-06

tipa.JPG

Category Score
n02110627 affenpinscher, monkey pinscher, monkey dog 0.47548773884773254
n02096177 cairn, cairn terrier 0.1800858974456787
n02328150 Angora, Angora rabbit 0.07240748405456543
n02097298 Scotch terrier, Scottish terrier, Scottie 0.06806369125843048
n02096294 Australian terrier 0.02631850726902485

cherryblossom.JPG

Category Score
n02206856 bee 0.30947500467300415
n02219486 ant, emmet, pismire 0.2313130646944046
n11939491 daisy 0.10648820549249649
n03476684 hair slide 0.10484256595373154
n03991062 pot, flowerpot 0.05003173649311066

relakkuma.JPG

Category Score
n03630383 lab coat, laboratory coat 0.7959275245666504
n04501370 turnstile 0.031312499195337296
n03868863 oxygen mask 0.011007886379957199
n02992529 cellular telephone, cellular phone, cellphone, cell, mobile phone 0.005440668202936649
n03891332 parking meter 0.00535581074655056
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.