Ningxin Hu (Intel Corporation) · w3.org

1. Introduction

The Web Neural Network API defines a web-friendly hardware-agnostic abstraction layer that makes use of Machine Learning capabilities of operating systems and underlying hardware platforms without being tied to platform-specific capabilities. The abstraction layer addresses the requirements of key Machine Learning JavaScript frameworks and also allows web developers familiar with the ML domain to write custom code without the help of libraries.

For an illustrated introduction, please see the explainer.

2. Use cases

2.1. Application Use Cases

This section illustrates application-level use cases for neural network inference hardware acceleration. All applications in those use cases can be built on top of pre-trained deep neural network (DNN) [models].

Note: Please be aware that some of the use cases described here, are by their very nature, privacy-invasive. Developers who are planning to use the API for such use cases should ensure that the API is being used to benefit users, for purposes that users understand, and approve. They should apply the Ethical Principles for Web Machine Learning [webmachinelearning-ethics] and implement appropriate privacy risk mitigations such as transparency, data minimisation, and users controls.

Note: § 3 Accessibility Considerations provides guidance on how to improve accessibility of these use cases.

2.1.1. Person Detection

A user opens a web-based video conferencing application, but she temporarily leaves from her room. The application is watching whether she is in front of her PC by using object detection (for example, using object detection approaches such as [SSD] or [YOLO] that use a single DNN) to detect regions in a camera input frame that include persons.

When she comes back, the application automatically detects her and notifies other online users that she is active now.

2.1.2. Semantic Segmentation

A user joins a teleconference via a web-based video conferencing application at her desk since no meeting room in her office is available. During the teleconference, she does not wish that her room and people in the background are visible. To protect the privacy of the other people and the surroundings, the application runs a machine learning model such as [DeepLabv3+], [MaskR-CNN] or [SegAny] to semantically split an image into segments and replaces segments that represent other people and background with another picture.

2.1.3. Skeleton Detection

A web-based video conferencing application tracks a pose of user’s skeleton by running a machine learning model, which allows for real-time human pose estimation, such as [PoseNet] to recognize her gesture and body language. When she raises her hand, her microphone is automatically unmuted and she can start speaking on the teleconference.

2.1.4. Face Recognition

There are multiple people in the conference room and they join an online meeting using a web-based video conferencing application. The application detects faces of participants by using object detection (for example, using object detection approaches such as [SSD]) and checks whether each face was present at the previous meeting or not by running a machine learning model such as [FaceNet], which verifies whether two faces would be identical or not.

2.1.5. Facial Landmark Detection

A user wants to find new glasses that beautifully fits her on an online glasses store. The online store offers web-based try-on simulator that runs a machine learning model such as Face Alignment Network [FAN] to detect facial landmarks like eyes, nose, mouth, etc. When she chooses a pair of glasses, the simulator properly renders the selected glasses on the detected position of eyes on her facial image.

2.1.6. Style Transfer

A user is looking for cosmetics on an online store and wondering which color may fit her face. The online store shows sample facial makeup images of cosmetics, and offers makeup simulator that runs a machine learning model like [ContextualLoss] or [PairedCycleGAN] to transfer the makeup style of the sample makeup image to her facial image. She can check how the selected makeup looks like on her face by the simulator.

2.1.7. Super Resolution

A web-based video conferencing is receiving a video stream from its peer, but the resolution of the video becomes lower due to network congestion. To prevent degradation of the perceived video quality, the application runs a machine learning model for super-resolution such as [SRGAN] to generate higher-resolution video frames.

2.1.8. Image Captioning

For better accessibility, a web-based presentation application provides automatic image captioning by running a machine learning model such as [im2txt] which predicts explanatory words of the presentation slides.

2.1.9. Text-to-image

Images are a core part of modern web experiences. An ability to generate images based on text input in a privacy-preserving manner enables visual personalization and adaptation of web applications and content. For example, a web application can use as an input a natural language description on the web page or a description provided by the user within a text prompt to produce an image matching the text description. This text-to-image use case enabled by latent diffusion model architecture [LDM] forms the basis for additional text-to-image use cases. For example, inpainting where a portion of an existing image on the web page is selectively modified using the newly generated content, or the converse, outpainting, where an original image is extended beyond its original dimensions filling the empty space with generated content.

2.1.10. Machine Translation

Multiple people from various countries are talking via a web-based real-time text chat application. The application translates their conversation by using a machine learning model such as [GNMT] or [OpenNMT], which translates every text into different language.

2.1.11. Emotion Analysis

A user is talking to her friend via a web-based real-time text chat application, and she is wondering how the friend feels because she cannot see the friend’s face. The application analyses the friend’s emotion by using a machine learning model such as [DeepMoji], which infers emotion from input texts, and displays an emoji that represents the estimated emotion.

2.1.12. Video Summarization

A web-based video conferencing application records received video streams, and it needs to reduce recorded video data to be stored. The application generates the short version of the recorded video by using a machine learning model for video summarization such as [Video-Summarization-with-LSTM].

2.1.13. Noise Suppression

A web-based video conferencing application records received audio streams, but usually the background noise is everywhere. The application leverages real-time noise suppression using Recurrent Neural Network such as [RNNoise] for suppressing background dynamic noise like baby cry or dog barking to improve audio experiences in video conferences.

2.1.14. Speech Recognition

Speech recognition, also known as speech to text, enables recognition and translation of spoken language into text. Example applications of speech recognition include transcription, automatic translation, multimodal interaction, real-time captioning and virtual assistants. Speech recognition improves accessibility of auditory content and makes it possible to interact with such content in a privacy-preserving manner in a textual form. Examples of common use cases include watching videos or participating in online meetings using real-time captioning. Models such as [Whisper] approach humans in their accuracy and robustness and are well positioned to improve accessibility of such use cases.

2.1.15. Text Generation

Various text generation use cases are enabled by large language models (LLM) that are able to perform tasks where a general ability to predict the next item in a text sequence is required. This class of models can translate texts, answer questions based on a text input, summarize a larger body of text, or generate text output based on a textual input. LLMs enable better performance compared to older models based on RNN, CNN, or LSTM architectures and further improve the performance of many other use cases discussed in this section. Examples of LLMs include [t5-small], [m2m100_418M], [gpt2], and [llama-2-7b].

2.1.16. Detecting fake video

A user is exposed to realistic fake videos generated by ‘deepfake’ on the web. The fake video can swap the speaker’s face into the president’s face to incite a user politically or to manipulate user’s opinion. The deepfake detection applications such as [FaceForensics++] analyze the videos and protect a user against the fake videos or images. When she watches a fake video on the web, the detection application alerts her of the fraud video in real-time.

2.2. Framework Use Cases

This section collects framework-level use cases for a dedicated low-level API for neural network inference hardware acceleration. It is expected that Machine Learning frameworks will be key consumers of the Web Neural Network API (WebNN API) and the low-level details exposed through the WebNN API are abstracted out from typical web developers. However, it is also expected that web developers with specific interest and competence in Machine Learning will want to interface with the WebNN API directly instead of a higher-level ML framework.

2.2.1. Custom Layer

A web application developer wants to run a DNN model on the WebNN API. However, she has found that some of activation functions like [LeakyReLU], [ELU], etc. are not included in the WebNN API. To address this issue, she constructs custom layers of the additional activation functions on top of the WebNN API. Note that the scope of custom layers may include convolution, normalization, etc. as well as activation.

2.2.2. Network Concatenation

A web application uses a DNN model, and its model data of upper convolutional layers and lower fully-connected layers are stored in separate files, since model data of the fully-connected layers are periodically updated due to fine tuning at the server side.

Therefore, the application downloads both partial model files at first and concatenates them into a single model. When the model is updated, the application downloads fine-tuned part of the model and replace only the fully-connected layers with it.

2.2.3. Performance Adaptation

A web application developer has a concern about performance of her DNN model on mobile devices. She has confirmed that it may run too slow on mobile devices which do not have GPU acceleration. To address this issue, her web application refers to the WebNN API to confirm whether acceleration is available or not, so that the application can display the warning for devices without acceleration.

After several weeks, she has developed a tiny DNN model that can even run on CPU. In order to accommodate CPU execution, she modifies the application so that the application loads the tiny model in the case of CPU-only devices.

2.2.4. Operation Level Execution

A JavaScript ML framework is responsible for loading, interpreting and executing a ML model. During the model execution phase, the framework iterates through the operations of the model and executes each operation on the hardware device, like CPU, GPU or ML accelerator. To avoid the unnecessary data copying across devices, the framework selects the same device to execute the operations. For a compute intensive operation, such as convolution 2D or matrix multiplication, the framework uses WebNN API to execute it with the ML-specific acceleration available on that selected device.

2.2.5. Integration with real-time video processing

The user experience of WebRTC-based video conferencing is enhanced using real-time video processing. For example, background blur implemented using a § 2.1.2 Semantic Segmentation model blurs the background in the user’s live camera feed. To satisfy the performance requirements of this use case, the WebNN API integrates with primitives from other Web APIs that make up the media pipeline to allow WebNN API-based transformation of real-time video streams.

3. Accessibility Considerations

This section provides guidance to web authors on how to improve accessibility of § 2.1 Application Use Cases enabled by neural network inference hardware acceleration. This guidance generalizes beyond the specific use cases outlined in this specification, and web authors are encouraged to consult [wcag] for further accessibility guidance and § 6 Ethical Considerations for digital accessibility in context of ethical principles.

§ 2.1.8 Image Captioning can be improved by ensuring the captions are surfaced to screen-reader and other Assistive Technology (AT) users. Web authors are encouraged to ensure the generated image captions are semantically linked to their respective images, either via the standard alt attribute, or other means which may depend on whether the descriptions are updated on initial page load, or later, as the result of user action.

§ 2.1.11 Emotion Analysis can mis-label and thus mis-classify users, leading to discriminatory experiences. Web authors are encouraged to expose confidence scores and give users an option to turn the feature off.

