【硬核】自己動手實(shí)現(xiàn)輕量級神經(jīng)網(wǎng)絡(luò)推理框架
點(diǎn)擊上方“視學(xué)算法”,選擇加"星標(biāo)"或“置頂”
重磅干貨,第一時間送達(dá)
導(dǎo)讀
本文介紹了作者編寫的 Planer (Powerful Light Artificial NEuRon)框架,該框架僅依賴 NumPy 作為其矩陣計(jì)算庫,通過正則表達(dá)式對 PyTorch 模型 TorchScript 進(jìn)行解析實(shí)現(xiàn)模型自動轉(zhuǎn)換到 Planer 框架進(jìn)行推理。 作者已經(jīng)轉(zhuǎn)換了多種 CNN 模型在 Planer 實(shí)現(xiàn)成功推理。
介紹:
前段時間投入了大量的時間與精力編寫了 Planer (Powerful Light Artificial NEuRon)框架,該框架僅依賴 NumPy 作為其矩陣計(jì)算庫,并設(shè)計(jì)了 JSON 格式的及其精簡的中間表達(dá)格式。最終通過正則表達(dá)式對 PyTorch 模型 TorchScript 進(jìn)行解析實(shí)現(xiàn)模型自動轉(zhuǎn)換到 Planer 框架進(jìn)行推理。筆者已經(jīng)轉(zhuǎn)換了多種 CNN 模型在 Planer 實(shí)現(xiàn)成功推理。同時,筆者希望 Planer 能夠成為在對部署難度有要求的計(jì)算環(huán)境中成為有競爭力的一個框架。Planer 在設(shè)計(jì)之初就考慮到 了可擴(kuò)展性以及可移植性,筆者編寫的另一個目的是希望大家能夠加入完善 Planer 的隊(duì)伍當(dāng)中,實(shí)現(xiàn)更多的 Layer 并支持更多更新的模型,讓 Planer 的生態(tài)壯大起來。
https://github.com/Image-Py/planergithub.com
下圖是已經(jīng)成功轉(zhuǎn)換的PyTorch訓(xùn)練好的模型在Planer上實(shí)現(xiàn)推理(HED邊緣檢測、CRAFT場景文字檢測、ResNet18、ESRGAN超分辨率、UNet以及YOLO-v3)。Image-Py/planer(https://github.com/Image-Py/planer)下圖是已經(jīng)成功轉(zhuǎn)換的PyTorch訓(xùn)練好的模型在Planer上實(shí)現(xiàn)推理(HED邊緣檢測、CRAFT場景文字檢測、ResNet18、ESRGAN超分辨率、UNet以及YOLO-v3)。

特點(diǎn):
純NumPy實(shí)現(xiàn),依賴簡單、部署快捷 非常精簡的IR實(shí)現(xiàn),基于JSON 自帶模型可視化(基于networkx) 支持模型從PyTorch自動轉(zhuǎn)換 比較豐富的示例CNN模型
頂層設(shè)計(jì):
我們要設(shè)計(jì)一個神經(jīng)網(wǎng)絡(luò)推理框架,首先要先把框架的頂層設(shè)計(jì)想好。我們的目的是實(shí)現(xiàn)一個部署友好、自主可控且輕量級的推理框架。部署友好如何實(shí)現(xiàn)?因?yàn)橥评砜蚣艿谋举|(zhì)還是涉及到數(shù)據(jù)的計(jì)算,我們采用NumPy來支撐我們所有的計(jì)算。同時為了做到輕量級,我們將所有神經(jīng)網(wǎng)絡(luò)中涉及到比較單獨(dú)的部分統(tǒng)稱為Layer,比如卷積層、全連接層以及非線性激活函數(shù)等。同時這種設(shè)計(jì)方式使得以后對框架進(jìn)行擴(kuò)充只需要再實(shí)現(xiàn)新的Layer功能就好。這里我們給出我們Layer這個基本類的Python抽象:
class Layer:name = 'layer'def __init__(self, name):self.name = namedef forward(self, x): passdef backward(self, grad_y): passdef para(self): return Nonedef load(self, buf): return 0def __call__(self, x):return self.forward(x)
Layer中最重要的兩個api就是前向計(jì)算 forward 以及參數(shù)加載load。這個設(shè)計(jì)基本上可以覆蓋大部分的模型中所涉及到的層與操作。同時我們這種統(tǒng)一的Layer 設(shè)計(jì),可以統(tǒng)一有訓(xùn)練參數(shù)層操作(全連接、卷積層等)與無訓(xùn)練參數(shù)操作(激活函數(shù)、池化等)。無訓(xùn)練參數(shù)操作只需要實(shí)現(xiàn)forward即可。為了保證模型在部署加載中的簡便性,我們將所有的權(quán)重都拉直后拼接成一個一維npy文件保存起來,通過NumPy 的io功能實(shí)現(xiàn)模型的保存于加載。同時我們將模型的計(jì)算表示,也就是IR用json文件保存。這樣在實(shí)際部署推理模型的時候,只需要NumPy模塊與一個npy和一個json文件。這樣的設(shè)計(jì)極大程度的較小了部署難度,將所有的業(yè)務(wù)實(shí)現(xiàn)交給NumPy來完成。同時由于PyTorch更加直觀且高效,在研究中廣泛使用。Planer框架主要將PyTorch作為對照,計(jì)算風(fēng)格與api設(shè)計(jì)成與之類似。
構(gòu)建方式:
Planer支持兩種構(gòu)建方式,一種是手動構(gòu)建,基本和PyTorch一樣的實(shí)現(xiàn),另外一種是基于json文件自動生成模型。
手動構(gòu)建:
from planer import *# ========== write a net manually ==========class CustomNet(Net):def __init__(self):self.conv = Conv2d(3, 64, 3, 1)self.relu = ReLU()self.pool = Maxpool(2)self.upsample = UpSample(2)self.concatenate = Concatenate()self.sigmoid = Sigmoid()def forward(self, x):x = self.conv(x)x = self.relu(x)y = self.pool(x)y = self.upsample(y)z = self.concatenate([x, y])return self.sigmoid(z)
JSON構(gòu)建:
# ========== load net from json ==========layer = [('conv', 'conv', (3, 64, 3, 1)),('relu', 'relu', None),('pool', 'maxpool', (2,)),('up', 'upsample', (2,)),('concat', 'concat', None),('sigmoid', 'sigmoid', None)]flow = [('x', ['conv', 'relu'], 'x'),('x', ['pool', 'up'], 'y'),(['x','y'], ['concat', 'sigmoid'], 'z')]net = Net()net.load_json(layer, flow)
模型自動轉(zhuǎn)換(ResNet18、pytorch 1.1.0):
from torchvision.models import resnet18import torchfrom planer import torch2planernet = resnet18(pretrained=True)x = torch.randn(1, 3, 224, 224, device='cpu')torch2planer(net, 'resnet18', x)# then you will get a resnet18.json and resnet18.npy in current folder.from planer import read_netimport planerimport numpy as np# get the planer array libpal = planer.core(np)x = pal.random.randn(1, 3, 224, 224).astype('float32')net = read_net('resnet18')net(x) # use the net to predict youre dataGPU加速:
這里可以直接使用CuPy替換掉NumPy作為backend來進(jìn)行g(shù)pu計(jì)算加速
import planer, cupyplaner.core(cupy) # use cupy as backendimport planer, clpyplaner.core(clpy) # use clpy as backend模型可視化(UNet):

已經(jīng)支持的Layer:
FC、Conv、Flatten、Upsample、MaxPool、BachNorm、ReLU、Sigmoid、LeakyReLU、Softmax等。其實(shí)再有了這些基本的操作后,可以成功推理復(fù)雜的CNN,比如YOLO-v3:

YOLO-v3的成功轉(zhuǎn)換代表了一個里程碑,表示一些基本的模型都可以通過Planer來進(jìn)行推理實(shí)現(xiàn),而且Planer推理只依賴NumPy,這使得使用Planer可以大幅度降低部署難度與門檻。同時我正在寫一本詳細(xì)講解Planer的電子書《動手編寫深度學(xué)習(xí)推理框架 Planer》,第一個版本的電子書已經(jīng)編寫完畢,詳情可以私聊。

點(diǎn)個在看 paper不斷!
