### Install Development Version Source: https://github.com/audeering/audonnx/blob/main/CONTRIBUTING.rst Clone the repository and install the latest development version using uv sync. This ensures your installation is up-to-date with the latest changes. ```bash git clone https://github.com/audeering/audonnx/ cd audonnx uv sync ``` -------------------------------- ### Install Audonnx with Pip Source: https://github.com/audeering/audonnx/blob/main/docs/installation.md Use this command to install the audonnx package. It is recommended to do this within a Python virtual environment. ```bash $ # Create and activate Python virtual environment, e.g. $ # virtualenv --no-download --python=python3 ${HOME}/.envs/audonnx $ # source ${HOME}/.envs/audonnx/bin/activate $ pip install audonnx ``` -------------------------------- ### Install Pre-commit Hooks Source: https://github.com/audeering/audonnx/blob/main/CONTRIBUTING.rst Install pre-commit hooks to automatically check code style and spelling before each commit. This helps maintain code quality and consistency. ```bash uvx pre-commit install uvx pre-commit run --all-files ``` -------------------------------- ### Create a synthetic test model with multiple outputs Source: https://context7.com/audeering/audonnx/llms.txt Create a synthetic audonnx.Model with multiple output nodes, using -1 to denote dynamic axes. This example also demonstrates setting a constant value for outputs and printing the model structure. ```python import numpy as np import audonnx.testing # Multiple output nodes; -1 marks a dynamic axis model = audonnx.testing.create_model([[3], [1, -1, 2]], value=1.0) print(model) # Input: # input-0: shape: [3] transform: audonnx.core.function.Function(reshape) # input-1: shape: [1, -1, 2] ... # Output: # output-0: shape: [3] labels: [output-0-0, output-0-1, output-0-2] # output-1: shape: [1, -1, 2] labels: [output-1-0, output-1-1] y = model(signal, 16000) # {'output-0': array([1., 1., 1.], dtype=float32), # 'output-1': array([[[1., 1.], [1., 1.], ...]], dtype=float32)} ``` -------------------------------- ### Create Audinterface for ONNX Model Processing Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md Creates an interface using `audinterface.Feature` to process audio files with a pre-configured Audonnx model. This setup allows for batch processing of files and concatenates specified outputs into a single array. ```python >>> outputs = ["gender", "confidence"] >>> interface = audinterface.Feature( ... feature_names=onnx_model_7.labels(outputs), ... process_func=onnx_model_7, ... process_func_args={ ... "outputs": outputs, ... "concat": True, ... }, ... ) >>> interface.process_file(file) female male confidence file start end test.wav 0 days 0 days 00:00:05.247687500 307.07... 22.489... -92.46... ``` -------------------------------- ### Create a synthetic test model with single output Source: https://context7.com/audeering/audonnx/llms.txt Generate a functional audonnx.Model with an identity ONNX graph for unit testing. This example shows creating a model with a single output node of a specified shape. ```python import numpy as np import audonnx.testing # Single output node of shape [3] model = audonnx.testing.create_model([[3]]) signal = np.zeros((1, 16000), dtype=np.float32) y = model(signal, 16000) # array([0., 0., 0.], dtype=float32) ``` -------------------------------- ### Quantize Model Weights Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md Reduces the memory footprint of a model by quantizing its weights, typically to 8-bit integers. Requires `onnx` and `onnxruntime` to be installed. ```python import onnxruntime.quantization onnx_infer_path = os.path.join(onnx_root, "model_infer.onnx") onnxruntime.quantization.quant_pre_process( onnx_model_path, onnx_infer_path, ) onnx_quant_path = os.path.join(onnx_root, "model_quant.onnx") onnxruntime.quantization.quantize_dynamic( onnx_infer_path, onnx_quant_path, weight_type=onnxruntime.quantization.QuantType.QUInt8, ) ``` -------------------------------- ### Create Serializable Custom Transform Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md Wraps a self-contained Python function (like the MFCC example) into an `audonnx.Function` object, making it serializable and usable as a model transform. ```pycon >>> transform = audonnx.Function(mfcc) >>> print(transform) ``` -------------------------------- ### Prepare Input Data for AudONNX Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md This snippet shows how to prepare input data, including reading an audio file and creating a pandas MultiIndex for time segments. ```python import audiofile import pandas as pd file = "test.wav" signal, sampling_rate = audiofile.read( file, always_2d=True, ) index = pd.MultiIndex.from_arrays( [ [file, file], pd.to_timedelta(["0s", "3s"]), pd.to_timedelta(["3s", "5s"]), ], names=["file", "start", "end"], ) ``` -------------------------------- ### Load Model from Directory Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md A convenient shortcut to load a model directly from its root directory, which should contain the necessary configuration files. ```pycon >>> onnx_model_3 = audonnx.load(onnx_root) >>> onnx_model_3(signal, sampling_rate) ``` -------------------------------- ### Get ONNX Model Output Node Labels Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md Extracts the labels associated with the output node of the loaded ONNX model. ```python onnx_model.outputs["gender"].labels ``` -------------------------------- ### Import audonnx.testing Source: https://github.com/audeering/audonnx/blob/main/docs/api-src/audonnx.testing.rst Import the audonnx.testing module to enable the creation of audonnx.Model objects with custom output shapes. ```python import audonnx.testing ``` -------------------------------- ### Build Documentation with Sphinx Source: https://github.com/audeering/audonnx/blob/main/CONTRIBUTING.rst Re-create the HTML documentation pages using Sphinx. The generated files will be located in the build/html directory. ```bash uv run python -m sphinx docs/ build/html -b html ``` -------------------------------- ### Get Majority Class from AudINTERFACE Output Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md Determines the majority class (e.g., 'male' or 'female') for each segment in the processed index by finding the maximum value along the feature axis. ```python interface.process_index(index).idxmax(axis=1) ``` -------------------------------- ### Process Audio with OpenSMILE and PyTorch Model Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md Calculates audio features using OpenSMILE and then runs them through a PyTorch model for inference. ```python y = smile(signal, sampling_rate) with torch.no_grad(): z = torch_model(torch.from_numpy(y)) ``` -------------------------------- ### Load Quantized Model Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md Initializes a model using the path to a quantized ONNX file. Note that the output of a quantized model may differ slightly from the original. ```pycon >>> onnx_model_4 = audonnx.Model( ... onnx_quant_path, ... labels=["female", "male"], ... transform=smile, ... ) >>> onnx_model_4(signal, sampling_rate) ``` -------------------------------- ### Initialize OpenSMILE Feature Extractor Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md Initializes an OpenSMILE feature extractor to convert raw audio signals into low-level descriptors. ```python import opensmile smile = opensmile.Smile( feature_set=opensmile.FeatureSet.GeMAPSv01b, feature_level=opensmile.FeatureLevel.LowLevelDescriptors, ) ``` -------------------------------- ### Load Model from Directory Source: https://context7.com/audeering/audonnx/llms.txt Use `audonnx.load()` as a convenience function to load a `Model` from a folder. It prioritizes `model.yaml` and falls back to `model.onnx` with optional label and transform files. ```python import audonnx import onnxruntime # Basic load from directory containing model.yaml / model.onnx model = audonnx.load("tests") print(model) # Input: # feature: # shape: [18, -1] # dtype: tensor(float) # transform: opensmile.core.smile.Smile # Output: # gender: # shape: [2] # dtype: tensor(float) # labels: [female, male] ``` ```python # Override runtime options without changing the stored config model_gpu = audonnx.load( "tests", device="cuda:0", # run on first GPU num_workers=4, auto_install=False, # raise error for missing packages instead of installing ) ``` ```python # Use a custom SessionOptions object (num_workers is then ignored) opts = onnxruntime.SessionOptions() opts.intra_op_num_threads = 2 opts.inter_op_num_threads = 2 model_opts = audonnx.load("tests", session_options=opts) ``` ```python # Legacy mode: directory has only model.onnx (+ optional labels.yaml) model_legacy = audonnx.load( "legacy_dir", model_file="model.onnx", labels_file="labels.yaml", transform_file="transform.yaml", ) ``` -------------------------------- ### Create ONNX Model Proto with audonnx.testing Source: https://context7.com/audeering/audonnx/llms.txt Use `create_model_proto` to generate an ONNX ModelProto. This is useful for testing serialization or when you need a raw proto to pass to `audonnx.Model` with custom transforms and labels. ```python import onnx import audonnx import audonnx.testing proto = audonnx.testing.create_model_proto([[2]]) # Inspect the ONNX graph print(onnx.printer.to_text(proto)) # < # ir_version: 7, # opset_import: ["" : 14], # producer_name: "test" # > # test (float[2] "input-0") => (float[2] "output-0") { # "output-0" = Identity ("input-0") # } ``` ```python # Use proto directly in audonnx.Model with custom labels and transform def my_transform(x, sr): return x * 2.0 model = audonnx.Model( proto, labels=["low", "high"], transform=my_transform, ) ``` ```python # Proto with multiple nodes and a dynamic axis proto_multi = audonnx.testing.create_model_proto( [[18, -1], [2]], dtype=onnx.TensorProto.FLOAT, opset_version=14, ir_version=7, ) model_multi = audonnx.Model( proto_multi, labels={"output-1": ["neg", "pos"]}, ) ``` -------------------------------- ### Save and Load Model with Custom Transform Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md Demonstrates saving a model initialized with a custom transform to YAML and then loading it back, preserving the custom transform configuration. ```pycon >>> onnx_model_5.to_yaml(onnx_meta_path) >>> onnx_model_6 = audonnx.load(onnx_root) >>> onnx_model_6(signal, sampling_rate) ``` -------------------------------- ### Load Model on GPU (onnxruntime-gpu >= 1.8) Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md Load an Audonnx model to run on the GPU by specifying the 'cuda' device with an optional device ID. ```python import os import audonnx model = audonnx.load(..., device='cuda:2') ``` -------------------------------- ### audonnx.testing.create_model_proto Source: https://context7.com/audeering/audonnx/llms.txt Builds and returns an onnx.ModelProto identity graph. This is useful for testing serialization of ONNX bytes or when you need a raw proto to pass to audonnx.Model with fully custom transforms and labels. ```APIDOC ## audonnx.testing.create_model_proto — Create a raw ONNX proto object ### Description Builds and returns an `onnx.ModelProto` identity graph (no `audonnx.Model` wrapper). Useful when you need the raw proto to pass to `audonnx.Model` with fully custom transforms and labels, or when testing serialization of ONNX bytes. ### Parameters This function does not explicitly list parameters in the provided text, but examples show it can accept: - `shape` (list of lists of ints): Defines the shape of the input tensor. Example: `[[2]]` or `[[18, -1], [2]]`. - `dtype` (onnx.TensorProto): Specifies the data type of the tensor. Defaults to `onnx.TensorProto.FLOAT`. - `opset_version` (int): The ONNX opset version to use. Defaults to 14. - `ir_version` (int): The ONNX IR version to use. Defaults to 7. ### Returns - `onnx.ModelProto`: An ONNX ModelProto object representing an identity graph. ### Example ```python import onnx import audonnx import audonnx.testing # Create a simple identity graph proto proto = audonnx.testing.create_model_proto([[2]]) # Inspect the ONNX graph print(onnx.printer.to_text(proto)) # Create a proto with multiple nodes and a dynamic axis proto_multi = audonnx.testing.create_model_proto( [[18, -1], [2]], dtype=onnx.TensorProto.FLOAT, opset_version=14, ir_version=7, ) ``` ``` -------------------------------- ### audonnx.load Source: https://context7.com/audeering/audonnx/llms.txt Loads a model from a directory, supporting various configurations including YAML, ONNX files, and legacy formats. ```APIDOC ## audonnx.load — Load a model from a directory ### Description Convenience function that loads a `Model` from a folder. It first tries to deserialize from `model.yaml`; if the YAML starts with `$audonnx`, the full object (including transform and labels) is restored via `audobject`. Falls back to loading from `model.onnx` with optional separate `labels.yaml` and `transform.yaml` files (legacy mode). ### Function Signature `audonnx.load(path, model_file=None, labels_file=None, transform_file=None, device=None, num_workers=None, auto_install=True, session_options=None)` ### Parameters * **path** (str): The path to the directory containing the model files. * **model_file** (str, optional): The name of the ONNX model file. Defaults to `model.onnx`. * **labels_file** (str, optional): The name of the labels YAML file. Defaults to `labels.yaml`. * **transform_file** (str, optional): The name of the transform YAML file. Defaults to `transform.yaml`. * **device** (str, optional): The device to run the model on (e.g., 'cpu', 'cuda:0'). * **num_workers** (int, optional): Number of worker threads for ONNX Runtime. * **auto_install** (bool, optional): If True, automatically installs missing packages. Defaults to True. * **session_options** (onnxruntime.SessionOptions, optional): Custom ONNX Runtime session options. ### Returns * audonnx.Model: The loaded model object. ### Example ```python import audonnx import onnxruntime # Basic load from directory containing model.yaml / model.onnx model = audonnx.load("tests") print(model) # Input: # feature: # shape: [18, -1] # dtype: tensor(float) # transform: opensmile.core.smile.Smile # Output: # gender: # shape: [2] # dtype: tensor(float) # labels: [female, male] # Override runtime options without changing the stored config model_gpu = audonnx.load( "tests", device="cuda:0", # run on first GPU num_workers=4, auto_install=False, # raise error for missing packages instead of installing ) # Use a custom SessionOptions object (num_workers is then ignored) opts = onnxruntime.SessionOptions() opts.intra_op_num_threads = 2 opts.inter_op_num_threads = 2 model_opts = audonnx.load("tests", session_options=opts) # Legacy mode: directory has only model.onnx (+ optional labels.yaml) model_legacy = audonnx.load( "legacy_dir", model_file="model.onnx", labels_file="labels.yaml", transform_file="transform.yaml", ) ``` ``` -------------------------------- ### Audonnx Utility Functions Source: https://github.com/audeering/audonnx/blob/main/docs/api-src/audonnx.rst This section details utility functions for loading models and managing execution providers. ```APIDOC ## Function: device_to_providers ### Description Converts a device specification to a list of ONNX execution providers. ## Function: load ### Description Loads an ONNX model from a specified path. ``` -------------------------------- ### audonnx.device_to_providers Source: https://context7.com/audeering/audonnx/llms.txt Map device name to ONNX Runtime providers. Translates a human-readable device string (e.g., "cpu", "cuda", "cuda:") into the list of ONNX Runtime execution provider tuples. It also accepts raw provider names or lists of providers and passes them through unchanged. ```APIDOC ## audonnx.device_to_providers ### Description Map device name to ONNX Runtime providers. Translates a human-readable device string (`"cpu"`, `"cuda"`, `"cuda:"`) into the list of ONNX Runtime execution provider tuples expected by `onnxruntime.InferenceSession`. Also accepts raw provider names or lists of providers and passes them through unchanged. ### Usage Examples ```python import audonnx # CPU print(audonnx.device_to_providers("cpu")) # Expected output: ['CPUExecutionProvider'] # CUDA (all GPUs) print(audonnx.device_to_providers("cuda")) # Expected output: ['CUDAExecutionProvider'] # Specific GPU print(audonnx.device_to_providers("cuda:2")) # Expected output: [('CUDAExecutionProvider', {'device_id': '2'})] # Raw provider string passed through print(audonnx.device_to_providers("CPUExecutionProvider")) # Expected output: ['CPUExecutionProvider'] # Provider tuple passed through print(audonnx.device_to_providers(("CUDAExecutionProvider", {"device_id": 0}))) # Expected output: [('CUDAExecutionProvider', {'device_id': 0})] # List of providers (fallback chain) print(audonnx.device_to_providers(["CUDAExecutionProvider", "CPUExecutionProvider"])) # Expected output: ['CUDAExecutionProvider', 'CPUExecutionProvider'] # Used implicitly by audonnx.load and audonnx.Model # model = audonnx.load("tests", device="cuda:0") ``` ``` -------------------------------- ### Create Model with Additional Inputs Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md Instantiate a model with specific labels and no transform for the 'feature' input, allowing for direct input of additional data. ```python >>> onnx_model_8 = audonnx.Model( ... onnx_multi_path, ... labels={ ... "gender": ["female", "male"], ... }, ... ) >>> onnx_model_8 Input: signal: shape: [1, -1] dtype: tensor(float) transform: None feature: shape: [18, -1] dtype: tensor(float) transform: None Output: hidden: shape: [8] dtype: tensor(float) labels: [hidden-0, hidden-1, hidden-2, (...), hidden-5, hidden-6, hidden-7] gender: shape: [2] dtype: tensor(float) labels: [female, male] confidence: shape: [1] dtype: tensor(float) labels: [confidence] ``` -------------------------------- ### Create a synthetic test model with custom parameters Source: https://context7.com/audeering/audonnx/llms.txt Generate a synthetic audonnx.Model by customizing dtype, opset version, IR version, device, and number of workers. This is useful for testing specific configurations. ```python import numpy as np import audonnx.testing import onnx model_int = audonnx.testing.create_model( [[4]], value=0, dtype=onnx.TensorProto.INT64, opset_version=14, ir_version=7, device="cpu", num_workers=2, ) ``` -------------------------------- ### Print ONNX Model Input Transform Details Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md Prints the detailed configuration of the transform associated with the ONNX model's input node. ```python print(onnx_model.inputs["feature"].transform) ``` -------------------------------- ### Create Model Without Signal Input Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md Instantiate a model that does not use 'signal' as an input, simplifying the input requirements. ```python >>> onnx_model_9 = audonnx.Model( ... onnx_model_path, ... labels=["female", "male"], ... ) >>> onnx_model_9 Input: feature: shape: [18, -1] dtype: tensor(float) transform: None Output: gender: shape: [2] dtype: tensor(float) labels: [female, male] ``` -------------------------------- ### Load Model on GPU (onnxruntime-gpu < 1.8) Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md For older versions of 'onnxruntime-gpu', set the 'CUDA_VISIBLE_DEVICES' environment variable before loading the model to specify the GPU device. ```python os.environ['CUDA_VISIBLE_DEVICES'] = '2' model = audonnx.load(..., device='cuda') ``` -------------------------------- ### Run Inference with AudONNX Model Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md Performs inference using the loaded AudONNX model on the input signal and sampling rate, returning the model's output. ```python onnx_model(signal, sampling_rate) ``` -------------------------------- ### Map device name to ONNX Runtime providers Source: https://context7.com/audeering/audonnx/llms.txt Use audonnx.device_to_providers to translate human-readable device strings into ONNX Runtime execution provider tuples. This function also passes through raw provider names or lists. ```python import audonnx # CPU print(audonnx.device_to_providers("cpu")) # ['CPUExecutionProvider'] # CUDA (all GPUs) print(audonnx.device_to_providers("cuda")) # ['CUDAExecutionProvider'] # Specific GPU print(audonnx.device_to_providers("cuda:2")) # [('CUDAExecutionProvider', {'device_id': '2'})] # Raw provider string passed through print(audonnx.device_to_providers("CPUExecutionProvider")) # ['CPUExecutionProvider'] # Provider tuple passed through print(audonnx.device_to_providers(("CUDAExecutionProvider", {"device_id": 0}))) # [('CUDAExecutionProvider', {'device_id': 0})] # List of providers (fallback chain) print(audonnx.device_to_providers(["CUDAExecutionProvider", "CPUExecutionProvider"])) # ['CUDAExecutionProvider', 'CPUExecutionProvider'] # Used implicitly by audonnx.load and audonnx.Model model = audonnx.load("tests", device="cuda:0") ``` -------------------------------- ### Export PyTorch Model to ONNX and Load with Audonnx Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md Exports a PyTorch model to ONNX format, specifying input/output names and dynamic axes for flexible input sizes. It then loads the ONNX model using Audonnx, configuring labels for specific outputs and applying transformations to inputs. ```python >>> onnx_multi_root = audeer.mkdir("onnx_multi") >>> onnx_multi_path = os.path.join(onnx_multi_root, "model.onnx") >>> torch.onnx.export( ... TorchModelMulti(), ... ( ... torch.randn(signal.shape), ... torch.randn(y.shape[1:]), ... ), ... onnx_multi_path, ... input_names=["signal", "feature"], ... output_names=["hidden", "gender", "confidence"], ... dynamic_axes={ ... "signal": {1: "time"}, ... "feature": {1: "time"}, ... }, ... opset_version=12, ... dynamo=False, ... ) >>> onnx_model_7 = audonnx.Model( ... onnx_multi_path, ... labels={ ... "gender": ["female", "male"], ... }, ... transform={ ... "feature": smile, ... }, ... ) ``` ```text >>> onnx_model_7 Input: signal: shape: [1, -1] dtype: tensor(float) transform: None feature: shape: [18, -1] dtype: tensor(float) transform: opensmile.core.smile.Smile Output: hidden: shape: [8] dtype: tensor(float) labels: [hidden-0, hidden-1, hidden-2, (...,), hidden-5, hidden-6, hidden-7] gender: shape: [2] dtype: tensor(float) labels: [female, male] confidence: shape: [1] dtype: tensor(float) labels: [confidence] ``` -------------------------------- ### Create Model with Custom Function Transform Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md Instantiate a model and apply a custom transform function to a specific input, such as 'feature'. ```python >>> onnx_model_10 = audonnx.Model( ... onnx_multi_path, ... labels={ ... "gender": ["female", "male"], ... }, ... transform={ ... "feature": transform, ... }, ... ) >>> onnx_model_10 Input: signal: shape: [1, -1] dtype: tensor(float) transform: None feature: shape: [18, -1] dtype: tensor(float) transform: audonnx.core.function.Function(feature_addition) Output: hidden: shape: [8] dtype: tensor(float) labels: [hidden-0, hidden-1, hidden-2, (...), hidden-5, hidden-6, hidden-7] gender: shape: [2] dtype: tensor(float) labels: [female, male] confidence: shape: [1] dtype: tensor(float) labels: [confidence] ``` -------------------------------- ### Run Tests with Pytest Source: https://github.com/audeering/audonnx/blob/main/CONTRIBUTING.rst Execute the project's test suite using pytest. Ensure all tests pass to confirm code integrity. ```bash uv run pytest ``` -------------------------------- ### Load and run an ONNX model with transforms and labels Source: https://context7.com/audeering/audonnx/llms.txt Load an ONNX model, attaching a feature extractor transform and output labels. The model can then be used to run inference on audio signals. Inspect model inputs, outputs, and labels. ```python import os import audiofile import opensmile import audonnx # Feature extractor to convert raw audio -> feature matrix smile = opensmile.Smile( feature_set=opensmile.FeatureSet.GeMAPSv01b, feature_level=opensmile.FeatureLevel.LowLevelDescriptors, ) # Load model from .onnx file; attach transform and output labels model = audonnx.Model( os.path.join("tests", "model.onnx"), labels=["female", "male"], # assigned to last static dim of each output node transform=smile, # applied to signal before inference device="cpu", # "cpu", "cuda", or "cuda:" num_workers=1, # threads for CPU inference ) # Inspect the model print(model) # Input: # feature: # shape: [18, -1] # dtype: tensor(float) # transform: opensmile.core.smile.Smile # Output: # gender: # shape: [2] # dtype: tensor(float) # labels: [female, male] # Inspect individual nodes print(model.inputs["feature"]) # {shape: [18, -1], dtype: tensor(float), transform: opensmile.core.smile.Smile} print(model.outputs["gender"].labels) # ['female', 'male'] # Run inference: returns numpy array when there is one output node signal, sampling_rate = audiofile.read("tests/test.wav", always_2d=True) result = model(signal, sampling_rate) # array([-195.1, 73.3], dtype=float32) # Select a specific output node by name result = model(signal, sampling_rate, outputs="gender") # Request multiple nodes -> returns dict result = model(signal, sampling_rate, outputs=["gender"]) # {"gender": array([...], dtype=float32)} # Concatenate multiple output nodes into one array model_multi = audonnx.Model( "onnx_multi/model.onnx", labels={"gender": ["female", "male"]}, transform={"feature": smile}, # dict assigns transforms to specific inputs ) result = model_multi( signal, sampling_rate, outputs=["gender", "confidence"], concat=True, # concatenate along last non-dynamic axis squeeze=True, # remove length-1 dimensions ) # Pass multiple inputs as a dictionary (no transform applied) features = smile(signal, sampling_rate) result = model_multi( {"signal": signal, "feature": features}, sampling_rate, outputs="gender", ) ``` -------------------------------- ### audonnx.Model.to_yaml Source: https://context7.com/audeering/audonnx/llms.txt Serializes the model configuration, including ONNX file path, labels, and transform, to a YAML file using audobject serialization. ```APIDOC ## audonnx.Model.to_yaml — Serialize model to YAML ### Description Saves the model configuration (ONNX file path, labels, and transform) to a YAML file using `audobject` serialization. If the model was created from an in-memory proto object rather than a file, the ONNX bytes are written to a companion `.onnx` file automatically. ### Method Signature `model.to_yaml(path)` ### Parameters * **path** (str): The path to the YAML file where the model configuration will be saved. ### Example ```python import audonnx import audobject import os model = audonnx.load("tests") # Save to YAML (transform and labels are embedded) model.to_yaml("saved/model.yaml") # Inspect the written YAML import oyaml as yaml with open("saved/model.yaml") as fp: print(yaml.dump(yaml.load(fp, Loader=yaml.Loader))) # $audonnx.core.model.Model==1.0.1: # path: model.onnx # labels: # - female # - male # transform: # $opensmile.core.smile.Smile==...: # feature_set: GeMAPSv01b # ... # Reload via audobject directly model2 = audobject.from_yaml("saved/model.yaml") # Or reload via audonnx.load (preferred) model3 = audonnx.load("saved") ``` ``` -------------------------------- ### Create Model with Concatenated Outputs Source: https://context7.com/audeering/audonnx/llms.txt Use `concat=True` when creating a model to concatenate compatible outputs into a single array. ```python import audonnx import numpy as np signal = np.zeros(16000) # --- Concatenate compatible outputs --- model_concat = audonnx.testing.create_model([[2], [3]]) y = model_concat(signal, 16000, concat=True) # array([0., 0., 0., 0., 0.], dtype=float32) ``` -------------------------------- ### Load ONNX Model with AudONNX Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md Loads an exported ONNX model using audonnx.Model, configuring it with output labels and a feature transformation. ```python import audonnx onnx_model = audonnx.Model( onnx_model_path, labels=["female", "male"], transform=smile, ) ``` -------------------------------- ### Initialize Model with Custom Transform Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md Initializes an Audonnx model using a custom transform object. This allows using non-standard feature extraction methods. ```pycon >>> onnx_model_5 = audonnx.Model( ... onnx_model_path, ... labels=["female", "male"], ... transform=transform, ... ) >>> onnx_model_5 ``` -------------------------------- ### audonnx.Model Source: https://context7.com/audeering/audonnx/llms.txt Load and run an ONNX model. The Model class wraps an onnxruntime.InferenceSession and supports named input/output nodes, optional pre-processing transforms, and output labels. It is serializable to YAML. ```APIDOC ## audonnx.Model ### Description Wraps an `onnxruntime.InferenceSession` around an ONNX file or proto object. Supports named input/output nodes, an optional per-input transform callable, and optional label lists for output dimensions. When printed, it shows a human-readable summary of all input and output nodes with shapes, dtypes, and transforms/labels. `Model` inherits from `audobject.Object`, making instances serializable to YAML. ### Method `audonnx.Model(onnx_path, labels=None, transform=None, device='cpu', num_workers=1)` ### Parameters #### Path Parameters - **onnx_path** (str) - Required - Path to the ONNX model file. #### Query Parameters - **labels** (list or dict, optional) - Labels for output dimensions. If a list, assigned to the last static dimension of each output node. If a dict, maps output node names to lists of labels. - **transform** (callable or dict, optional) - A callable or a dictionary mapping input node names to callables for pre-processing. - **device** (str, optional) - The device to use for inference ('cpu', 'cuda', or 'cuda:'). Defaults to 'cpu'. - **num_workers** (int, optional) - Number of threads for CPU inference. Defaults to 1. ### Request Example ```python import os import audiofile import opensmile import audonnx smile = opensmile.Smile( feature_set=opensmile.FeatureSet.GeMAPSv01b, feature_level=opensmile.FeatureLevel.LowLevelDescriptors, ) model = audonnx.Model( os.path.join("tests", "model.onnx"), labels=["female", "male"], transform=smile, device="cpu", num_workers=1, ) print(model) signal, sampling_rate = audiofile.read("tests/test.wav", always_2d=True) result = model(signal, sampling_rate) result = model(signal, sampling_rate, outputs="gender") result = model(signal, sampling_rate, outputs=["gender"]) model_multi = audonnx.Model( "onnx_multi/model.onnx", labels={"gender": ["female", "male"]}, transform={"feature": smile}, ) result = model_multi( signal, sampling_rate, outputs=["gender", "confidence"], concat=True, squeeze=True, ) features = smile(signal, sampling_rate) result = model_multi( {"signal": signal, "feature": features}, sampling_rate, outputs="gender", ) ``` ### Response #### Success Response (200) - **output** (numpy.ndarray or dict) - The inference result. Returns a numpy array if there is a single output node, otherwise returns a dictionary mapping output node names to numpy arrays. ``` -------------------------------- ### Define a PyTorch Model for Audio Features Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md Defines a simple PyTorch model with a single input and output, suitable for processing audio features. ```python import torch class TorchModelSingle(torch.nn.Module): def __init__( self, ): super().__init__() self.hidden = torch.nn.Linear(18, 8) self.out = torch.nn.Linear(8, 2) def forward(self, x: torch.Tensor): y = self.hidden(x.mean(dim=-1)) y = self.out(y) return y.squeeze() torch_model = TorchModelSingle() ``` -------------------------------- ### Create Model with Squeezed Length-1 Axes Source: https://context7.com/audeering/audonnx/llms.txt Use `squeeze=True` when creating a model to remove length-1 axes from the output. ```python # --- Squeeze length-1 axes --- model_sq = audonnx.testing.create_model([[1, 2]]) y = model_sq(signal, 16000, squeeze=True) # array([0., 0.], dtype=float32) ``` -------------------------------- ### Serialize Model to YAML Source: https://context7.com/audeering/audonnx/llms.txt Use `model.to_yaml()` to save the model configuration to a YAML file. This method embeds the transform and labels, and automatically writes companion ONNX files if the model was created from an in-memory proto. ```python import audonnx import audobject import os model = audonnx.load("tests") # Save to YAML (transform and labels are embedded) model.to_yaml("saved/model.yaml") # Inspect the written YAML import oyaml as yaml with open("saved/model.yaml") as fp: print(yaml.dump(yaml.load(fp, Loader=yaml.Loader))) # $audonnx.core.model.Model==1.0.1: # path: model.onnx # labels: # - female # - male # transform: # $opensmile.core.smile.Smile==...: # feature_set: GeMAPSv01b # ... # Reload via audobject directly model2 = audobject.from_yaml("saved/model.yaml") # Or reload via audonnx.load (preferred) model3 = audonnx.load("saved") ``` -------------------------------- ### Model Input with Dictionary Source: https://context7.com/audeering/audonnx/llms.txt Models without a transform can accept dictionary inputs, mapping input names to NumPy arrays. ```python # --- Dict input for models without a transform --- model_raw = audonnx.testing.create_model([[2]]) proto = audonnx.testing.create_model_proto([[2]]) model_notransform = audonnx.Model(proto) y = model_notransform({"input-0": np.array([1.0, 2.0], dtype=np.float32)}) # array([1., 2.], dtype=float32) ``` -------------------------------- ### audonnx.testing.create_model Source: https://context7.com/audeering/audonnx/llms.txt Creates a fully functional `audonnx.Model` backed by an identity ONNX graph. Each output node simply echoes its corresponding input, filled with a constant `value`. Each input node automatically receives a reshape `Function` transform. Useful for unit tests that need a real `Model` object without a trained ONNX file. ```APIDOC ## audonnx.testing.create_model ### Description Creates a fully functional `audonnx.Model` backed by an identity ONNX graph — each output node simply echoes its corresponding input, filled with a constant `value`. Each input node automatically receives a reshape `Function` transform. Useful for unit tests that need a real `Model` object without a trained ONNX file. ### Usage Examples ```python import numpy as np import audonnx.testing import onnx # Single output node of shape [3] model = audonnx.testing.create_model([[3]]) signal = np.zeros((1, 16000), dtype=np.float32) y = model(signal, 16000) # Expected output: array([0., 0., 0.], dtype=float32) # Multiple output nodes; -1 marks a dynamic axis model = audonnx.testing.create_model([[3], [1, -1, 2]], value=1.0) print(model) # Expected output: # Input: # input-0: shape: [3] transform: audonnx.core.function.Function(reshape) # input-1: shape: [1, -1, 2] ... # Output: # output-0: shape: [3] labels: [output-0-0, output-0-1, output-0-2] # output-1: shape: [1, -1, 2] labels: [output-1-0, output-1-1] y = model(signal, 16000) # Expected output: # {'output-0': array([1., 1., 1.], dtype=float32), # 'output-1': array([[[1., 1.], [1., 1.], ...]], dtype=float32)} # Customize dtype, opset, and device model_int = audonnx.testing.create_model( [[4]], value=0, dtype=onnx.TensorProto.INT64, opset_version=14, ir_version=7, device="cpu", num_workers=2, ) ``` ``` -------------------------------- ### Check Documentation Links with Sphinx Source: https://github.com/audeering/audonnx/blob/main/CONTRIBUTING.rst Automatically check if all links within the documentation are still valid using Sphinx's linkcheck builder. ```bash uv run python -m sphinx docs/ build/html -b linkcheck ``` -------------------------------- ### Run Ruff and Codespell Directly Source: https://github.com/audeering/audonnx/blob/main/CONTRIBUTING.rst Execute ruff for linting and formatting, and codespell for checking spelling errors directly. These commands can be restricted to specific directories. ```bash uvx ruff check --fix . uvx ruff format . uvx codespell ``` ```bash uvx ruff check audonnx/ tests/ uvx codespell audonnx/ tests/ ``` -------------------------------- ### Process Audio Signal with ONNX Model Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md Processes an audio signal using a loaded Audonnx model. By default, it returns a dictionary of all output nodes. Specific outputs can be requested using the `outputs` argument. ```python >>> onnx_model_7(signal, sampling_rate) {'hidden': array([ 7.603...e-01, ...], dtype=float32), 'gender': ...} ``` ```python >>> onnx_model_7( ... signal, ... sampling_rate, ... outputs="gender", ... ) array([307.07..., 22.489...], dtype=float32) ``` ```python >>> onnx_model_7( ... signal, ... sampling_rate, ... outputs=["gender", "confidence"], ... ) {'gender': array([307.07..., 22.489...], dtype=float32), 'confidence': ...} ``` ```python >>> onnx_model_7( ... signal, ... sampling_rate, ... outputs=["gender", "confidence"], ... concat=True, ... ) array([307.07..., 22.489..., -92.46...], dtype=float32) ``` -------------------------------- ### Define PyTorch Model with Multiple Output Nodes Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md Defines a PyTorch model that accepts raw audio and features, producing outputs from a hidden layer and a confidence score. This is useful for models requiring intermediate feature extraction or confidence estimation. ```python class TorchModelMulti(torch.nn.Module): def __init__(self): super().__init__() self.hidden_left = torch.nn.Linear(1, 4) self.hidden_right = torch.nn.Linear(18, 4) self.out = torch.nn.ModuleDict( { "gender": torch.nn.Linear(8, 2), "confidence": torch.nn.Linear(8, 1), } ) def forward(self, signal: torch.Tensor, feature: torch.Tensor): y_left = self.hidden_left(signal.mean(dim=-1)) y_right = self.hidden_right(feature.mean(dim=-1)) y_hidden = torch.cat([y_left, y_right], dim=-1) y_gender = self.out["gender"](y_hidden) y_confidence = self.out["confidence"](y_hidden) return ( y_hidden.squeeze(), y_gender.squeeze(), y_confidence, ) ``` -------------------------------- ### Load Model from YAML Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md Loads a model from a previously saved YAML file. This is useful for restoring model configurations and metadata. ```pycon >>> import oyaml as yaml >>> with open(onnx_meta_path, "r") as fp: ... d = yaml.load(fp, Loader=yaml.Loader) >>> print(yaml.dump(d)) ``` ```pycon >>> import audobject >>> onnx_model_2 = audobject.from_yaml(onnx_meta_path) >>> onnx_model_2(signal, sampling_rate) ``` -------------------------------- ### Create an AudINTERFACE Feature Processor Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md Creates an audinterface.Feature object that uses the loaded ONNX model as its processing function, mapping output labels to feature names. ```python import numpy as np import audinterface interface = audinterface.Feature( feature_names=onnx_model.outputs["gender"].labels, process_func=onnx_model, ) ``` -------------------------------- ### Audonnx Core Components Source: https://github.com/audeering/audonnx/blob/main/docs/api-src/audonnx.rst This section covers the main classes used to represent ONNX models and their components within the audonnx library. ```APIDOC ## Class: Function ### Description Represents a function or operation within an ONNX graph. ## Class: Model ### Description Represents an ONNX model, providing methods for loading and manipulation. ## Class: InputNode ### Description Represents an input node of an ONNX model. ## Class: OutputNode ### Description Represents an output node of an ONNX model. ``` -------------------------------- ### Call Model with Additional Inputs Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md Pass all inputs, including the additional 'feature' input, as a dictionary when calling the model. ```python >>> onnx_model_8( ... {"signal": signal, "feature": y}, ... sampling_rate, ... ) {'hidden': array([ 7.603...e-01, ...], dtype=float32), 'gender': ...} ``` -------------------------------- ### audonnx.InputNode and audonnx.OutputNode Source: https://context7.com/audeering/audonnx/llms.txt Lightweight data classes that store the shape, dtype, and transform (input) or labels (output) for each node in the ONNX graph. They are created automatically by `Model.__init__` and are accessible via `Model.inputs` and `Model.outputs`. ```APIDOC ## audonnx.InputNode and audonnx.OutputNode ### Description `InputNode` and `OutputNode` are lightweight data classes that store the shape, dtype, and transform (input) or labels (output) for each node in the ONNX graph. They are created automatically by `Model.__init__` and are accessible via `Model.inputs` and `Model.outputs`. ### Usage Examples ```python import audonnx import audonnx.testing model = audonnx.testing.create_model([[18, -1], [2]]) # InputNode attributes in_node = model.inputs["input-0"] print(in_node.shape) # Expected output: [18, -1] print(in_node.dtype) # Expected output: tensor(float) print(in_node.transform) # Expected output: audonnx.core.function.Function(reshape) print(repr(in_node)) # Expected output: {shape: [18, -1], dtype: tensor(float), transform: audonnx.core.function.Function(reshape)} # OutputNode attributes out_node = model.outputs["output-1"] print(out_node.shape) # Expected output: [2] print(out_node.dtype) # Expected output: tensor(float) print(out_node.labels) # Expected output: ['output-1-0', 'output-1-1'] print(repr(out_node)) # Expected output: {shape: [2], dtype: tensor(float), labels: [output-1-0, output-1-1]} # Iterating all nodes for name, node in model.inputs.items(): print(f"{name}: shape={node.shape}, transform={node.transform}") for name, node in model.outputs.items(): print(f"{name}: labels={node.labels}") ``` ``` -------------------------------- ### Export PyTorch Model to ONNX Format Source: https://github.com/audeering/audonnx/blob/main/docs/usage.md Exports a PyTorch model to ONNX format, specifying input/output names and dynamic axes for variable input sizes. ```python import audeer import os onnx_root = audeer.mkdir("onnx") onnx_model_path = os.path.join(onnx_root, "model.onnx") dummy_input = torch.randn(y.shape[1:]) torch.onnx.export( torch_model, dummy_input, onnx_model_path, input_names=["feature"], # assign custom name to input node output_names=["gender"], # assign custom name to output node dynamic_axes={"feature": {1: "time"}}, # dynamic size opset_version=12, dynamo=False, ) ```