ONNX
ONNX là một định dạng đại diện mở dùng trong các model của machine learning, cho phép nhà phát triển AI sử dụng các models trên các libraries và công cụ khác nhau. SINGA hỗ trợ tải các models dạng ONNX trong training và inference, và lưu các models ở dạng ONNX với SINGA APIs (e.g., Module).
SINGA đã được thử nghiệm với phiên bản sau của ONNX.
Phiên bản ONNX | Phiên bản định dạng tệp tin | Opset phiên bản ai.onnx | Opset phiên bản ai.onnx.ml | Opset phiên bản ai.onnx.training |
---|---|---|---|---|
1.6.0 | 6 | 11 | 2 | - |
Sử dụng chung
Tải một ONNX Model trong SINGA
Sau khi tải một ONNX model từ disk qua onnx.load
, bạn chỉ cần cập nhật
batch-size của input sử dụng tensor.PlaceHolder
sau SINGA v3.0, shape của
internal tensors sẽ tự động được tạo ra.
Sau đó, bạn định nghĩa một class thừa hưởng từ sonnx.SONNXModel
và thực hiện
hai phương pháp forward
cho quá trình forward và train_one_batch
cho quá
trình training. Sau khi gọi hàm model.compile
, hàm SONNX sẽ lặp lại và dịch
tất cả các nodes trong phạm vi graph của ONNX model sang các hàm SINGA, tải tất
cả weights đã lưu trữ và tạo ra shape của từng tensor trung gian.
import onnx
from singa import device
from singa import sonnx
class MyModel(sonnx.SONNXModel):
def __init__(self, onnx_model):
super(MyModel, self).__init__(onnx_model)
def forward(self, *x):
y = super(MyModel, self).forward(*x)
# Since SINGA model returns the output as a list,
# if there is only one output,
# you just need to take the first element.
return y[0]
def train_one_batch(self, x, y):
pass
model_path = "PATH/To/ONNX/MODEL"
onnx_model = onnx.load(model_path)
# convert onnx model into SINGA model
dev = device.create_cuda_gpu()
x = tensor.PlaceHolder(INPUT.shape, device=dev)
model = MyModel(onnx_model)
model.compile([x], is_train=False, use_graph=True, sequential=True)
Inference với SINGA model
Sau khi tạo models, bạn có thể tiến hành inference bằng cách gọi hàm
model.forward
. Đầu vào và đầu ra phải ở dạng phiên bản của SINGA Tensor
.
x = tensor.Tensor(device=dev, data=INPUT)
y = model.forward(x)
Lưu model của SINGA dưới dạng ONNX
Với hàm tensors đầu vào và đầu ra được tạo ra bởi các hàm của model, bạn có thể truy nguyên đến tất cả các hàm nội bộ. Bởi vậy, một model SINGA được xác định bởi tensors đầu vào và đầu ra. Để biến một model SINGA sang dạng ONNX, bạn chỉ cần cung cấp danh sách tensor đầu vào và đầu ra.
# x is the input tensor, y is the output tensor
sonnx.to_onnx([x], [y])
Training lại với model ONNX
Để train (hay luyện) một model ONNX sử dụng SINGA, bạn cần thực hiện
train_one_batch
từ sonnx.SONNXModel
và đánh dấu is_train=True
khi gọi hàm
model.compile
.
from singa import opt
from singa import autograd
class MyModel(sonnx.SONNXModel):
def __init__(self, onnx_model):
super(MyModel, self).__init__(onnx_model)
def forward(self, *x):
y = super(MyModel, self).forward(*x)
return y[0]
def train_one_batch(self, x, y, dist_option, spars):
out = self.forward(x)
loss = autograd.softmax_cross_entropy(out, y)
if dist_option == 'fp32':
self.optimizer.backward_and_update(loss)
elif dist_option == 'fp16':
self.optimizer.backward_and_update_half(loss)
elif dist_option == 'partialUpdate':
self.optimizer.backward_and_partial_update(loss)
elif dist_option == 'sparseTopK':
self.optimizer.backward_and_sparse_update(loss,
topK=True,
spars=spars)
elif dist_option == 'sparseThreshold':
self.optimizer.backward_and_sparse_update(loss,
topK=False,
spars=spars)
return out, loss
def set_optimizer(self, optimizer):
self.optimizer = optimizer
sgd = opt.SGD(lr=0.005, momentum=0.9, weight_decay=1e-5)
model.set_optimizer(sgd)
model.compile([tx], is_train=True, use_graph=graph, sequential=True)
Transfer-learning một model ONNX
Bạn cũng có thể thêm một vài layers vào phần cuối của ONNX model để làm
transfer-learning. Hàm last_layers
chấp nhận một số nguyên âm để chỉ layer bị
cắt ra. Ví dụ, -1
nghĩa là bị cắt ra sau kết quả cuối cùng (không xoá bớt
layer nào) -2
nghĩa là bị cắt ra sau hai layer cuối cùng.
from singa import opt
from singa import autograd
class MyModel(sonnx.SONNXModel):
def __init__(self, onnx_model):
super(MyModel, self).__init__(onnx_model)
self.linear = layer.Linear(1000, 3)
def forward(self, *x):
# cut off after the last third layer
# and append a linear layer
y = super(MyModel, self).forward(*x, last_layers=-3)[0]
y = self.linear(y)
return y
def train_one_batch(self, x, y, dist_option, spars):
out = self.forward(x)
loss = autograd.softmax_cross_entropy(out, y)
if dist_option == 'fp32':
self.optimizer.backward_and_update(loss)
elif dist_option == 'fp16':
self.optimizer.backward_and_update_half(loss)
elif dist_option == 'partialUpdate':
self.optimizer.backward_and_partial_update(loss)
elif dist_option == 'sparseTopK':
self.optimizer.backward_and_sparse_update(loss,
topK=True,
spars=spars)
elif dist_option == 'sparseThreshold':
self.optimizer.backward_and_sparse_update(loss,
topK=False,
spars=spars)
return out, loss
def set_optimizer(self, optimizer):
self.optimizer = optimizer
sgd = opt.SGD(lr=0.005, momentum=0.9, weight_decay=1e-5)
model.set_optimizer(sgd)
model.compile([tx], is_train=True, use_graph=graph, sequential=True)
ONNX model zoo
ONNX Model Zoo là tổ hợp các models ở dạng ONNX, đã được train có kết quả tốt nhất, đóng góp bởi cộng đồng thành viên. SINGA giờ đây đã hỗ trợ một số models CV và NLP. Chúng tôi dự định sẽ sớm hỗ trợ thêm các models khác.
Phân loại hình ảnh (Image Classification)
Tổ hợp models này có đầu vào là hình ảnh, sau đó phân loại các đối tượng chính trong hình ảnh thành 1000 mục đối tượng như bàn phím, chuột, bút chì, và các động vật.
Model Class | Tham khảo | Mô tả | Đường dẫn |
---|---|---|---|
MobileNet | Sandler et al. | deep neural network nhỏ, nhẹ phù hợp nhất cho điện thoại và ứng dụng hình ảnh đính kèm. Top-5 error từ báo cáo - ~10% | |
ResNet18 | He et al. | Mô hình CNN (lên tới 152 layers). Sử dụng liên kết ngắn gọn để đạt độ chính xác cao hơn khi phân loại hình ảnh. Top-5 error từ báo cáo - ~3.6% | |
VGG16 | Simonyan et al. | Mô hình CNN chuyên sâu (lên tới 19 layers). Tương tự như AlexNet nhưng sử dụng nhiều loại filters cỡ kernel nhỏ hơn mang lại độ chính xác cao hơn khi phân loại hình ảnh. Top-5 từ báo cáo - ~8% | |
ShuffleNet_V2 | Simonyan et al. | Mô hình CNN cực kỳ hiệu quả trong sử dụng tài nguyên, được thiết kế đặc biệt cho các thiết bị di động. Mạng lưới thiết kế hệ mô hình sử dụng số liệu trực tiếp như tốc độ, thay vì các số liệu gián tiếp như FLOP. Top-1 error từ báo cáo - ~30.6% | [ |
Chúng tôi cung cấp ví dụ re-training sử dụng VGG và ResNet, vui lòng xem tại
examples/onnx/training
.
Nhận Diện Đối Tượng (Object Detection)
Các models Object detection nhận diện sự hiện diện của các đối tượng trong một hình ảnh và phân đoạn ra các khu vực của bức ảnh mà đối tượng được nhận diện.
Model Class | Tham khảo | Mô tả | Đường dẫn |
---|---|---|---|
Tiny YOLOv2 | Redmon et al. | Mô hình CNN thời gian thực cho Nhận diện đối tượng có thể nhận diện 20 loại đối tượng khác nhau. Phiên bản nhỏ của mô hình phức tạp Yolov2. |
Phân tích Khuôn Mặt (Face Analysis)
Các mô hình Nhận Diện Khuôn Mặt xác định và/hoặc nhận diện khuôn mặt người và các trạng thái cảm xúc trong bức ảnh.
Model Class | Tham khảo | Mô tả | Đường dẫn |
---|---|---|---|
ArcFace | Deng et al. | Mô hình dựa trên CNN để nhận diện khuôn mặt, học từ các đặc tính khác nhau trên khuôn mặt và tạo ra các embeddings cho hình ảnh khuôn mặt đầu vào. | |
Emotion FerPlus | Barsoum et al. | Mô hình CNN chuyên sâu nhận diện cảm xúc được train trên các hình ảnh khuôn mặt. |
Máy Hiểu (Machine Comprehension)
Một dạng của mô hình xử lý ngôn ngữ tự nhiên giúp trả lời câu hỏi trên một đoạn ngôn ngữ cung cấp.
Model Class | Tham khảo | Mô tả | Đường dẫn |
---|---|---|---|
BERT-Squad | Devlin et al. | Mô hình này trả lời câu hỏi dựa trên ngữ cảnh của đoạn văn đầu vào. | |
RoBERTa | Devlin et al. | Mô hình transformer-based kích thước lớn, dự đoán ngữ nghĩa dựa trên đoạn văn đầu vào. | |
GPT-2 | Devlin et al. | Mô hình ngôn ngữ transformer-based kích thước lớn, đưa ra một đoạn chữ, rồi dự đoán từ tiếp theo. | [ |
Các toán tử (Operators) được hỗ trợ
Chúng tôi hỗ trợ các toán tử sau:
- Acos
- Acosh
- Add
- And
- Asin
- Asinh
- Atan
- Atanh
- AveragePool
- BatchNormalization
- Cast
- Ceil
- Clip
- Concat
- ConstantOfShape
- Conv
- Cos
- Cosh
- Div
- Dropout
- Elu
- Equal
- Erf
- Expand
- Flatten
- Gather
- Gemm
- GlobalAveragePool
- Greater
- HardSigmoid
- Identity
- LeakyRelu
- Less
- Log
- MatMul
- Max
- MaxPool
- Mean
- Min
- Mul
- Neg
- NonZero
- Not
- OneHot
- Or
- Pad
- Pow
- PRelu
- Reciprocal
- ReduceMean
- ReduceSum
- Relu
- Reshape
- ScatterElements
- Selu
- Shape
- Sigmoid
- Sign
- Sin
- Sinh
- Slice
- Softmax
- Softplus
- Softsign
- Split
- Sqrt
- Squeeze
- Sub
- Sum
- Tan
- Tanh
- Tile
- Transpose
- Unsqueeze
- Upsample
- Where
- Xor
Các lưu ý đặc biệt cho ONNX backend
Conv, MaxPool và AveragePool
Đầu vào phải có shape 1d
(N*C*H)
và 2d(N*C*H*W
) trong khidilation
phải là 1.BatchNormalization
epsilon
là 1e-05 và không được đổi.Cast
Chỉ hỗ trợ float32 và int32, các dạng khác phải được cast thành hai dạng này.
Squeeze và Unsqueeze
Nếu gặp lỗi khi dùng
Squeeze
hayUnsqueeze
giữaTensor
và Scalar, vui lòng báo cho chúng tôi.Empty tensor Empty tensor không được chấp nhận trong SINGA.
Thực hiện
Mã code của SINGA ONNX được đặt trong python/singa/soonx.py
. Có bốn loại
chính, SingaFrontend
, SingaBackend
, SingaRep
và SONNXModel
.
SingaFrontend
qui đổi mô hình SINGA model sang mô hình ONNX model;
SingaBackend
biến mô hình ONNX model sang đối tượng SingaRep
giúp lưu trữ
tất cả các toán tử SINGA operators và tensors(tensor trong văn bản này nghĩa là
SINGA Tensor
); SingaRep
có thẻ chạy giống như mô hình SINGA model.
SONNXModel
tạo ra từ model.Model
xác định thống nhất API cho SINGA.
SingaFrontend
Hàm function đầu vào của SingaFrontend
là singa_to_onnx_model
cũng được gọi
là to_onnx
. singa_to_onnx_model
tạo ra mô hình ONNX model, và nó cũng tạo ra
một ONNX graph bằng việc sử dụng singa_to_onnx_graph
.
singa_to_onnx_graph
chấp nhận đầu ra của mô hình, và lặp lại đệ quy graph của
mô hình SINGA model từ đầu ra để gom tất cả toán tử tạo thành một hàng. Tensors
đầu vào và trực tiếp, v.d, weights để train, của mô hình SINGA model được chọn
cùng một lúc. Đầu vào được lưu trong onnx_model.graph.input
; đầu ra được lưu
trong onnx_model.graph.output
; và weights để train được lưu trong
onnx_model.graph.initializer
.
Sau đó toán tử SINGA operator trong hàng được đổi sang từng toán tử ONNX
operators. _rename_operators
xác định tên toán tử giữa SINGA và ONNX.
_special_operators
xác định function sử dụng để biến đổi toán tử.
Thêm vào đó, một vài toán tử trong SINGA có các định nghĩa khác với ONNX, chẳng
hạn như, ONNX coi một vài thuộc tính của toán tử SINGA operators là đầu vào, vì
thế _unhandled_operators
xác định function nào dùng để xử lý toán tử đặc biệt.
Do dạng bool được coi là dạng int32 trong SINGA, _bool_operators
địng nghĩa
toán tử có thể chuyển sang dạng bool.
SingaBackend
Function đầu vào của SingaBackend
là prepare
kiểm tra phiên bản nào của mô
hình ONNX model rồi gọi _onnx_model_to_singa_ops
.
Chức năng của _onnx_model_to_singa_ops
là để lấy SINGA tensors và operators.
Các tensors được lưu trong một thư viện, theo tên trong ONNX, và operators được
lưu trong hàng ở dạng namedtuple('SingaOps', ['node', 'operator'])
. Với mỗi
toán tử operator, node
là một ví dụ từ OnnxNode được dùng để lưu các thông tin
cơ bản của ONNX node; operator
là forward function cho toán tử SINGA;
Bước đầu tiên của _onnx_model_to_singa_ops
có bốn bước, đầu tiên là gọi
_parse_graph_params
để lấy tất các các tensors lưu trong params
. Sau đó gọi
hàm _parse_graph_inputs_outputs
để lấy tất cả thông tin đầu vào đầu ra lưu
trong inputs
và outputs
. Cuối cùng nó lặp lại tất cả các nodes trong ONNX
graph và đẩy sang _onnx_node_to_singa_op
như SINGA operators hoặc layers và
lưu chúng thành outputs
. Một vài weights được lưu trong ONNX node gọi là
Constant
, SONNX có thể xử lý chúng bằng _onnx_constant_to_np
để lưu trong
params
.
Cuối cùng class này trả lại một đối tượng SingaRep
và lưu trên params
,
inputs
, outputs
, layers
.
SingaRep
SingaBackend
lưu tất cả SINGA tensors và operators. run
chấp nhận đầu vào
của mô hình và chạy từng toán tử SINGA operators một, theo hàng của toán tử.
Người dùng có thể sử dụng last_layers
để xoá mô hình model sau vài layers cuối
cùng.
SONNXModel
SONNXModel
được tạo từ sonnx.SONNXModel
và thực hiện phương pháp forward
để cung cấp một API đồng bộ với các mô hình SINGA.