§ 2.1.13 Noise Suppression with aggressive filters can wipe out the speech of users with dysarthria, making captions and recognition fail. Web authors are encouraged to expose a bypass or sensitivity control, and not hard-wire noise suppression when live captions are active.

§ 2.2.5 Integration with real-time video processing with background-blur powered segmentation helps remove distractions, but can add too much delay that breaks lip-reading and live captions. Web authors are encouraged to provide an ability for user-facing keyboard- and screen-reader-operable “Background blur on/off” control, surfaced next to other accessibility/media settings.

§ 7.2 Device Selection allows web authors to indicate preferences for execution speed and power consumption. Implementers are encouraged to allow users to override the web author hint in browser UI to ensure that people on low-end or battery-sensitive devices can keep captions and other critical accessibility features responsive, especially on portable AAC or eye-gaze setups.

4. Security Considerations

This specification defines a low-level API for neural network inference hardware acceleration. This API is considered a powerful feature [POWERFUL-FEATURES] because it grants low-level access to a user’s computer. To meet the authentication and confidentiality expectations of a powerful feature and to prevent man-in-the-middle attacks, all interfaces defined by this specification are only available in a secure context.

This API is disabled by default in all cross-origin frames using the § 7.5 Permissions Policy Integration. This prevents third-party content from using this API unless the embedding page explicitly sets a policy that grants permission.

This API allows creation of an MLContext from a GPUDevice defined by WebGPU specification. See WebGPU Security Considerations for more information regarding security characteristics of this context.

This API provides an abstraction across GPU, CPU, and dedicated ML accelerator hardware. When using a GPU, denial of service considerations similar to WebGPU apply. When using a CPU or a dedicated ML accelerator, the types of potential resource contention are different and mitigations will be implementation and configuration dependent. Implementations should use whatever mechanisms are available from the platform to prevent sites from using an unfair amount of system resources. These compute units are shared resources, and the use of any compute API will affect overall performance on a fully-loaded system.

Once the graph is fully constructed and compiled, the input shapes into each of the operations in the graph are inferred and finalized. The bounds checking occurs when the compute method is invoked that executes the graph against the actual data. No actual data is bound to the compiled graph before this stage. It is the implementation’s responsibility to make sure proper bounds checking occurs against the shapes of the data already inferred by that time.

Document operations susceptible to out-of-bounds access as a guidance to implementers.

Implementations must defend against control-flow attacks based on changes to data considered to be constant. For example, optimizations in the underlying platform may assume that a weight remains unchanged throughout a computation. If the API allowed the contents of buffers holding weights to change during a computation then those optimization assumptions would be invalidated, causing undefined behavior in the underlying platform. The API mitigates this category of attacks from script by always copying or transferring buffers, but implementations should consider additional defenses such as process isolation of data assumed to be constant.

As a future-proofing measure, the API design allows certain operations that can be generically emulated to be deprecated for security, performance, or other reasons without breaking compatibility. This is made possible by high-level functions that are defined in terms of smaller primitive operations defined in this specifications. This enables a native implementation of a high-level function to be replaced with a polyfill implementation.

Investigate side channel attack feasibility considering the current state where CPU is shared between processes running renderers.

In order to not allow an attacker to target a specific implementation that may contain a flaw, the § 7.2 Device Selection mechanism is a hint only, and the concrete device selection is left to the implementation - a user agent could for instance choose never to run a model on a device with known vulnerabilities. As a further mitigation, no device enumeration mechanism is defined.

Hinting partially mitigates the concern. Investigate additional mitigations.

The API design minimizes the attack surface for the compiled computational graph. The MLGraphBuilder interface that hosts the various operations is a data definition API and as such doesn’t execute anything, only constructs data. What follows, is that the potential for an attack is limited to when binding the data to the graph before executing it by invoking the MLContext.dispatch() method. This enables implementers to focus on hardening the MLContext.dispatch() method. For example, by making sure it honors the boundary of data and fails appropriately when the bounds are not respected.

Purpose-built Web APIs for measuring high-resolution time mitigate against timing attacks using techniques such as resolution reduction, adding jitter, detection of abuse and API call throttling [hr-time-3]. The practical deployment of WebNN implementations are likely to bring enough jitter to make timing attacks impractical (e.g. because they would use IPC) but implementers are advised to consider and test their implementations against timing attacks.

Note: Security risks related to Unicode sequences are discussed in context of the label USVString definition.

4.1. Guidelines for new operations

This section is non-normative.

To ensure operations defined in this specification are shaped in a way they can be implemented securely, this section includes guidelines on how operations are expected to be defined to reduce potential for implementation problems. These guidelines are expected to evolve over time to align with industry best practices:

  • Prefer simplicity of arguments

  • Don’t use parsers for complex data formats

  • If an operation can be decomposed to low level primitives:

    • Add an informative emulation path

    • Prefer primitives over new high level operations but consider performance consequences

  • Follow a consistent style for operation inputs and attributes

  • Share API shape and options for operation families such as pooling and reduction

  • Formalize failure cases into test cases whenever possible

  • When in doubt, leave it out: keep the API surface as small as possible to satisfy the use cases, but no smaller

  • Try to keep the API free of implementation details that might inhibit future evolution, do not overspecify

  • Fail fast: the sooner the web developer is informed of an issue, the better

In general, always consider the security and privacy implications as documented in [security-privacy-questionnaire] by the Technical Architecture Group and the Privacy Interest Group when adding new features.

5. Privacy Considerations

This API provides a privacy improvement over cloud-based inference alternatives by keeping sensitive user data within the browser’s sandbox. Input data such as images, audio, video streams, and other personal information never leave the user’s device, eliminating risks associated with data transmission to remote servers and third-party data processing.

However, as a powerful local compute API that interacts closely with hardware acceleration capabilities, the WebNN API has to balance performance optimization with privacy protection. The API includes multiple privacy-preserving measures to mitigate against fingerprinting while still enabling effective machine learning inference capabilities.

5.1. Fingerprinting

By design, this API aims to expose the minimum amount of information necessary to address the identified § 2 Use cases with the best performance and reliability of results. First, the API mitigates against fingerprinting through standardization: by defining consistent behavior across diverse platform APIs and by minimizing information leakage about the underlying hardware variation across conformant implementations. This is achieved through:

  • § 7.3 Operators that are hardware-agnostic and minimize the exposure of low-level details of the underlying platform, in line with the principle of data minimization.

  • § 8.2.1 MLContextOptions API that allows a web developer to indicate preference for execution speed and power consumption, but does not expose the actual device selected for execution, nor does it allow a web developer to enumerate or select specific devices. This hinting mechanism does not add to the entropy.

  • § 8.3.7 opSupportLimits() API that allows a web developer to query support for specific operators using an explicit query API instead of inferring this information using a side channel. This API can contribute to fingerprintability, but its entropy can be reduced by limiting the number of distinguishable configurations exposed through this API using buckets as appropriate.

  • Standardized data types and tensor operations that work consistently across platforms.

  • Consistent error handling across different backend implementations.

The overall design ensures that implementations maintain a consistent interface across different platforms while providing the necessary functionality. By abstracting platform-specific details, the API can provide privacy-preserving predictable behavior regardless of whether the underlying acceleration is provided by CPU, GPU, or dedicated ML hardware.

Note: MLContextOptions is under active development, and the design is expected to change, informed by further implementation experience and new use cases from the wider web community.

