onnx.reference¶
DefaultNone¶
ReferenceEvaluator¶
- class onnx.reference.ReferenceEvaluator(proto: Any, opsets: dict[str, int] | None = None, functions: list[ReferenceEvaluator | FunctionProto] | None = None, verbose: int = 0, new_ops: list[OpRun] | None = None, optimized: bool = True)[原始碼]¶
計算 ONNX 原型 (ModelProto、FunctionProto、GraphProto、NodeProto) 的輸出。
這是 ONNX 規格的純 Python 實作。官方規格與此處的實作之間可能仍存在不匹配之處。如果發生此類不匹配,則以官方規格為準,覆蓋此實作。
- 參數:
proto –
onnx.ModelProto
、onnx.GraphProto
、onnx.FunctionProto
、onnx.NodeProto
、檔名或位元組verbose – 在執行期間於標準輸出上顯示中間結果
opsets – 如果 proto 是 GraphProto 的執行個體,則 opsets 必須由以下字典定義
functions – 已知的 onnx 函式
new_ops – 此執行階段可用於測試新運算子的實作,new_ops 是衍生自
OpRun
的類別清單,每個類別都必須定義靜態屬性 domain,同一個運算子可能會有多個實作,清單中的第一個實作會被使用。optimized – 有些運算子有兩種實作,一個是符合運算子數學定義的簡單實作,另一個是更有效率的實作。Conv 運算子即為如此。簡單版本比使用分解為 Conv = im2col + Gemm 的最佳化版本慢十倍。如果為 True,則所有最佳化的核心都會新增至 new_ops,並且會取代內部實作 (如果清單 new_ops 尚未包含一個)。
此類別會將每個節點對應到其相關的實作。當遇到函式的子圖時,它會使用此類別來執行子圖或函式。下一個範例顯示如何使用儲存在檔案 model.onnx 中的 onnx 模型來執行 ReferenceEvaluator。
import numpy as np from onnx.reference import ReferenceEvaluator X = np.array(...) sess = ReferenceEvaluator("model.onnx") results = sess.run(None, {"X": X}) print(results[0]) # display the first result
參數 verbose 可用於顯示中間結果。
import numpy as np from onnx.reference import ReferenceEvaluator X = np.array(...) sess = ReferenceEvaluator("model.onnx", verbose=1) results = sess.run(None, {"X": X}) print(results[0]) # display the first result
此類別可以使用 ops 資料夾中任何可用的實作。新增實作需要進行兩個變更。第一個是實作本身。任何現有的節點都可以作為範本。第二個是在 _op_list.py 檔案中加入一行,以匯入該檔案並讓參考評估器知道它的存在。
此類別也可用於測試自訂運算子的實作。假設這個新的運算子是來自 custom 網域的 InvAlpha。實作必須在繼承自
OpRun
的類別中進行。它還必須定義屬性 op_domain。以下是一個計算 \(\\frac{1}{X + \\alpha}\) 的範例。from onnx.reference.op_run import OpRun class InvAlpha(OpRun): op_domain = "custom" def _run(self, x, alpha=None): # type: ignore # None must be the default value, it is automatically # replaced by class OpRun with either the default value # specified in the NodeProto or an attribute value defined # in a `FunctionProto`. return (1 / (x + alpha),)
alpha 是一個屬性。它可以由 onnx 節點定義,也可以由使用此節點的函數定義。可以安全地假設屬性與輸入同時已知。類別 ReferenceEvaluator 必須知道這個新的實作,這可以透過指定的參數 new_ops 來完成。
sess = ReferenceEvaluator(onnx_model, new_ops=[InvAlpha]) got = sess.run(None, {"X": x})[0]
可以簡單地評估一個特定的節點。
import numpy as np from onnx.reference.ops._op_list import Celu x = np.array([[0, 1], [-1, 2]], dtype=np.float32) y = Celu.eval(x, alpha=0.5) print(y)
[[ 0. 1. ] [-0.43233237 2. ]]
這也可以表示為
import numpy as np from onnx.reference.ops import load_op Celu = load_op("", "Celu") # domain is "" x = np.array([[0, 1], [-1, 2]], dtype=np.float32) y = Celu.eval(x, alpha=0.5) print(y)
[[ 0. 1. ] [-0.43233237 2. ]]
可以覆寫現有的運算子。類別名稱必須相同。預設網域不需要指定網域。但是,預設情況下,類別 OpRun 會載入此運算子的最新版本。可以透過新增
OpSchema
類型的靜態屬性 op_schema 來明確指定。from onnx.reference.op_run.op_conv import Conv as _Conv class Conv(_Conv): op_schema = instance_of_OpSchema() def _run(self, ...): ... An operator may be different in a later opset. In that case, a new implementation needs to be registered. `Pad_11`, `Pad_18`. `Pad_11` is the implementation chose for opset in [11, 17]. `Pad_18` is selected for any greater opset. Both classes must be imported into file `_op_list.py` to register their existence to the runtime. An operator may have a reference implementation such as `CastLike` and still be defined as a function. By default, the reference implementation is used. This behavior can be changed by adding a class to the list of overwritten operators. It must inherit from :class:`OpRunExpand`. :: from onnx.reference.op_run import OpRunExpand class CastLike(OpRunExpand): op_domain = "" ref = ReferenceEvaluator(model, new_ops=[CastLike]) # ... This mechanism is used in unit test to check the function implementation a schema may define.
- property input_names¶
傳回輸入名稱。
- property opsets¶
傳回 opsets。
- property output_names¶
傳回輸出名稱。
- run(output_names, feed_inputs: dict[str, Any], attributes: dict[str, Any] | None = None, intermediate: bool = False) dict[str, Any] | list[Any] [原始碼]¶
執行 onnx 模型。
- 參數:
output_names – 依名稱要求的輸出,若為 None 則代表全部
feed_inputs – 字典 { 輸入名稱: 輸入值 }
attributes – 如果執行個體執行 FunctionProto,則為屬性值
intermediate – 如果為 True,則此函數會傳回所有結果,包括最終結果和中間結果在同一個字典中;如果為 False,則只會以清單形式傳回最終結果
- 傳回:
如果 intermediate 為 False,則傳回要求的輸出清單,否則以字典形式傳回具名結果
OpFunction¶
- class onnx.reference.op_run.OpFunction(onnx_node: NodeProto, run_params: dict[str, Any] | None, impl: Any | None = None, attributes: dict[str, Any] | None = None)[原始碼]¶
執行自訂函數。
- classmethod create(n_inputs: int | None = None, n_outputs: int | None = None, verbose: int = 0, **kwargs: Any) Any ¶
根據給定的資訊實例化此類別。
- 參數:
n_inputs – 輸入數量(預設值由運算子架構定義)
n_outputs – 輸出數量(預設值由運算子架構定義)
verbose – 詳細程度
**kwargs – 節點屬性
- 傳回:
NodeProto
- classmethod eval(*args: list[Any], n_outputs: int | None = None, verbose: int = 0, **kwargs: Any) Any ¶
評估此運算子。
- 參數:
*args – 輸入
n_outputs – 輸出數量(預設值由運算子架構定義)
verbose – 詳細程度
**kwargs – 節點屬性
- 傳回:
NodeProto
- static implicit_inputs(graph: GraphProto) list[str] ¶
傳回所有未註冊為輸入,且非由圖形內節點產生的變數。這些輸入是呼叫此圖形的上下文中存在的一部分。
- classmethod make_node(n_inputs: int | None = None, n_outputs: int | None = None, **kwargs: Any) NodeProto ¶
根據給定的資訊,為此類別建立 ONNX 節點。
- 參數:
n_inputs – 輸入數量(預設值由運算子架構定義)
n_outputs – 輸出數量(預設值由運算子架構定義)
verbose – 詳細程度
**kwargs – 節點屬性
- 傳回:
NodeProto
方法
eval
會建立由方法make_node
傳回的 onnx 節點。import numpy as np from onnx.reference.ops._op_list import Celu onnx_node = Celu.make_node(alpha=0.5) print(onnx_node)
input: "x0" output: "y0" op_type: "Celu" attribute { name: "alpha" f: 0.5 type: FLOAT }
- need_context() bool ¶
告訴執行階段,此節點是否需要上下文(目前為止產生的所有結果),因為它可能會靜默地存取其中一個結果(運算子 Scan、If、Loop)。預設答案為 False。
- run(*args, linked_attributes=None, context=None)¶
呼叫方法
_run
,捕捉例外,顯示較長的錯誤訊息。- 參數:
*args – 輸入
linked_attributes – 如果此節點具有連結至它所屬函數的屬性,則會使用此屬性
context – 如果此節點是子圖的一部分,則 context 是包含此節點可能會使用的值的字典
- 傳回:
結果的元組
OpRun¶
- class onnx.reference.op_run.OpRun(onnx_node: NodeProto, run_params: dict[str, Any], schema: Any | None = None)[原始碼]¶
此子資料夾中所有運算子的祖先。
- 參數:
onnx_node – onnx 節點
run_params – 其他參數,例如 verbose、opsets(如果運算子有子圖,則可以有多個)、log 用於記錄函數
schema – 運算子結構描述
- classmethod create(n_inputs: int | None = None, n_outputs: int | None = None, verbose: int = 0, **kwargs: Any) Any [原始碼]¶
根據給定的資訊實例化此類別。
- 參數:
n_inputs – 輸入數量(預設值由運算子架構定義)
n_outputs – 輸出數量(預設值由運算子架構定義)
verbose – 詳細程度
**kwargs – 節點屬性
- 傳回:
NodeProto
- 類別方法 eval(*args: list[Any], n_outputs: int | None = None, verbose: int = 0, **kwargs: Any) Any [原始碼]¶
評估此運算子。
- 參數:
*args – 輸入
n_outputs – 輸出數量(預設值由運算子架構定義)
verbose – 詳細程度
**kwargs – 節點屬性
- 傳回:
NodeProto
- 靜態方法 implicit_inputs(graph: GraphProto) list[str] [原始碼]¶
傳回所有未註冊為輸入,且非由圖形內節點產生的變數。這些輸入是呼叫此圖形的上下文中存在的一部分。
- 類別方法 make_node(n_inputs: int | None = None, n_outputs: int | None = None, **kwargs: Any) NodeProto [原始碼]¶
根據給定的資訊,為此類別建立 ONNX 節點。
- 參數:
n_inputs – 輸入數量(預設值由運算子架構定義)
n_outputs – 輸出數量(預設值由運算子架構定義)
verbose – 詳細程度
**kwargs – 節點屬性
- 傳回:
NodeProto
方法
eval
會建立由方法make_node
傳回的 onnx 節點。import numpy as np from onnx.reference.ops._op_list import Celu onnx_node = Celu.make_node(alpha=0.5) print(onnx_node)
input: "x0" output: "y0" op_type: "Celu" attribute { name: "alpha" f: 0.5 type: FLOAT }