Skip to content

model converter from Chainer to Flux

License

Notifications You must be signed in to change notification settings

terasakisatoshi/Gomah.jl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

131 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Gomah.jl

Stable Dev CircleCI Build Status Codecov Coveralls

About this repo

  • This repo provides train/inference procedure of MNIST model known as Hello World of Deep Learning on Julia runtime. These techniques are based on Chainer and PyCall.jl.
  • NEW: Add feature to convert ResNet50/Chainer -> ResNet50/Flux.jl

Usage

How to install

  • This package is not registered as official julia package, so called 野良(nora), which means we should specify repository url:
  • Note that Package Gomah.jl depends on PyCall.jl. So before installing, We recommend set environment variable in Julia.
$ julia
julia> ENV["PYTHON"] = Sys.which("python3")
pkg> add https://github.com/terasakisatoshi/Gomah.jl.git
julia> using Gomah

Call Chainer script from Julia via Gomah.jl

  • PyCall.jl provides interface between Python and Julia.
  • This means you can construct training script of Chainer on Julia environment.
  • If you are familiar with some Deep learnig framework, checkout our src/mnist.jl.
  • We provide an example of training MNIST classifier.
$ julia
julia> using Gomah
julia> train()
epoch       main/loss   main/accuracy  validation/main/loss  validation/main/accuracy  elapsed_time
1           0.56446     0.840621       0.28946               0.914727                  3.49408       
2           0.248238    0.927429       0.212789              0.937381                  5.90154       
3           0.189395    0.945183       0.175694              0.948423                  8.43833       
4           0.152917    0.95592        0.145494              0.957898                  10.832        
5           0.128008    0.963307       0.128785              0.962386                  13.2714       
6           0.108765    0.968306       0.121768              0.961222                  15.6906       
7           0.0948146   0.97286        0.103434              0.969201                  18.361        
8           0.0854993   0.974762       0.10229               0.96818                   20.7444       
9           0.0746463   0.977655       0.0916977             0.972739                  23.1146       
10          0.0663983   0.980598       0.0889726             0.972573                  25.5239    
julia> predict()
accuracy for test set = 97.31 [%]

Convert ResNet/Chainer -> ResNet/Flux.jl

  • We found the structure (shape) of parameter i.e. weight of Chainer is similar that of Flux.
  • The structure of weight of Convolution of Chainer is NCHW. On the other hand, Conv of Flux.jl has weight its shape is WHCN, where N is batchsize, H (resp. W) is height (resp. width) of kernel and C is num of channel.
  • We provided script to convert ResNet50 of Chainer to that of Flux.jl
  • Here is a example of How to use converted model. What you have to do is ...
    • Install chainer and chainercv
    • Install Flux.jl, PyCall, Gomah.jl
    • Prepare sample RGB image. e.g. pineapple.png
    • Run the following the script.
using Gomah
using Gomah: L, np, reversedims
using Flux
using PyCall

using Test
using BenchmarkTools

py"""
import chainer
import chainercv
import numpy as np
num = 50
PyResNet = chainercv.links.model.resnet.ResNet
resnet = PyResNet(num, pretrained_model = "imagenet")
img=chainercv.utils.read_image("pineapple.png",dtype=np.float32,alpha="ignore")
img=chainercv.transforms.resize(img,(224,224))
_imagenet_mean = np.array(
            [123.15163084, 115.90288257, 103.0626238],
            dtype=np.float32
        )[:, np.newaxis, np.newaxis]
img=img-_imagenet_mean
img=np.expand_dims(img,axis=0)
resnet.pick=resnet.layer_names
with chainer.using_config('train', False):
    pyret=resnet(img)
    result=np.squeeze(pyret[-1].array)
    chidx=int(np.argmax(result))
    chprob=100*float(result[chidx])
    print(chidx)
    print(chprob)
"""

@testset "regression" begin
    num = 50
    myres = ResNet(num)
    Flux.testmode!.(myres.layers)
    img = reversedims(py"img")
    @show size(img), typeof(img)
    ret, name2data = myres(img)
    for (i,name) in enumerate(myres.layer_names)
        pyr = reversedims(py"pyret[$i-1].array")
        flr = name2data[name]
        @show name, size(flr)
        @test size(pyr) == size(flr)
        @show maximum(abs.(pyr .- flr))
    end
    flidx = argmax(ret)
    flprob = 100ret[argmax(ret)]
    @show flidx,flprob
    @test Int(py"chidx") == flidx[1]-1
    @show Float32(py"chprob") - flprob
end

@testset "benchmark" begin
    num=50
    img = reversedims(py"img")
    myres = ResNet(num)
    chainmodel = Chain(myres.layers...)
    Flux.testmode!(chainmodel)
    @time chainmodel(img)
    @time chainmodel(img)
    @time chainmodel(img)
    @time chainmodel(img)
    @time chainmodel(img)
    @time chainmodel(img)
end

Why Gomah(ごまぁ)?

  • My favorite thing ごまちゃん
  • Inspired by Menoh
  • Gomah.jl will be promoted as DNN inference library (in the future)

Acknowledgement

About

model converter from Chainer to Flux

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project

 

Packages

No packages published