MLGraph.devices API extension has been proposed to expose the actual devices selected for execution after the graph is fully constructed and compiled. Privacy implications of this API extension are under investigation. [Issue #836]

5.2. Execution Time Analysis

The timing characteristics of operations can provide some indirect information about the underlying hardware performance, a feature inherent to any compute API. In certain circumstances an execution time analysis can reveal indirectly the performance of the underlying platform’s neural network hardware acceleration capabilities relative to another underlying platform. See also § 4 Security Considerations for further discussion on timing attacks.

Note: The group welcomes further input on the proposed execution time analysis fingerprinting vector and mitigations.

5.3. WebGPU Comparison

Unlike WebGPU, this API does not intrinsically support custom shader authoring; and as a result is not prone to timing attacks that rely on shader caches, or other persistent data. The API builds upon pre-existing shaders and lower level primitives of the browser or the underlying OS. Web developers who interface with GPUDevice are expected to be aware of WebGPU compilation cache considerations.

The WebGPU API identifies machine-specific artifacts as a privacy consideration. Similarly, the WebNN API’s compute unit scheduling may under certain circumstances introduce a fingerprint. However, similarly to WebGPU, such fingerprints are identical across most or all of the devices of each vendor, mitigating the concern. Furthermore, software implementations can be used to further eliminate such artifacts.

In general, implementers of this API are expected to apply WebGPU Privacy Considerations to their implementations where applicable.

6. Ethical Considerations

The Working Group has started documenting ethical issues associated with using Machine Learning on the Web, to help identify what mitigations its normative specifications should take into account. The Working Group publishes and maintains an Ethical Principles for Web Machine Learning document [webmachinelearning-ethics] open to contributions from the wider community via a dedicated GitHub repository.

7. Programming Model

7.1. Overview

At the heart of neural networks is a computational graph of mathematical operations. These operations are the building blocks of modern machine learning technologies in computer vision, natural language processing, and robotics. The WebNN API is a specification for constructing, compiling, and executing computational graphs of neural networks.

The MLGraph interface represents a compiled computational graph that is immutable (that is, a model).

The MLGraphBuilder interface serves as a builder (factory) to construct a computational graph (its graph ) that is then compiled to create an MLGraph.

In WebNN, a computational graph is composed of operators which act on data, and are the nodes of the graph. MLOperands are a representation of data that flows within the computational graph, and are the edges of the graph. MLOperands include a computational graph’s input values for inference, constants (including trained weights) used for inference, intermediate values (often referred to as activations) computed during inference, as well as the output values of inference. An operator’s input is one or more MLOperands. An operator’s output is one or more MLOperands. Operators have operator-specific parameters that control their behavior, which can include zero or more activation functions .

A key part of the MLGraphBuilder interface are methods such as gemm() and relu() which create an operator which represents the actual operation to perform on the input data when the computation is run, and return a new MLOperand holding the operator. Methods that create an MLOperand connect any inputs and activations to the operator. Each method invocation returns a distinct new value, without changing the value of any other MLOperand.

An operator has a label , a string which may be included in diagnostics such as exception messages. When an operator is created its label is initialized in an implementation-defined manner and may include the passed label.

Consider adding a mechanism for reporting errors during dispatch(). [Issue #778]

At inference time, every MLOperand will be bound to a tensor (the actual data), which are essentially multidimensional arrays. The representation of the tensors is implementation dependent, but it typically includes the array data stored in some buffer (memory) and some metadata describing the array data (such as its shape).

Operations within the computational graph have functional semantics. This allows the implementation to potentially share the array data between multiple tensors. For example, the implementation of operations such as reshape, or slice may return a view of its input tensor that shares the same buffer as the input tensor. (In the case of reshape, the entire data is shared, while in the case of slice, a part of the input data is shared.) The implementation may use views, as above, for intermediate values.

Before the execution, the computation graph that is used to compute one or more specified outputs needs to be converted, compiled, and optimized. The key purpose of the compilation step is to enable optimizations that span two or more operations, such as operation or loop fusion. The user agent may also perform these optimizations during graph conversion.

The MLGraphBuilder.build() method compiles the graph in the background without blocking the calling thread, and returns a Promise that resolves to an MLGraph. Each MLGraphBuilder can build at most one MLGraph.

The MLGraph underlying implementation will be composed of platform-specific representations of operators and operands which correspond to the MLGraphBuilder’s operators and MLOperands, but which are not script-visible and may be compositions or decompositions of the graph as constructed by script.

Once the MLGraph is constructed, the MLContext.dispatch() method performs the execution of the graph asynchronously either on a parallel timeline in a separate worker thread for the CPU execution or on a GPU timeline in a GPU command queue. This method returns immediately without blocking the calling thread while the actual execution is offloaded to a different timeline. The caller supplies the input values using MLNamedTensors, binding the input MLOperands to their values. The caller also supplies MLNamedTensors for output MLOperands which will contain the result of graph execution, if successful, which may be read back to script using the MLContext.readTensor(tensor) method. This type of execution supports CPU, GPU, and NPU devices.

7.2. Device Selection

An MLContext interface represents a global state of neural network execution. One of the important context states is the underlying execution device that manages the resources and facilitates the compilation and the eventual execution of the neural network graph. In addition to the default method of creation with MLContextOptions, an MLContext could also be created from a specific GPUDevice that is already in use by the application.

In a situation when a GPU context executes a graph with a constant or an input in the system memory as an ArrayBufferView, the input content is automatically uploaded from the system memory to the GPU memory, and downloaded back to the system memory of an ArrayBufferView output buffer at the end of the graph execution. This data upload and download cycles will only occur whenever the execution device requires the data to be copied out of and back into the system memory, such as in the case of the GPU. It doesn’t occur when the device is a CPU device. Additionally, the result of the graph execution is in a known layout format. While the execution may be optimized for a native memory access pattern in an intermediate result within the graph, the output of the last operation of the graph must convert the content back to a known layout format at the end of the graph in order to maintain the expected behavior from the caller’s perspective.

When an MLContext is created with MLContextOptions, the user agent selects and creates the underlying execution device by taking into account these options.

Depending on the underlying platform, the user agent may select different combinations of CPU, NPU and GPU devices.

For a history and rationale of this design, please see the device selection explainer.

7.3. Operators

This section is non-normative.

The WebNN API defines a set of operators required by well-known CNN and RNN, transformer and generative models that address key § 2.1 Application Use Cases. The details of each operator are defined in the normative sections of this specification, in alphabetical order by the operator name. These operators are grouped into categories based on their functionality in the following non-normative table to give a functional overview of the API surface.

Note: Some operators belong to multiple categories. For example, clamp() is both a math function and also used as an activation.

Operators by category
Category Operators​
Tensor creation input(), constant()
Tensor manipulation concat(), expand(), gather(), gatherElements(), scatterElements(), gatherND(), scatterND(), where(), pad(), reshape(), slice(), split(), transpose(), resample2d(), reverse(), tile(), triangular()
Tensor quantization quantizeLinear(), dequantizeLinear()
Tensor casting cast()
Mathematics add(), sub(), mul(), div(), max(), min(), clamp(), pow(), abs(), ceil(), cos(), erf(), exp(), floor(), identity(), log(), neg(), reciprocal(), roundEven(), sin(), sqrt(), tan(), tanh(), sign(), clamp()
Logical equal(), notEqual(), greater(), greaterOrEqual(), lesser(), lesserOrEqual(), logicalNot(), logicalAnd(), logicalOr(), logicalXor(), isNaN(), isInfinite()
Matrix multiplication matmul(), gemm()
Convolution conv2d(), convTranspose2d()
Pooling averagePool2d(), l2Pool2d(), maxPool2d()
Activation clamp(), elu(), gelu(), hardSigmoid(), hardSwish(), leakyRelu(), linear(), prelu(), relu(), sigmoid(), softmax(), softplus(), softsign(), tanh()
Normalization batchNormalization(), instanceNormalization(), layerNormalization()
Reduction argMin(), argMax(), reduceL1(), reduceL2(), reduceLogSum(), reduceLogSumExp(), reduceMax(), reduceMean(), reduceMin(), reduceProduct(), reduceSum(), reduceSumSquare(), cumulativeSum()
Recurrent Neural Networks gruCell(), gru(), lstmCell(), lstm()

7.4. Task Source

The ML task source is a task source to be used for all tasks related to asynchronous compilation and execution of MLGraphs and creation of MLContexts.

7.5. Permissions Policy Integration

This specification defines a policy-controlled feature identified by the string " webnn ". Its default allowlist is 'self'.

8. API

8.1. The navigator.ml interface

An ML object is available in the Window and WorkerGlobalScope contexts through the Navigator and WorkerNavigator interfaces respectively and is exposed via navigator.ml.

 interface   mixin    NavigatorML   {
  [ SecureContext ,  SameObject ]  readonly   attribute   ML    ml  ;
};
 Navigator   includes   NavigatorML ;
 WorkerNavigator   includes   NavigatorML ;

8.2. ML interface

 enum   MLPowerPreference  {
   "default" ,
   "high-performance" ,
   "low-power" 
};
 dictionary    MLContextOptions   {
   MLPowerPreference   powerPreference  = "default";
   boolean   accelerated  =  true ;
};
[ SecureContext ,  Exposed =( Window ,  Worker )]
 interface    ML   {
   Promise < MLContext >  createContext ( optional   MLContextOptions   options  = {});
   Promise < MLContext >  createContext ( GPUDevice   gpuDevice );
};

8.2.1. MLContextOptions

Note: MLContextOptions is under active development, and the design is expected to change, informed by further implementation experience and new use cases from the wider web community. The Working Group is considering additional API controls to allow the definition of a fallback device, multiple devices in a preferred order, or an exclusion of a specific device. Other considerations under discussion include error handling, ultimate fallback, and quantized operators. Feedback is welcome on any of these design considerations from web developers, library authors, OS and hardware vendors, and other stakeholders via GitHub. See § 5 Privacy Considerations for additional discussion of fingerprinting considerations.

The powerPreference option is an MLPowerPreference and indicates the application’s preference as related to power consumption. It is one of the following:

" default "
Let the user agent select the most suitable behavior.
" high-performance "
Prioritizes execution speed over power consumption.
" low-power "
Prioritizes power consumption over other considerations such as execution speed.

The accelerated option indicates the application’s preference as related to massively parallel acceleration. This option has less priority than powerPreference. When set to true (by default), the underlying platform will attempt to use the available massively parallel accelerators, such as a GPU or NPU, also depending on the powerPreference. When set to false, the application indicates it prefers CPU inference. If there is contradictory input, for instance when powerPreference is "high-performance" and accelerated is false, then the implementation will choose the best available match in the underlying platform (for instance a high performance CPU mode, or will ignore accelerated as it has less priority than powerPreference).

8.2.2. createContext()

Arguments:

  • options : an MLContextOptions. Provides the application’s preferences for the context.

  • gpuDevice : a GPUDevice. A specific device to use with the context.

Returns: an MLContext.

To create a context given realm realm and options (a GPUDevice or MLContextOptions), run these steps:
  1. Let context be a new MLContext in realm.

  2. If options is a GPUDevice object, then:

    1. Set context.[[contextType]] to "webgpu".

    2. Set context.[[powerPreference]] to "default".

    3. Set context.[[accelerated]] to true.

  3. Otherwise:

    1. Set context.[[contextType]] to "default".

    2. Set context.[[lost]] to a new promise in realm.

    3. If options["powerPreference"] exists, then set context.[[powerPreference]] to options["powerPreference"].

    4. Otherwise, set context.[[powerPreference]] to "default".

    5. If options["accelerated"] exists, then set context.[[accelerated]] to options["accelerated"].

    6. Otherwise, set context.[[accelerated]] to true.

  4. If the user agent cannot support context.[[contextType]], then return failure.

  5. Return context.

The createContext(options) steps are:
  1. Let global be this’s relevant global object.

  2. Let realm be this’s relevant realm.

  3. If global’s associated Document is not allowed to use the webnn feature, then return a new promise in realm rejected with a "SecurityError" DOMException.

  4. Let promise be a new promise in realm.

  5. Run the following steps in parallel.

    1. Let context be the result of creating a context given realm and options. If that returns failure, then queue an ML task with global to reject promise with a "NotSupportedError" DOMException and abort these steps.

    2. Queue an ML task with global to resolve promise with context.

  6. Return promise.

The createContext(gpuDevice) method steps are:
  1. Let global be this’s relevant global object.

  2. Let realm be this’s relevant realm.

  3. If global’s associated Document is not allowed to use the webnn feature, then return a new promise in realm rejected with a "SecurityError" DOMException.

  4. Let promise be a new promise in realm.

  5. Run the following steps in parallel.

    1. Let context be the result of creating a context given realm and gpuDevice. If that returns failure, then queue an ML task with global to reject promise with a "NotSupportedError" DOMException and abort these steps.

    2. Queue an ML task with global to resolve promise with context.

  6. Return promise.

8.3. MLContext interface

The MLContext interface represents a global state of neural network compute workload and execution processes. Each MLContext object has associated context type and MLPowerPreference.
 typedef   record < USVString ,  MLTensor >   MLNamedTensors  ;
 dictionary    MLContextLostInfo   {
   DOMString   message ;
};
[ SecureContext ,  Exposed =( Window ,  Worker )]
 interface    MLContext   {
   undefined   dispatch ( MLGraph   graph ,  MLNamedTensors   inputs ,  MLNamedTensors   outputs );
   Promise < MLTensor >  createTensor ( MLTensorDescriptor   descriptor );
   Promise < MLTensor >  createConstantTensor (
     MLOperandDescriptor   descriptor ,  AllowSharedBufferSource   inputData );
   Promise < ArrayBuffer >  readTensor ( MLTensor   tensor );
   Promise < undefined >  readTensor ( MLTensor   tensor ,  AllowSharedBufferSource   outputData );
   undefined   writeTensor ( MLTensor   tensor ,  AllowSharedBufferSource   inputData );
   MLOpSupportLimits    opSupportLimits  ();
   undefined   destroy ();
   readonly   attribute   boolean   accelerated ;
   readonly   attribute   Promise < MLContextLostInfo >  lost ;
};

MLContext has the following internal slots:

[[contextType]] of type context type.

The MLContext’s context type.

[[powerPreference]] of type MLPowerPreference.

The MLContext’s MLPowerPreference.

[[accelerated]] of type boolean.

The MLContext’s processing type (CPU or massively parallel processing).

[[lost]] of type Promise<MLContextLostInfo>.

A Promise that is resolved when the MLContext’s underlying execution device is no longer available.

[[timeline]]

A timeline associated with the execution of operations on the compute units of the MLContext. These operations include inferencing on computational graphs and modifying the [[data]] of MLTensors.

More rigorously define this timeline. [Issue #529]

The context type is the type of the execution context that manages the resources and facilitates the compilation and execution of the neural network graph:

" default "
Context created per user preference options.
" webgpu "
Context created from WebGPU device.

The accelerated getter steps are to return this.[[accelerated]].

To validate buffer with descriptor given AllowSharedBufferSource bufferSource and MLOperandDescriptor descriptor, run the following steps:
  1. If bufferSource’s byte length is not equal to descriptor’s byte length, then return false.

  2. Switch on the type of bufferSource:

    ArrayBuffer

    Return true.

    SharedArrayBuffer

    Return true.

    ArrayBufferView
    1. If bufferSource is a Uint8Array object, then return true.

    2. If bufferSource matches descriptor’s dataType according to this table, then return true.

    3. Return false.

Note: Using Uint8Array regardless of the descriptor’s dataType is supported as a generic way of representing a slice of an ArrayBuffer, for example part of a WebAssembly.Memory instance. Developers are encouraged to use more specific view types when authoring WebNN code for readability and maintainability.

To validate tensors with descriptors given an MLNamedTensors namedTensors with record<USVString, MLOperandDescriptor> namedDescriptors:
  1. If namedTensors’s size is not equal to namedDescriptors’s size, then return false.

  2. For each nametensor of namedTensors:

    1. If tensor.[[isConstant]] is true, then return false.

    2. If namedDescriptors[name] does not exist, then return false.

    3. If tensor.[[descriptor]] is not equal to namedDescriptors[name], then return false.

  3. Return true.

8.3.1. dispatch()

Schedules the computational workload of a compiled MLGraph on the MLContext’s [[timeline]].

Arguments:

  • graph : an MLGraph. The computational graph to be executed.

  • inputs : an MLNamedTensors. The inputs to the computational graph.

  • outputs : an MLNamedTensors. The outputs of the computational graph.

Returns: undefined.

Note: dispatch() itself provides no signal that graph execution has completed. Rather, callers can await the results of reading back the output tensors. See § 8.3.1.1 Examples below.

The dispatch(graph, inputs, outputs) method steps are:
  1. If graph.[[context]] is not this, then throw a TypeError.

  2. If graph.[[isDestroyed]] is true, then throw an "InvalidStateError" DOMException.

  3. Let allTensors be a list of MLTensors consisting of inputs’s values extended by outputs’s values.

  4. If allTensors contains any duplicate items, then throw a TypeError.

  5. For each tensor of allTensors:

    1. If tensor.[[context]] is not this, then throw a TypeError.

    2. If tensor.[[isDestroyed]] is true, then throw a TypeError.

  6. If validating tensors with descriptors given inputs and graph.[[inputDescriptors]] returns false, then throw a TypeError.

  7. If validating tensors with descriptors given outputs and graph.[[outputDescriptors]] returns false, then throw a TypeError.

  8. Enqueue the following steps to graph.[[context]].[[timeline]]:

    1. Run these steps, but abort when this is lost:

      1. Issue a compute request to graph.[[implementation]] given inputs and outputs.

        Add a mechanism for reporting errors during graph execution. [Issue #778]

When a constant operand is created using a tensor, it is legal for that tensor to be destroyed after build completes. Implementations are expected to ensure that the compiled graph remains valid and unaffected by such destruction.

8.3.1.1. Examples
The following code showcases executing an MLGraph using MLTensors.
 const  descriptor  =   {
  dataType :   'float32'  ,
  shape :   [  2  ,   2  ]
 };
 const  context  =   await  navigator . ml . createContext ();
 const  builder  =   new  MLGraphBuilder ( context );
 // 1. Create a computational graph 'C = 0.2 * A + B'.
 const  constant  =  builder . constant ( descriptor ,   new  Float32Array (  4  ). fill (  0.2  ));
 const  A  =  builder . input (  'A'  ,  descriptor );
 const  B  =  builder . input (  'B'  ,  descriptor );
 const  C  =  builder . add ( builder . mul ( A ,  constant ),  B );
 // 2. Compile the graph.
 const  graph  =   await  builder . build ({  'C'  :  C });
 // 3. Create reusable input and output tensors.
 const   [ inputTensorA ,  inputTensorB ,  outputTensorC ]   =   await  Promise . all ([
  context . createTensor ({ dataType :  A . dataType ,  shape :  A . shape ,  writable :   true  }),
  context . createTensor ({ dataType :  B . dataType ,  shape :  B . shape ,  writable :   true  }),
  context . createTensor ({ dataType :  C . dataType ,  shape :  C . shape ,  readable :   true  })
 ]);
 // 4. Initialize the inputs.
context . writeTensor ( inputTensorA ,   new  Float32Array (  4  ). fill (  1.0  ));
context . writeTensor ( inputTensorB ,   new  Float32Array (  4  ). fill (  0.8  ));
 // 5. Execute the graph.
 const  inputs  =   {
   'A'  :  inputTensorA ,
   'B'  :  inputTensorB
 };
 const  outputs  =   {
   'C'  :  outputTensorC
 };
context . dispatch ( graph ,  inputs ,  outputs );
 // 6. Read back the computed result.
 const  result  =   await  context . readTensor ( outputTensorC );
console . log (  'Output value:'  ,   new  Float32Array ( result ));    // [1, 1, 1, 1]

8.3.2. createTensor()

Creates an MLTensor associated with this MLContext.

The createTensor(descriptor) method steps are:
  1. Let global be this’s relevant global object.

  2. Let realm be this’s relevant realm.

  3. If this is lost, then return a new promise in realm rejected with an "InvalidStateError" DOMException.

  4. Let tensor be the result of creating an MLTensor given this, and descriptor.

  5. Let promise be a new promise in realm.

  6. Enqueue the following steps to this.[[timeline]]:

    1. Run these steps, but abort when this is lost:

      1. Create tensor.[[data]] given descriptor and initialize all bytes to zeros.

      2. If that fails, then queue an ML task with global to reject promise with an "UnknownError" DOMException, and abort these steps.

      3. Otherwise, queue an ML task with global to resolve promise with tensor.

    2. If aborted, then queue an ML task with global to reject promise with an "InvalidStateError" DOMException.

  7. Return promise.

8.3.3. createConstantTensor()

Creates a constant MLTensor associated with this MLContext.

The createConstantTensor(descriptor, inputData) method steps are:
  1. Let global be this’s relevant global object.

  2. Let realm be this’s relevant realm.

  3. If this is lost, then return a new promise in realm rejected with an "InvalidStateError" DOMException.

  4. If checking dimensions given descriptor returns false, then return a new promise in realm rejected with a TypeError.

  5. If validating buffer with descriptor given inputData and descriptor returns false, then return a new promise in realm rejected with a TypeError.

  6. Let bytes be the result of getting a copy of the bytes held by the buffer source given inputData.

  7. Assert: bytes’s length is equal to descriptor’s byte length.

  8. Let tensor be the result of creating a constant MLTensor given this, and descriptor.

  9. Let promise be a new promise in realm.

  10. Enqueue the following steps to this.[[timeline]]:

    1. Run these steps, but abort when this is lost:

      1. Create tensor.[[data]] given descriptor.

      2. If that fails, then queue an ML task with global to reject promise with an "UnknownError" DOMException, and abort these steps.

      3. Copy bytes to tensor.[[data]].

      4. If that fails, then queue an ML task with global to reject promise with an "UnknownError" DOMException, and abort these steps.

      5. Otherwise, queue an ML task with global to resolve promise with tensor.

    2. If aborted, then queue an ML task with global to reject promise with an "InvalidStateError" DOMException.

  11. Return promise.

8.3.4. readTensor(tensor)

Reads back the [[data]] of an MLTensor from the MLContext.[[timeline]] to script.

Arguments:

  • tensor : an MLTensor. The tensor to be read.

Returns: Promise<ArrayBuffer>. A buffer containing the result of the read.

The readTensor(tensor) method steps are:
  1. Let global be this’s relevant global object.

  2. Let realm be this’s relevant realm.

  3. If tensor.[[context]] is not this, then return a new promise in realm rejected with a TypeError.

  4. If tensor.[[isDestroyed]] is true, then return a new promise in realm rejected with a TypeError.

  5. If tensor.[[descriptor]].readable is false, then return a new promise in realm rejected with a TypeError.

  6. Let promise be a new promise in realm.

  7. Append promise to tensor.[[pendingPromises]].

  8. Enqueue the following steps to tensor.[[context]].[[timeline]]:

    1. Run these steps, but abort when this is lost:

      1. Let bytes be a byte sequence containing a copy of tensor.[[data]].

      2. If that fails, then queue an ML task with global and the following steps:

        1. Remove promise from tensor.[[pendingPromises]].

        2. Reject promise with an "UnknownError" DOMException, and abort these steps.

      3. Otherwise, queue an ML task with global and the following steps:

        1. Remove promise from tensor.[[pendingPromises]].

        2. Let buffer be the result of creating an ArrayBuffer from bytes in realm.

        3. Resolve promise with buffer.

    2. If aborted, then queue an ML task with global to reject promise with an "InvalidStateError" DOMException.

  9. Return promise.

8.3.5. readTensor(tensor, outputData)

Bring-your-own-buffer variant of readTensor(tensor). Reads back the [[data]] of an MLTensor into the provided buffer.

The readTensor(tensor, outputData) method steps are:
  1. Let global be this’s relevant global object.

  2. Let realm be this’s relevant realm.

  3. If tensor.[[context]] is not this, then return a new promise in realm rejected with a TypeError.

  4. If tensor.[[isDestroyed]] is true, then return a new promise in realm rejected with a TypeError.

  5. If tensor.[[descriptor]].readable is false, then return a new promise in realm rejected with a TypeError.

  6. If validating buffer with descriptor given outputData and tensor.[[descriptor]] returns false, then return a new promise in realm rejected with a TypeError.

  7. Let promise be a new promise in realm.

  8. Append promise to tensor.[[pendingPromises]].

  9. Enqueue the following steps to tensor.[[context]].[[timeline]]:

    1. Run these steps, but abort when this is lost:

      1. Let bytes be a byte sequence containing a copy of tensor.[[data]].

      2. If that fails, then queue an ML task with global to run these steps:

        1. Remove promise from tensor.[[pendingPromises]].

        2. Reject promise with an "UnknownError" DOMException, and abort these steps.

      3. Otherwise, queue an ML task with global to run these steps:

        1. Remove promise from tensor.[[pendingPromises]].

        2. If outputData is detached, then reject promise with a TypeError, and abort these steps.

          Note: Validating buffer with descriptor above will fail if outputData is detached, but it is possible that outputData could be detached between that step and this one.

        3. Write bytes to outputData.

        4. Resolve promise with undefined.

    2. If aborted, then queue an ML task with global to reject promise with an "InvalidStateError" DOMException.

  10. Return promise.

8.3.6. writeTensor()

Writes data to the [[data]] of an MLTensor on the MLContext’s [[timeline]].

Arguments:

Returns: undefined.

The writeTensor(tensor, inputData) method steps are:
  1. If tensor.[[context]] is not this, then throw a TypeError.

  2. If tensor.[[isDestroyed]] is true, then throw a TypeError.

  3. If tensor.[[descriptor]].writable is false, then throw a TypeError.

  4. If validating buffer with descriptor given inputData and tensor.[[descriptor]] returns false, then throw a TypeError.

  5. Let bytes be the result of getting a copy of the bytes held by the buffer source given inputData.

  6. Assert: bytes’s length is equal to tensor.[[descriptor]]’s byte length.

  7. Enqueue the following steps to tensor.[[context]].[[timeline]]:

    1. Run these steps, but abort when this is lost:

      1. Copy bytes to tensor.[[data]].

        Add a mechanism for reporting errors while writing to a tensor. [Issue #778]

Note: Similar to dispatch(), writeTensor() itself provides no signal that the write has completed. To inspect the contents of a tensor, callers can await the results of reading back the tensor.

8.3.7. opSupportLimits()

The opSupportLimits() exposes level of support that differs across implementations at operator level. Consumers of the WebNN API are encouraged to probe feature support level by using opSupportLimits() to determine the optimal model architecture to be deployed for each target platform.

Note: The opSupportLimits() API is not intended to provide additional entropy for browser fingerprinting. In current implementations this feature support information can be inferred from the OS and browser version alone. If the diversity of future implementations warrants it, this API allows future implementations to add new privacy mitigations e.g. to bucket capabilities similar to WebGPU to reduce entropy.

See § 5 Privacy Considerations for additional discussion of fingerprinting considerations.

8.3.7.1. MLOpSupportLimits dictionary
The MLOpSupportLimits has the following top level members, aside from these, each operator has a corresponding member defined in its builder method.
 dictionary    MLOpSupportLimits   {
   MLInputOperandLayout   preferredInputLayout ;
  [ EnforceRange ]  unsigned   long   long   maxTensorByteLength ;
   MLTensorLimits   input ;
   MLTensorLimits   constant ;
   MLTensorLimits   output ;
};
preferredInputLayout , of type MLInputOperandLayout

Preferred input layout for layout dependent operators like conv2d().

maxTensorByteLength , of type unsigned long long

The maximum supported length of tensors, in bytes.

input , of type MLTensorLimits

Support limits for input MLOperands for an MLGraph.

constant , of type MLTensorLimits

Support limits for constant MLOperands for an MLGraph.

output , of type MLTensorLimits

Support limits for output MLOperands for an MLGraph.

8.3.7.2. MLRankRange dictionary
 dictionary    MLRankRange   {
   unsigned   long   min ;
   unsigned   long   max ;
};
min , of type unsigned long

Minimum supported rank.

max , of type unsigned long

Maximum supported rank.

8.3.7.3. MLTensorLimits dictionary
 typedef   sequence < MLOperandDataType >   MLDataTypeList  ;
 dictionary    MLTensorLimits   {
   MLDataTypeList   dataTypes ;
   MLRankRange   rankRange ;
};
dataTypes , of type MLDataTypeList

Supported data types.

rankRange , of type MLRankRange

Minimum and maximum supported ranks.

8.3.7.4. MLBinarySupportLimits dictionary
 dictionary    MLBinarySupportLimits   {
   MLTensorLimits   a ;
   MLTensorLimits   b ;
   MLTensorLimits   output ;
};
a , of type MLTensorLimits

MLTensorLimits for a operand.

b , of type MLTensorLimits

MLTensorLimits for b operand.

output , of type MLTensorLimits

MLTensorLimits for output operand.

8.3.7.5. MLSingleInputSupportLimits dictionary
 dictionary    MLSingleInputSupportLimits   {
   MLTensorLimits   input ;
   MLTensorLimits   output ;
};
input , of type MLTensorLimits

MLTensorLimits for input operand.

output , of type MLTensorLimits

MLTensorLimits for output operand.

8.3.8. destroy()

The destroy() method can be called to release all resources associated with the context. Any outstanding compute requests and MLTensor creation/read/write requests will fail.

The destroy() method steps are:
  1. If this is lost, then abort these steps.

  2. Run the steps to lose this with an implementation-defined message.

    Note: A message indicating that destroy() was called can help developers distinguish the cause of the context loss.

8.3.9. Errors

When a user agent determines that an MLContext is no longer available to fulfill requests, it must run the context lost steps for it.

The context lost steps for MLContext context, are:
  1. Let global be context’s relevant global object.

  2. Queue an ML task with global to run these steps:

    1. Lose context, with an implementation-defined message.

To lose MLContext context with DOMString message:
  1. Let info be a new MLContextLostInfo.

  2. Set info.message to message.

  3. Resolve context.[[lost]] with info.

  4. For each MLGraph graph where graph.[[context]] equals this:

    1. Run the destroy() method steps for graph with graph as this.

  5. For each MLTensor tensor where tensor.[[context]] equals this:

    1. Run the destroy() method steps for tensor with tensor as this.

message , of type DOMString

An implementation-defined message providing information about the error that occurred.

The lost getter steps are to return this’s [[lost]] Promise.

A MLContext is lost if its [[lost]] Promise is settled.

8.4. MLGraph interface

The MLGraph interface represents a compiled computational graph. A compiled graph once constructed is immutable and cannot be subsequently changed.
[ SecureContext ,  Exposed =( Window ,  Worker )]
 interface    MLGraph   {
   undefined   destroy ();
};

MLGraph has the following internal slots:

[[context]] of type MLContext

The context of type MLContext associated with this MLGraph.

[[inputDescriptors]] of type record<USVString, MLOperandDescriptor>

Maps the name of an input MLOperand to its MLOperandDescriptor for all input MLOperands of this MLGraph.

[[outputDescriptors]] of type record<USVString, MLOperandDescriptor>

Maps the name of an output MLOperand to its MLOperandDescriptor for all output MLOperands of this MLGraph.

[[implementation]]

The underlying implementation provided by the User Agent.

[[isDestroyed]] of type boolean

Whether the MLGraph.destroy() method steps have been run. Once destroyed, the MLGraph can no longer be used.

8.4.1. destroy()

The destroy() method can be called to release all resources associated with the graph.

The destroy() method steps are:
  1. If this.[[isDestroyed]] is true, then abort these steps.

  2. Set this.[[isDestroyed]] to true.

  3. Queue a task on this.[[context]].[[timeline]] to mark resources owned by this graph as freeable.

Note: Since no further workloads can be enqueued using this graph, implementations can free any additional resource allocations associated with this graph once all previously submitted workloads using it are complete.

8.5. MLOperandDescriptor dictionary

An MLOperandDescriptor describes the shape (dimensions) and data type of an operand. They are used to describe the inputs and constants for an MLGraph, and every MLOperand has an internal MLOperandDescriptor.

 enum    MLInputOperandLayout   {
    "nchw"  ,
    "nhwc" 
};
 enum    MLOperandDataType   {
    "float32"  ,
    "float16"  ,
    "int32"  ,
    "uint32"  ,
    "int64"  ,
    "uint64"  ,
    "int8"  ,
    "uint8" 
};
 dictionary    MLOperandDescriptor   {
   required   MLOperandDataType   dataType ;
   required   sequence <[ EnforceRange ]  unsigned   long >  shape ;
};
dataType , of type MLOperandDataType

The operand data type.

shape , of type sequence<[EnforceRange] unsigned long>

The list of dimensions of the operand. It is empty for scalar operands.

An MLOperandDescriptor A is equal to an MLOperandDescriptor B if A.dataType equals B.dataType and A.shape equals B.shape.

To create an MLOperandDescriptor given MLOperandDataType dataType and list shape, run the following steps:
  1. Let descriptor be a new MLOperandDescriptor.

  2. Set descriptor.dataType to dataType.

  3. Set descriptor.shape to a clone of shape.

  4. Return descriptor.

The byte length of an MLOperandDescriptor desc is the value returned by the following steps:
  1. Let elementLength be 1.

  2. For each dimension of desc.shape:

    1. Set elementLength to elementLength * dimension.

  3. Let elementSize be the element size of one of the ArrayBufferView types that matches desc.dataType according to this table.

  4. Return elementLength * elementSize.

The element count of an MLOperandDescriptor desc is the value returned by the following steps:
  1. Let elementCount be 1.

  2. For each dimension of desc.shape:

    1. Set elementCount to elementCount * dimension.

  3. Return elementCount.

A valid dimension is an integer greater than zero and in the range of long. Implementations may impose a smaller upper bound.

A valid tensor count is an integer greater than zero and less or equal to 8192. Implementations may impose a smaller upper bound.

Should 0-size dimensions be supported? [Issue #391]

To check dimensions given MLOperandDescriptor descriptor, run the following steps:
  1. If any item of descriptor.shape is not a valid dimension, then return false.

  2. If descriptor.shape’s size is too large to be supported by the implementation, then return false.

    The maximum number of operand dimensions is not defined, but native ML APIs usually have a maximum supported size. [Issue #456]

  3. If descriptor’s element count is not a valid dimension, then return false.

  4. If descriptor’s byte length is not supported by the implementation, then return false.

  5. Return true.

8.6. MLOperand interface

An MLOperand represents an intermediary graph being constructed as a result of compositing parts of an operation into a fully composed operation.

For instance, an MLOperand can represent a constant feeding to an operation or the result from combining multiple constants together into an operation. See also § 7 Programming Model.

[ SecureContext ,  Exposed =( Window ,  Worker )]
 interface    MLOperand   {
   readonly   attribute   MLOperandDataType   dataType ;
   readonly   attribute   FrozenArray < unsigned   long >  shape ;
};
 dictionary    MLOperatorOptions   {
   USVString   label  = "";
};
 typedef  ( bigint   or   unrestricted   double )  MLNumber ;

MLOperand has the following internal slots:

[[builder]] of type MLGraphBuilder

The MLOperand’s associated builder object.

[[descriptor]] of type MLOperandDescriptor

The MLOperand’s descriptor.

[[name]] of type string

The MLOperand’s name (only for input operands).

[[operator]] of type operator

Reference to MLOperand’s corresponding operator.

[[constantTensor]] of type MLTensor

The MLOperand’s tensor (only for constant operands).

An MLOperand’s dataType is its [[descriptor]].dataType.

An MLOperand’s shape is its [[descriptor]].shape.

An MLOperand’s rank is its shape’s size.

The dataType getter steps are to return this’s dataType.

The shape getter steps are to return this’s shape.

Since the [[builder]] object is bound by the MLGraphBuilder() constructor to an MLContext object, an MLOperand is also always bound to the same MLContext object.

If an operation supports only a subset of MLOperandDataTypes, the allowed data types for each of the operation’s input operands, including both positional arguments and options, are given as either an explicit list of MLOperandDataTypes, or a constraint that the operand’s dataType must be the same as the dataType of another input operand, or any to allow any MLOperandDataType.

Implementations MAY support fewer data types for operands than specified, but MUST support at least the specified required data types . Support can be queried for each operation using the opSupportLimits() method on MLContext and inspecting the dataTypes value of the corresponding member for the operation across ONNX Runtime, LiteRT, and CoreML backends in Chromium prototype now.

The set of required data types has been determined based on implementation experience across a breadth of platforms to ensure that developers can produce interoperable content by designing models to only use these data types. The Web Platform Tests for this specification use this capability detection mechanism to validate correct behavior for all allowed data types but can be passed with only support for the required data types.

If an operation requires input operands with a particular rank, the allowed ranks for each of the operation’s input operands, including both positional arguments and options, are given as an explicit rank (e.g. 1), or N to allow any dimensionality, or the same as another operand. More specific constraints are common, such as when an input operand’s shape must be unidirectionally broadcastable to or bidirectionally broadcastable with another input operand; in these cases, the allowed ranks are listed as a range, with specific validation given as steps in the operation.

Implementations MAY impose a more restricted lower bound and/or upper bound on the rank of operands than specified, but MUST support at least the specified required ranks . Support can be queried for each operation using the opSupportLimits() method on MLContext and inspecting the rankRange.min and rankRange.max values of the corresponding member for the operation across ONNX Runtime, LiteRT, and CoreML backends in Chromium prototype now.

The set of required ranks has been determined based on implementation experience across a breadth of platforms to ensure that developers can produce interoperable content by designing models to be composed of input operands with only these ranks.

MLOperatorOptions has the following members:

label , of type USVString, defaulting to ""

Optionally provided when an operator is created using MLGraphBuilder methods that create MLOperands. The implementation may use this value to initialize the operator’s label.

Note: The label is not intended to be a natural language string. It is a language-independent identifier, analogous to a variable name or error code, like "mul#1234".

Note: Implementations are encouraged to use the label provided by developers to enhance error messages and improve debuggability, including both synchronous errors during graph construction and for errors that occur during the asynchronous build() method.

When displaying labels provided by developers via label in debugging tools, logs, or error messages, implementations should sanitize the output to prevent security risks, such as injection of malicious Unicode sequences (e.g. Bidirectional Text Spoofing [UTR36], Source Code Spoofing [UTS55] and other concerns). For example, implementations should escape or filter control characters (e.g., U+202A to U+202E, U+2066 to U+2069) or use a safe rendering mechanism to neutralize potential spoofing.

8.6.1. Creating an MLOperand

The MLOperand objects are created by the methods of MLGraphBuilder, internally using the following algorithms. To create an MLOperand given MLGraphBuilder builder and MLOperandDescriptor desc, run the following steps:
  1. Let realm be builder’s relevant realm.

  2. Let operand be a new MLOperand in realm.

  3. Set operand.[[builder]] to builder.

  4. Set operand.[[descriptor]] to desc.

  5. Return operand.

To copy an MLOperand given MLOperand operand, run the following steps:
  1. Let builder be operand.[[builder]].

  2. Let realm be builder’s relevant realm.

  3. Let result be a new MLOperand in realm.

  4. Set result.[[builder]] to builder.

  5. Set result.[[descriptor]] to operand.[[descriptor]].

  6. If operand.[[name]] exists, then set result.[[name]] to operand.[[name]].

  7. Return result.

To validate operand given MLGraphBuilder builder and MLOperand operand, return true if operand.[[builder]] is builder, and false otherwise.

8.6.1.1. MLNumber

MLNumber is used when specifying the type of a numeric option for an MLOperand which can be of any MLOperandDataType, including both 64-bit integer types ("uint64" and "int64") and 32-bit floating point ("float32"). Implementations process the value according to the corresponding MLOperandDataType. For example, if clamp(input, options) is called with an MLOperand with dataType "uint32", the MLNumber parameters are explicitly cast to unsigned long.

Specifying the option as double would lose accuracy when passing values over 253, and specifying long long would disallow values over 263.

Support for unions of bigint and numeric types is new in [WEBIDL], and implementation support is also limited. Prototype implementations are encouraged to provide feedback for this approach. [whatwg/webidl Issue #1388]

8.7. MLTensorDescriptor dictionary

An MLTensorDescriptor describes the characteristics and capabilities of an MLTensor.

 dictionary    MLTensorDescriptor   :  MLOperandDescriptor  {
   boolean   readable  =  false ;
   boolean   writable  =  false ;
};
readable , of type boolean, defaulting to false

Whether the tensor’s contents can be read via readTensor(tensor) or readTensor(tensor, outputData).

writable , of type boolean, defaulting to false

Whether the tensor’s contents can be written to via writeTensor().

8.8. MLTensor interface

The MLTensor interface represents a tensor which may be used as an input or output to an MLGraph. The memory backing an MLTensor should be allocated in an implementation-defined fashion according to the requirements of the MLContext and the MLTensorDescriptor used to create it. Operations involving the [[data]] of an MLTensor occur on the [[timeline]] of its associated MLContext.

The implementation-defined requirements of how an MLTensor is allocated may include constraints such as that the memory is allocated with a particular byte alignment or in a particular memory pool.

[ SecureContext ,  Exposed =( Window ,  Worker )]
 interface    MLTensor   {
   readonly   attribute   MLOperandDataType   dataType ;
   readonly   attribute   FrozenArray < unsigned   long >  shape ;
   readonly   attribute   boolean   readable ;
   readonly   attribute   boolean   writable ;
   readonly   attribute   boolean   constant ;
   undefined   destroy ();
};

MLTensor has the following internal slots:

[[context]] of type MLContext

The MLTensor’s associated context.

[[descriptor]] of type MLTensorDescriptor

The MLTensor’s descriptor.

[[pendingPromises]] of type set of Promises

Promises corresponding to MLContext.readTensor(tensor) method calls which are in-progress and have yet to resolve. All pending promises will be rejected when the MLTensor is destroyed.

[[isDestroyed]] of type boolean

Whether the MLTensor.destroy() steps have been run. Once destroyed, the MLTensor can no longer be used.

[[data]] of an implementation-defined type

The bytes backing the MLTensor. This data may only be accessed or modified from the [[context]].[[timeline]].

[[isConstant]] of type boolean

Whether the MLTensor was created by create a constant MLTensor.

An MLTensor’s dataType is its [[descriptor]]’s dataType.

An MLTensor’s shape is its [[descriptor]]’s shape.

The dataType getter steps are to return this’s dataType.

The shape getter steps are to return this’s shape.

The readable getter steps are to return this.[[descriptor]].readable.

The writable getter steps are to return this.[[descriptor]].writable.

The constant getter steps are to return this’s [[isConstant]].

8.8.1. Creating an MLTensor

An MLTensor is created by its associated MLContext.

To create an MLTensor given MLContext context and MLTensorDescriptor descriptor, run the following steps:
  1. Let realm be context’s relevant realm.

  2. Let tensor be a new MLTensor in realm.

  3. Set tensor.[[context]] to context.

  4. Set tensor.[[descriptor]] to descriptor.

  5. Set tensor.[[isDestroyed]] to false.

  6. Set tensor.[[isConstant]] to false.

  7. Return tensor.

8.8.2. destroy()

Releases the resources associated with the MLTensor. This method is idempotent.

The destroy() method steps are:
  1. Set this.[[isDestroyed]] to true.

  2. For each promise in this.[[pendingPromises]]:

    1. Remove promise from this.[[pendingPromises]].

    2. Reject promise with an "InvalidStateError" DOMException.

  3. Enqueue the following steps to this.[[context]].[[timeline]]:

    1. Release this.[[data]].

Note: Since no further operations can be enqueued using this tensor, implementations can free any additional resource allocations associated with this tensor once all previously submitted operations using it are complete.

8.8.3. Creating a constant MLTensor

A constant MLTensor is created by its associated MLContext.

To create a constant MLTensor given MLContext context, MLOperandDescriptor inputDescriptor, run the following steps:
  1. Let realm be context’s relevant realm.

  2. Let tensor be a new MLTensor in realm.

  3. Set tensor.[[context]] to context.

  4. Let tensorDescriptor be a new MLTensorDescriptor.

  5. Set tensorDescriptor.readable to false.

  6. Set tensorDescriptor.writable to false.

  7. Set tensorDescriptor.dataType to inputDescriptor.dataType.

  8. Set tensorDescriptor.shape to inputDescriptor.shape.

  9. Set tensor.[[descriptor]] to tensorDescriptor.

  10. Set tensor.[[isDestroyed]] to false.

  11. Set tensor.[[isConstant]] to true.

  12. Return tensor.

8.9. MLGraphBuilder interface

The MLGraphBuilder interface defines a set of operations as identified by the § 2 Use cases that can be composed into a computational graph. It also represents the intermediate state of a graph building session.

 typedef   record < USVString ,  MLOperand >   MLNamedOperands  ;
[ SecureContext ,  Exposed =( Window ,  Worker )]
 interface    MLGraphBuilder   {
  // Construct the graph builder from the context.
   constructor ( MLContext   context );
  // Create an operand for a graph input.
   MLOperand   input ( USVString   name ,  MLOperandDescriptor   descriptor );
  // Create an operand for a graph constant.
   MLOperand   constant ( MLOperandDescriptor   descriptor ,
                      AllowSharedBufferSource   buffer );
  // Create a scalar operand from the specified number of the specified type.
   MLOperand   constant ( MLOperandDataType   dataType ,  MLNumber   value );
  // Create an operand from a specified constant tensor.
   MLOperand   constant ( MLTensor   tensor );
  // Compile the graph up to the specified output operands asynchronously.
   Promise < MLGraph >  build ( MLNamedOperands   outputs );
};

The MLGraphBuilder.build() method compiles the graph builder state up to the specified output operands into a compiled graph according to the type of MLContext that creates it. When the [[contextType]] of the MLContext is set to "default", the compiled graph is initialized right before the MLGraph is returned. This graph initialization stage is important for optimal performance of the subsequent graph executions. It typically involves a process known as "weight preprocessing" where all the constant inputs to the graph are preprocessed and cached at the operating system level for subsequent graph execution calls. The initializing inputs are typically the constant weight data specified through the constant() method as constant operands during graph construction time.

MLGraphBuilder has the following internal slots:

[[context]] of type MLContext

The context of type MLContext associated with this MLGraphBuilder.

[[hasBuilt]] of type boolean

Whether MLGraphBuilder.build() has been called. Once built, the MLGraphBuilder can no longer create operators or compile MLGraphs.

An MLGraphBuilder can build if its [[hasBuilt]] is false and its [[context]] is not lost.

8.9.1. MLGraphBuilder constructor

Arguments:

The new MLGraphBuilder(context) constructor steps are:
  1. If this’s relevant global object’s associated Document is not allowed to use the webnn feature, then throw a "SecurityError" DOMException.

  2. If context is lost, then throw an "InvalidStateError" DOMException.

  3. Set this.[[context]] to context.

  4. Set this.[[hasBuilt]] to false.

8.9.2. input operands

Create a named MLOperand based on a descriptor, that can be used as an input.

Arguments:

Returns: an MLOperand.

The input(name, descriptor) method steps are:
  1. If this can not build, then throw an "InvalidStateError" DOMException.

  2. If name is empty, then throw a TypeError.

  3. If any MLOperands in this’s graph’s inputs have a [[name]] equal to name, then throw a TypeError.

  4. If checking dimensions given descriptor returns false, then throw a TypeError.

  5. Make graph connections:

    1. Let operand be the result of creating an MLOperand given this and descriptor.

    2. Set operand.[[name]] to name.

    3. Add operand to this’s graph’s inputs.

  6. Return operand.

The MLGraphBuilder API allows creating an MLGraph without input operands. If the underlying platform doesn’t support that, implementations can add a stub input, or pass constants as inputs to the graph.

8.9.3. constant operands

Create a constant MLOperand that can be used in MLGraphBuilder methods.
8.9.3.1. constant(descriptor, buffer)
Create a constant MLOperand of the specified data type and shape that contains the initializing data.

Arguments:

Returns: an MLOperand. The constant output tensor.

The constant(descriptor, buffer) method steps are:
  1. If this can not build, then throw an "InvalidStateError" DOMException.

  2. If checking dimensions given descriptor returns false, then throw a TypeError.

  3. If validating buffer with descriptor given buffer and descriptor returns false, then throw a TypeError.

  4. Make graph connections:

    1. Let operand be the result of creating an MLOperand given this and descriptor.

    2. Let bytes be the result of getting a copy of the bytes held by the buffer source given buffer.

    3. Add operand to this’s graph’s constants with bytes as value.

  5. Return operand.

8.9.3.2. constant(tensor)
Create a constant MLOperand of the specified data type and shape that contains the initialized data.

Arguments:

  • tensor : an MLTensor. The constant tensor containing the initialized data.

Returns: an MLOperand. The constant output tensor.

The constant(tensor) method steps are:
  1. If tensor.[[context]] is not this.[[context]], then throw a TypeError.

  2. If tensor.[[isDestroyed]] is true, then throw a TypeError.

  3. If tensor.[[isConstant]] is false, then throw a TypeError.

  4. If this can not build, then throw an "InvalidStateError" DOMException.

  5. Make graph connections:

    1. Let operand be the result of creating an MLOperand given this and tensor.[[descriptor]].

    2. Set operand.[[constantTensor]] to tensor.

    3. Add operand to this’s graph’s constants with tensor as value.

  6. Return operand.

8.9.3.3. constant(dataType, value)
Create a scalar constant MLOperand of the specified value and data type.

Data truncation will occur when the specified value exceeds the range of the specified output data type e.g. when a floating point value is assigned to an "int8" data type, etc.

Arguments:

Returns: an MLOperand. The constant output.

The constant(dataType, value) method steps are:
  1. If this can not build, then throw an "InvalidStateError" DOMException.

  2. Set value to the result of casting value to dataType.

  3. Let descriptor be the result of creating an MLOperandDescriptor given dataType and « ».

  4. Make graph connections:

    1. Let operand be the result of creating an MLOperand given this and descriptor.

    2. Add operand to this’s graph’s constants with value as value.

  5. Return operand.

8.9.4. build method

Build a composed graph up to a given output operand into a computational graph asynchronously.

Arguments:

Returns: Promise<MLGraph>.

The build(outputs) method steps are:
  1. Let realm be this’s relevant realm.

  2. If this can not build, then return a new promise in realm rejected with an "InvalidStateError" DOMException.

  3. If outputs is empty, then return a new promise in realm rejected with a TypeError.

  4. For each nameoperand of outputs:

    1. If name is empty, then return a new promise in realm rejected with a TypeError.

    2. If validating operand given this and operand returns false, then return a new promise in realm rejected with a TypeError.

    3. If operand is in this’s graph’s inputs or constants, then return a new promise in realm rejected with a TypeError.

    4. If operand.[[constantTensor]] exists and operand.[[constantTensor]].[[isDestroyed]] is true, then return a new promise in realm rejected with a TypeError.

  5. Let operands be a new empty set.

  6. Let operators be a new empty set.

  7. Let inputs be a new empty set.

  8. Let queue be a new queue containing outputs’s values.

  9. While queue is not empty:

    1. Dequeue operand from queue.

    2. Append operand to operands.

    3. Append operand.[[operator]] to operators.

    4. If operand is in this’s graph’s inputs, then append operand to inputs.

    5. For each input of operand.[[operator]]’s inputs:

      1. Enqueue input to queue.

  10. Let global be this’s relevant global object.

  11. Let graph be a new MLGraph in realm.

  12. Set graph.[[context]] to this.[[context]].

  13. Set graph.[[isDestroyed]] to false.

  14. For each operand in inputs:

    1. Set graph.[[inputDescriptors]][operand.[[name]]] to operand.[[descriptor]].

  15. For each nameoperand of outputs:

    1. Set graph.[[outputDescriptors]][name] to operand.[[descriptor]].

  16. Set this.[[hasBuilt]] to true.

  17. Let promise be a new promise in realm.

  18. Enqueue the following steps to graph.[[context]].[[timeline]]:

    1. Run these steps, but abort when graph.[[context]] is lost:

      1. Let graphImpl be the result of converting this’s graph with operands, operators, inputs, and outputs’s values, as well as graph.[[context]].[[powerPreference]] and graph.[[context]].[[accelerated]] into an implementation-defined format which can be interpreted by the underlying platform.

      2. If the previous step failed, then queue an ML task with global to reject promise with an "OperationError" DOMException, and abort these steps.

      3. Set graph.[[implementation]] to graphImpl.

      4. Queue an ML task with global to resolve promise with graph.

    2. If aborted, then queue an ML task with global to reject promise with an "InvalidStateError" DOMException.

  19. Return promise.

NOTE: Specifying an input operand or constant operand as a graph output results in an error, as this is usually an incorrect usage of the API. Callers can work around this by introducing an identity() operator.

8.9.5. argMin/argMax operations

Return the index location of the minimum or maximum values of all the input values along the axis. In case of ties, the identity of the return value is implementation dependent.
 dictionary    MLArgMinMaxOptions   :  MLOperatorOptions  {
   boolean   keepDimensions  =  false ;
   MLOperandDataType   outputDataType  = "int32";
};
 partial   interface   MLGraphBuilder  {
   MLOperand   argMin ( MLOperand   input , [ EnforceRange ]  unsigned   long   axis ,
                    optional   MLArgMinMaxOptions   options  = {});
   MLOperand   argMax ( MLOperand   input , [ EnforceRange ]  unsigned   long   axis ,
                    optional   MLArgMinMaxOptions   options  = {});
};
 partial   dictionary   MLOpSupportLimits  {
   MLSingleInputSupportLimits   argMin ;
   MLSingleInputSupportLimits   argMax ;
};

MLArgMinMaxOptions has the following members:

keepDimensions , of type boolean, defaulting to false

If true, retains reduced dimensions with size 1.

outputDataType , of type MLOperandDataType, defaulting to "int32"

An MLOperandDataType. The output data type.

Arguments:

  • input : an MLOperand. The input N-D tensor.

  • axis : The dimension to reduce. The value must be in the range [0, N-1] where N is the rank of the input tensor.

  • options : an optional MLArgMinMaxOptions. The optional parameters of the operation.

Returns: an MLOperand. The output N-D tensor of rank equal to input’s rank if keepDimensions is true or the input’s rank - 1 if keepDimensions is false. The values must be of type outputDataType in the range [0, N-1] where N is the size of the input dimension specified by axis.

Tensor limits for argMin()/argMax()
operand allowed data types required data types allowed ranks required ranks
input any "float32", "float16", "int32" 1 to N 1 to 5
output "int32", "int64" "int32" N 0 to 5

MLOpSupportLimits has the following members for argMin() and argMax():

argMin , of type MLSingleInputSupportLimits

Support limits for operator argMin().

argMax , of type MLSingleInputSupportLimits

Support limits for operator argMax().

To create an argMin/argMax operation given string op, MLOperand input, unsigned long axis, and MLArgMinMaxOptions options, run the following steps:
  1. Assert: op is one of "argMin", "argMax".

  2. If this can not build, then throw an "InvalidStateError" DOMException.

  3. If validating operand with this and input returns false, then throw a TypeError.

  4. If axis is greater than or equal to input’s rank, then throw a TypeError.

  5. if options.outputDataType is not output tensor’s allowed data types (according to this table), then throw a TypeError.

  6. If input’s shape[axis] is greater than options.outputDataType’s maximum value, then throw a TypeError.

  7. Let outputShape be the result of calculating reduction output sizes given input’s shape, « axis », and options.keepDimensions. If that returns failure, then throw a TypeError.

  8. Let desc be the result of creating an MLOperandDescriptor given options.outputDataType and outputShape.

  9. Make graph connections:

    1. Let operator be an operator for the op operation, given options.

    2. Let output be the result of creating an MLOperand given this and desc.

    3. Set output.[[operator]] to operator.

    4. Set operator’s input to input.

    5. Set operator’s output to output.

  10. Return output.

The following argMin/argMax algorithms are supported.

The argMin(input, axis, options) method steps are:

  1. Let output be the result of creating an argMin/argMax operation given "argMin", input, axis and options.

    1. If that throws an error, then re-throw the error.

  2. Return output.

The argMax(input, axis, options) method steps are:

  1. Let output be the result of creating an argMin/argMax operation given "argMax", input, axis and options.

    1. If that throws an error, then re-throw the error.

  2. Return output.

8.9.6. batchNormalization

Normalize the values of the input tensor using [Batch-Normalization]. For each input feature, the mean and variance values of that feature are computed across all the samples in the batch dimension while the model is trained. These mean and variance values are then subsequently given to this operation during model inference.
 dictionary    MLBatchNormalizationOptions   :  MLOperatorOptions  {
   MLOperand   scale ;
   MLOperand   bias ;
  [ EnforceRange ]  unsigned   long   axis  = 1;
   double   epsilon  = 1e-5;
};
 partial   interface   MLGraphBuilder  {
   MLOperand   batchNormalization ( MLOperand   input ,  MLOperand   mean ,  MLOperand   variance ,
                                optional   MLBatchNormalizationOptions   options  = {});
};
 dictionary    MLBatchNormalizationSupportLimits   {
   MLTensorLimits   input ;
   MLTensorLimits   mean ;
   MLTensorLimits   variance ;
   MLTensorLimits   scale ;
   MLTensorLimits   bias ;
   MLTensorLimits   output ;
};
 partial   dictionary   MLOpSupportLimits  {
   MLBatchNormalizationSupportLimits   batchNormalization ;
};

MLBatchNormalizationOptions has the following members:

scale , of type MLOperand

The 1-D tensor of the scaling values whose size is equal to the size of the input dimension denoted by axis.

bias , of type MLOperand

The 1-D tensor of the bias values whose size is equal to the size of the input dimension denoted by axis.

axis , of type unsigned long, defaulting to 1

The index to the feature count dimension of the input shape for which the mean and variance values are. Its value must be in the range [0, N-1] where N is the rank of the input tensor. The default value is 1, corresponding to the channel ("c") dimension in the "nchw" data layout.

epsilon , of type double, defaulting to 1e-5

A small value to prevent computational error due to divide-by-zero.

Arguments:

  • input : an MLOperand. The input N-D tensor.

  • mean : an MLOperand. Specifies the 1-D tensor of the mean values of the input features across the batch. Its size is equal to the size of the input dimension denoted by axis.

  • variance : an MLOperand. The 1-D tensor of the variance values of the input features across the batch whose size is equal to the size of the input dimension denoted by axis.

  • options : an optional MLBatchNormalizationOptions. Specifies the optional parameters of the operation.

Returns: an MLOperand. The batch-normalized N-D tensor of the same shape as input.

Tensor limits for batchNormalization()
operand allowed data types required data types allowed ranks required ranks
input "float32", "float16" "float32", "float16" 1 to N 3 to 5
mean same as input "float32", "float16" 1 1
variance same as input "float32", "float16" 1 1
scale same as input "float32", "float16" 1 1
bias same as input "float32", "float16" 1 1
output same as input "float32", "float16" same as input 3 to 5

MLBatchNormalizationSupportLimits has the following members:

input , of type MLTensorLimits

MLTensorLimits for input operand.

mean , of type MLTensorLimits

MLTensorLimits for mean operand.

variance , of type MLTensorLimits

MLTensorLimits for variance operand.

scale , of type MLTensorLimits

MLTensorLimits for scale operand.

bias , of type MLTensorLimits

MLTensorLimits for bias operand.

output , of type MLTensorLimits

MLTensorLimits for output operand.

MLOpSupportLimits has the following members for batchNormalization():

batchNormalization , of type MLBatchNormalizationSupportLimits

Support limits for operator batchNormalization().

The batchNormalization(input, mean, variance, options) method steps are:
  1. If this can not build, then throw an "InvalidStateError" DOMException.

  2. If validating operand with this and any of input, mean, variance, options.scale (if it exists), and options.bias (if it exists) returns false, then throw a TypeError.

  3. If input’s dataType is not one of its allowed data types (according to this table), then throw a TypeError.

  4. If options.axis is not in the range 0 to input’s rank, exclusive, then throw a TypeError.

  5. If mean’s dataType is not one of its allowed data types (according to this table), then throw a TypeError.

  6. If mean’s shape is not equal to « input’s shape[options.axis] », then throw a TypeError.

  7. If variance’s dataType is not one of its allowed data types (according to this table), then throw a TypeError.

  8. If variance’s shape is not equal to « input’s shape[options.axis] », then throw a TypeError.

  9. Set options.epsilon to the result of casting options.epsilon to input’s dataType.

  10. If options.scale exists, then:

    1. If its dataType is not one of its allowed data types (according to this table), then throw a TypeError.

    2. If its shape is not equal to « input’s shape[options.axis] », then throw a TypeError.

  11. If options.bias exists, then:

    1. If its dataType is not one of its allowed data types (according to this table), then throw a TypeError.

    2. If its "ref-f

Read the original on w3.org ↗