1. 开放神经网络交换,提出用来表示深度学习模型的开放格式。所谓开放就是ONNX定义了一组和环境,平台均无关的标准格式,来增强各种AI模型的可交互性。即无论使用何种训练框架训练模型(比如TensorFlow/Pytorch/OneFlow/Paddle),在训练完毕后都可以将这些框架的模型统一转换为ONNX这种统一的格式进行存储。注意ONNX文件不仅仅存储了神经网络模型的权重,同时也存储了模型的结构信息以及网络中每一层的输入输出和一些其它的辅助信息。
  2. 在获得ONNX模型之后,模型部署人员自然就可以将这个模型部署到兼容ONNX的运行环境中去。这里一般还会设计到额外的模型转换工作,典型的比如在Android端利用NCNN部署ONNX格式模型,那么就需要将ONNX利用NCNN的转换工具转换到NCNN所支持的bin和param格式。
  3. ONNX作为一个文件格式,自然需要一定的规则去读取想要的信息或者是写入需要保存信息。ONNX使用的是Protobuf这个序列化数据结构去存储神经网络的权重信息。
  4. Protobuf:
    1. 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。目前提供了 C++、Java、Python 三种语言的 API(摘自官方介绍)。
    2. Protobuf协议是一个以*.proto后缀文件为基础的,这个文件描述了用户自定义的数据结构。自然onnx.proto就是ONNX格式文件了,在这个文件里面以message关键字开头的对象是需要关心的。最核心的几个对象:
      1. ModelProto
      2. GraphProto
      3. NodeProto
      4. ValueInfoProto
      5. TensorProto
      6. AttributeProto
    3. 当加载了一个ONNX之后,获得的就是一个ModelProto,它包含了一些版本信息,生产者信息和一个GraphProto。在GraphProto里面又包含了四个repeated数组,它们分别是node(NodeProto类型),input(ValueInfoProto类型),output(ValueInfoProto类型)和initializer(TensorProto类型),其中node中存放了模型中所有的计算节点,input存放了模型的输入节点,output存放了模型中所有的输出节点,initializer存放了模型的所有权重参数。
    4. ONNX的每个计算节点都会有input和output两个数组,这两个数组是string类型,通过input和output的指向关系,可以利用上述信息快速构建出一个深度学习模型的拓扑图。这里要注意一下,GraphProto中的input数组不仅包含一般理解中的图片输入的那个节点,还包含了模型中所有的权重。例如,Conv层里面的W权重实体是保存在initializer中的,那么相应的会有一个同名的输入在input中,其背后的逻辑应该是把权重也看成模型的输入,并通过initializer中的权重实体来对这个输入做初始化,即一个赋值的过程。
    5. 最后,每个计算节点中还包含了一个AttributeProto数组,用来描述该节点的属性,比如Conv节点或者说卷积层的属性包含group,pad,strides等等
11-27 07:54