golang实现Open Neural Network Exchange(ONNX)接口的插件库onnx-go的使用
Golang 实现 Open Neural Network Exchange (ONNX) 接口的插件库 onnx-go 的使用
这是一个 Go 语言实现的 Open Neural Network Exchange (ONNX) 接口库。
使用前须知
该项目最初由 owulveryck 创建,并于 2024 年 5 月 31 日归档。Orama 决定重振该项目,并将投入大量努力使其再次闪耀。目前我们正在积极维护它,如果您发现任何问题,请耐心等待。
概述
onnx-go 包含将 ONNX 二进制模型解码为计算后端的基本功能,并可以像其他 Go 库一样在代码中使用。关于 ONNX 的更多信息,请访问 onnx.ai。
ONNX 规范的实现部分支持导入,但不支持导出。
愿景声明
对于需要在其代码中添加机器学习功能的 Go 开发者来说,onnx-go 是一个便于使用神经网络模型(软件 2.0)的包。与任何其他计算库不同,这个包不需要数据科学方面的特殊技能。
警告 API 是实验性的,可能会发生变化。
免责声明
这是一个新版本的 API。Gorgonia 的调整版本已被移除,现在与 Gorgonia 的主分支兼容。不过,一些操作符尚不可用。
添加了一个实用程序来运行模型库中的模型。请查看 examples
子目录。
安装
通过 go get 安装:
go get github.com/owulveryck/onnx-go
onnx-go 兼容 Go 模块。
示例
这些示例假设您有一个预训练的 model.onnx
文件可用。您可以从 ONNX 模型库下载预训练模型。
非常简单的示例
这个示例只是将图解码到一个简单的后端中。然后您可以对生成的图执行任何操作。
// 创建一个后端接收器
backend := simple.NewSimpleGraph()
// 创建一个模型并设置执行后端
model := onnx.NewModel(backend)
// 读取 onnx 模型
b, _ := ioutil.ReadFile("model.onnx")
// 将其解码到模型中
err := model.UnmarshalBinary(b)
运行预训练模型的简单示例
这个示例使用 Gorgonia 作为后端。
import "github.com/owulveryck/onnx-go/backend/x/gorgonnx"
目前,Gorgonia 没有实现 ONNX 的所有操作符。因此,模型库中的大多数模型都无法工作。通过在后端添加更多操作符,情况会逐渐好转。
您可以在此处找到测试示例的列表和覆盖率。
func Example_gorgonia() {
// 创建一个后端接收器
backend := gorgonnx.NewGraph()
// 创建一个模型并设置执行后端
model := onnx.NewModel(backend)
// 读取 onnx 模型
b, _ := ioutil.ReadFile("model.onnx")
// 将其解码到模型中
err := model.UnmarshalBinary(b)
if err != nil {
log.Fatal(err)
}
// 设置第一个输入,数字取决于模型
model.SetInput(0, input)
err = backend.Run()
if err != nil {
log.Fatal(err)
}
// 检查错误
output, _ := model.GetOutputTensors()
// 将第一个输出写入 stdout
fmt.Println(output[0])
}
模型库
在 examples
子目录中,您将找到一个实用程序来运行模型库中的模型,以及一个使用 Tiny YOLO v2 分析图片的示例实用程序。
内部
ONNX protobuf 定义
onnx 的 protobuf 定义使用经典的 protoc
工具编译成 Go。定义可以在 internal
目录中找到。定义没有暴露出来,以避免对此仓库的外部依赖。实际上,pb 代码可以更改为使用更高效的编译器,例如 gogo protobuf
,并且此更改对包的用户应该是透明的。
执行后端
为了执行神经网络,您需要一个能够执行计算图的后端(有关计算图的更多信息,请阅读此博客文章)。
此图表示机制:
onnx-go 不提供任何可执行的后端,但作为参考,提供了一个构建信息图的简单后端作为示例(请参阅 simple
子包)。Gorgonia 是 ONNX-Go 的主要目标后端。
后端实现
后端基本上是一个可以对其节点应用操作的加权有向图。它应该满足以下接口:
type Backend interface {
OperationCarrier
graph.DirectedWeightedBuilder
}
type OperationCarrier interface {
// 在图的节点上应用操作
// graph.Node 是一个数组,因为它允许处理多个输出
// 例如,一个分割操作返回 n 个节点...
ApplyOperation(Operation, ...graph.Node) error
}
除了操作符,一个节点可以携带一个值。值被描述为 tensor.Tensor
。为了携带数据,图的 Node
应该满足以下接口:
type DataCarrier interface {
SetTensor(t tensor.Tensor) error
GetTensor() tensor.Tensor
}
后端测试
onnx-go 提供了一些实用程序来测试后端。访问 testbackend
包以获取更多信息。
贡献
欢迎贡献。最终将编写贡献指南。同时,您可以提出问题或发送 PR。您也可以通过 Twitter 或 gophers’ slack 联系我(我在两者上都是 @owulveryck)。
该项目旨在成为一个安全、欢迎协作的空间,贡献者应遵守贡献者公约行为准则。
作者
Olivier Wulveryck
许可证
MIT。
更多关于golang实现Open Neural Network Exchange(ONNX)接口的插件库onnx-go的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang实现Open Neural Network Exchange(ONNX)接口的插件库onnx-go的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
使用onnx-go实现ONNX接口的Golang插件库
ONNX (Open Neural Network Exchange) 是一种用于表示深度学习模型的开放格式,onnx-go是一个Golang实现的ONNX运行时库,允许在Go环境中加载和运行ONNX模型。
安装onnx-go
首先安装onnx-go库:
go get github.com/owulveryck/onnx-go
基本使用示例
1. 加载ONNX模型
package main
import (
"fmt"
"log"
"os"
"github.com/owulveryck/onnx-go"
"gorgonia.org/tensor"
)
func main() {
// 1. 加载ONNX模型文件
model := onnx.NewModel(onnx.NewGraph())
file, err := os.Open("model.onnx")
if err != nil {
log.Fatal(err)
}
defer file.Close()
err = model.UnmarshalBinary(file)
if err != nil {
log.Fatal(err)
}
// 2. 准备输入数据
inputT := tensor.New(
tensor.WithShape(1, 3, 224, 224), // 示例输入形状
tensor.WithBacking([]float32{...}), // 填入实际输入数据
)
// 3. 创建输入输出映射
input := make(map[string]interface{})
output := make(map[string]interface{})
// 获取输入节点名称(通常需要查看模型文档)
inputName := model.Graph().Input[0].Name
input[inputName] = inputT
// 4. 运行模型
err = model.Run(input, output)
if err != nil {
log.Fatal(err)
}
// 5. 获取输出
for name, value := range output {
fmt.Printf("Output %v: %v\n", name, value)
}
}
2. 使用后端加速
onnx-go支持不同的后端计算引擎,例如Gorgonia:
import (
"github.com/owulveryck/onnx-go/backend/x/gorgonnx"
)
func main() {
// 创建带有Gorgonia后端的模型
backend := gorgonnx.NewGraph()
model := onnx.NewModel(backend)
// 其余代码与前面相同...
}
高级用法
1. 处理多输入输出
// 准备多个输入
input1 := tensor.New(tensor.WithShape(1, 3), tensor.WithBacking([]float32{1, 2, 3}))
input2 := tensor.New(tensor.WithShape(1, 2), tensor.WithBacking([]float32{4, 5}))
inputs := map[string]interface{}{
"input1": input1,
"input2": input2,
}
outputs := make(map[string]interface{})
err := model.Run(inputs, outputs)
if err != nil {
log.Fatal(err)
}
for name, value := range outputs {
fmt.Printf("%s: %v\n", name, value)
}
2. 获取模型元信息
// 获取模型输入输出信息
fmt.Println("Model inputs:")
for _, input := range model.Graph().Input {
fmt.Printf(" Name: %v\n", input.Name)
fmt.Printf(" Type: %v\n", input.Type)
}
fmt.Println("Model outputs:")
for _, output := range model.Graph().Output {
fmt.Printf(" Name: %v\n", output.Name)
fmt.Printf(" Type: %v\n", output.Type)
}
注意事项
- 性能考虑:Golang不是深度学习的主流语言,onnx-go的性能可能不如Python实现
- 操作符支持:不是所有ONNX操作符都被完全支持,使用前需检查兼容性
- 模型转换:确保模型已正确转换为ONNX格式
- 输入输出形状:需要与模型期望的形状完全匹配
完整示例:图像分类
package main
import (
"fmt"
"log"
"os"
"github.com/owulveryck/onnx-go"
"github.com/owulveryck/onnx-go/backend/x/gorgonnx"
"gorgonia.org/tensor"
)
func main() {
// 1. 初始化模型
backend := gorgonnx.NewGraph()
model := onnx.NewModel(backend)
// 2. 加载ONNX模型
file, err := os.Open("resnet18.onnx")
if err != nil {
log.Fatal(err)
}
defer file.Close()
err = model.UnmarshalBinary(file)
if err != nil {
log.Fatal(err)
}
// 3. 准备输入数据 (假设是1x3x224x224的图片)
inputData := make([]float32, 1*3*224*224)
// 这里应该填充实际的图像数据,通常需要预处理(归一化等)
inputT := tensor.New(
tensor.WithShape(1, 3, 224, 224),
tensor.WithBacking(inputData),
)
// 4. 运行推理
input := map[string]interface{}{"input.1": inputT}
output := map[string]interface{}{}
err = model.Run(input, output)
if err != nil {
log.Fatal(err)
}
// 5. 处理输出 (假设输出是1x1000的类别概率)
outputTensor := output["output"].(*tensor.Dense)
probabilities := outputTensor.Data().([]float32)
// 找到最高概率的类别
maxIndex, maxProb := 0, float32(0)
for i, prob := range probabilities {
if prob > maxProb {
maxIndex, maxProb = i, prob
}
}
fmt.Printf("Predicted class: %d with probability: %.2f%%\n",
maxIndex, maxProb*100)
}
onnx-go为Golang开发者提供了在Go生态中使用ONNX模型的途径,虽然功能可能不如Python生态完善,但对于需要集成深度学习模型到Go应用中的场景是一个有价值的工具。