Resnet18 image classification
File.cd!(__DIR__)
# for windows JP
# System.shell("chcp 65001")
Mix.install(
[
{:axon_interp, "~> 0.1.0"},
{:cimg, "~> 0.1.14"},
{:nx, "~> 0.4.0"},
{:kino, "~> 0.7.0"}
],
config: [
nx: [default_defn_options: [compiler: EXLA]]
]
# system_env: [{"NNINTERP", "Axon"}]
)
0.Original work
torchvision.models.resnet18 - pre-trained model included in Pytorch.
Thanks a lot!!!
Implementation with AxonInterp in Elixir
1.Defining the inference module: ResNet18
-
Model
resnet18.axon: get from “https://github.com/shoz-f/axon_interp/releases/download/0.0.1/resnet18.axon” if not existed. -
Pre-processing
Resize the input image to the size{@width, @height}
and gaussian normalize. -
Post-processing
Sort outputs and take first item.
defmodule Resnet18 do
@width 224
@height 224
use AxonInterp,
model: "./model/resnet18.onnx",
url: "https://github.com/shoz-f/axon_interp/releases/download/0.0.1/resnet18.onnx",
inputs: [f32: {1, 3, @height, @width}],
outputs: [f32: {1, 1000}]
@imagenet1000 (for item <- File.stream!("./model/imagenet1000.label") do
String.trim_trailing(item)
end)
|> Enum.with_index(&{&2, &1})
|> Enum.into(%{})
def apply(img, top \\ 1) do
# preprocess
input0 =
CImg.builder(img)
|> CImg.resize({@width, @height})
|> CImg.to_binary([{:gauss, {{123.7, 58.4}, {116.3, 57.1}, {103.5, 57.4}}}, :nchw])
# prediction
output0 =
session()
|> AxonInterp.set_input_tensor(0, input0, [:binary])
|> AxonInterp.invoke()
|> AxonInterp.get_output_tensor(0)
|> Nx.squeeze()
# postprocess
then(Nx.exp(output0), fn exp -> Nx.divide(exp, Nx.sum(exp)) end)
|> Nx.argsort(direction: :desc)
|> Nx.slice([0], [top])
|> Nx.to_flat_list()
|> Enum.map(&@imagenet1000[&1])
end
end
Launch Resnet18
.
# AxonInterp.stop(Resnet18)
Resnet18.start_link([])
Display the properties of the Resnet18
model.
AxonInterp.info(Resnet18)
2.Let’s try it
Load a photo and apply Resnet18 to it.
img = CImg.load("lion.jpg")
Kino.render(CImg.display_kino(img, :jpeg))
Resnet18.apply(img, 3)
3.Appendix - How to convert Pytorch model to Axon
STEP1.
Create Onnx model from torchvision.models.resnet18.
mk_resnet18_onnx.py
import os
import torch
import torchvision.models as models
model = models.resnet18(weights='DEFAULT')
model.eval()
dummy_input = torch.randn(1, 3, 224, 224)
os.makedirs("data", exist_ok=True)
torch.onnx.export(model,
dummy_input,
"data/resnet18.onnx",
verbose=False,
input_names=["input.0"],
output_names=["output.0"],
export_params=True
)
STEP2.
Convert Onnx model to Axon’s graph and parameter.
mk_resnet18_axon.exs
Mix.install([
{:axon_onnx, "~> 0.3.0"}
])
AxonOnnx.import("data/resnet18.onnx")
|> then(fn {model, params} -> Axon.serialize(model, params) end)
|> (&File.write("data/resnet18.axon", &1)).()
□