diff --git a/index.bs b/index.bs index dc91c019..4714113a 100644 --- a/index.bs +++ b/index.bs @@ -39,49 +39,15 @@ Status Text:
-urlPrefix: https://gpuweb.github.io/gpuweb/; spec: WEBGPU - type: interface - text: GPUDevice; url: gpu-device - text: GPUBuffer; url: buffer-interface - for: GPUBuffer; text: size; url: dom-gpubuffer-size - text: GPUTexture; url: texture-interface - text: GPUQueue; url: queues - text: GPUCommandBuffer; url: command-buffers - text: GPUCommandBufferDescriptor; url: dictdef-gpucommandbufferdescriptor urlPrefix: https://tc39.es/ecma262/; spec: ECMA-262 type: dfn text: element size; url: table-the-typedarray-constructors text: element type; url: table-the-typedarray-constructors text: view constructor; url: table-the-typedarray-constructors - text: Construct; url: sec-construct -urlPrefix: https://webidl.spec.whatwg.org/; spec: WEBIDL - type: interface - text: Promise; url: idl-promise - text: nullable; url: idl-nullable-type - type: dfn - text: underlying buffer; url: buffersource-underlying-buffer - text: buffer byte length; url: buffersource-byte-length urlPrefix: https://tc39.es/proposal-float16array/; spec: float16array type: interface text: Float16Array; url: sec-float16array-
-{ - "WEBGPU": { - "authors": [ - "Dzmitry Malyshau", - "Kai Ninomiya" - ], - "href": "https://gpuweb.github.io/gpuweb/", - "title": "WebGPU", - "status": "ED", - "publisher": "W3C", - "deliveredBy": [ - "https://www.w3.org/2020/gpu/" - ] - } -} -
spec:html; @@ -104,19 +70,19 @@ p, ul, ol, dl { margin: 1em 0; } -/* Box for Valid Usage requirements. */ -div.validusage { - padding: .5em; - border: thin solid #88e !important; - border-radius: .5em; -} - /* * Stylistic labels, for clarity of presentation of these blocks. * * NOTE: This text is non-accessible and non-selectable; surrounding * text must also explain the context. */ + +/* Box for Valid Usage requirements. */ +div.validusage { + padding: .5em; + border: thin solid #88e !important; + border-radius: .5em; +} .validusage { position: relative; } @@ -134,6 +100,90 @@ div.validusage { content: "Valid Usage"; } +details { + padding: .5em; + border: thin solid #88e !important; + border-radius: .5em; +} + +summary { + font-weight: bold; + margin: -0.5em -0.5em 0; + padding: 0.5em; +} + +/* Box for algorithm steps. */ + +div.algorithm-steps { + padding: .5em; + background-color: ghostwhite; +} + +.algorithm-steps { + position: relative; + overflow: hidden; +} +.algorithm-steps::after { + font-weight: bold; + font-style: italic; + font-size: 130%; + color: rgba(0, 0, 0, 0.15); + color: var(--watermark-text); + position: absolute; + right: .3em; + bottom: .1em; +} +.algorithm-steps::after { + content: "Algorithm"; +} + +/* Informal steps */ +div.informalsteps { + padding: .5em; + border: thin solid #88e !important; + border-radius: .5em; + background-color: ghostwhite; +} + +.informalsteps { + position: relative; +} +.informalsteps::after { + font-weight: bold; + font-style: italic; + font-size: 130%; + color: rgba(0, 0, 0, 0.15); + color: var(--watermark-text); + position: absolute; + right: .3em; + bottom: .1em; +} +.informalsteps::after { + content: "Non-normative"; +} + +/* Internal slots */ +div.internal-slots { + padding: .5em; + border: thin solid #88e !important; + border-radius: .5em; + background-color: aliceblue; +} + +.internal-slots { + position: relative; +} +.internal-slots::after { + font-weight: bold; + font-style: italic; + font-size: 130%; + color: rgba(0, 0, 0, 0.15); + color: var(--watermark-text); + position: absolute; + right: .3em; + bottom: .1em; +} + /* * Ensure that argumentdef blocks don't overflow algorithm section borders. This is made far harder * than it needs to be because the top-level W3C stylesheet has several @media + min-width variants @@ -232,8 +282,116 @@ th, td { } } + +/* Floating button for collapse/expand all details elements */ + +.collapse-expand-button { + position: fixed; + bottom: 40px; + right: 40px; + width: 40px; + height: 40px; + border: none; + border-radius: 50%; + background-color: green; + color: ghostwhite; + font-size: 32px; + text-align: center; + align-items:center; + justify-content:center; + cursor: pointer; +} + +.collapse-expand-button:hover { + background-color: green; +} + +.collapse-expand-button.expand { + background-color: red; +} + +.collapse-expand-button.expand::before { + content: "+"; +} + +.collapse-expand-button.collapse { + background-color: green; +} + +.collapse-expand-button.collapse::before { + content: "-"; +} + +.collapse-expand-button .tooltiptext { + visibility: hidden; + bottom: 20px; + right: 20px; + width: 120px; + background-color: ghostwhite; + color: black; + font-size: 18px; + text-align: center; + align-items:center; + justify-content:center; + padding: 5px 0; + border-radius: 5px; + + /* position */ + position: absolute; + z-index: 1; + bottom: 100%; + left: 50%; + margin-left: -60px; + /* Use half of the width (120/2 = 60), to center the tooltip */ +} + +.collapse-expand-button:hover .tooltiptext { + visibility: visible; + opacity: 0.75; +} + +/* end of floating collapse/expand button */ + + + + + Introduction {#intro} ===================== @@ -617,12 +775,12 @@ string "webnn
". Its default allowlist is'self'
. ### The {{ML/createContext()}} method ### {#api-ml-createcontext} -The {{ML/createContext()}} method steps are: -1. If [=this=]'s [=relevant global object=]'s [=associated Document=] is not [=allowed to use=] the [=webnn-feature|webnn=] feature, return [=a new promise=] [=rejected=] with a "{{SecurityError}}" {{DOMException}} and abort these steps. -1. Let |promise| be [=a new promise=]. -1. Return |promise| and run the following steps [=in parallel=]. -1. Let |options| be the first argument. -1. Run the create context steps given |options|: + +++ ++ To create a context given |options|, run these steps: +
+1. Let |context| be a new {{MLContext}} object. 1. If |options| is a {{GPUDevice}} object, 1. Set |context|.{{[[contextType]]}} to "[=webgpu-context|webgpu=]". @@ -632,16 +790,63 @@ The {{ML/createContext()}} method steps are: 1. Set |context|.{{[[contextType]]}} to "[=default-context|default=]". 1. If |options|["{{deviceType}}"] [=map/exists=], then set |context|.{{[[deviceType]]}} to |options|["{{deviceType}}"]. Otherwise, set |context|.{{[[deviceType]]}} to "[=device-type-cpu|cpu=]". 1. If |options|["{{powerPreference}}"] [=map/exists=], then set |context|.{{[[powerPreference]]}} to |options|["{{powerPreference}}"]. Otherwise, set |context|.{{[[powerPreference]]}} to "[=power-preference-default|default=]". -1. If the validate MLContext steps given |context| return `false`, [=reject=] |promise| with a "{{NotSupportedError}}" {{DOMException}} and abort these steps. -1. [=Resolve=] |promise| with |context|. + 1. Return |context|. ++++ ++ The createContext(|options|) steps are: +
++ 1. If [=this=]'s [=relevant global object=]'s [=associated Document=] is not [=allowed to use=] the [=webnn-feature|webnn=] feature, return [=a new promise=] [=rejected=] with a "{{SecurityError}}" {{DOMException}}. + 1. Let |promise| be [=a new promise=]. + 1. Return |promise| and run the following steps [=in parallel=]. + 1. Let |context| be the result of [=creating a context=] given |options|. + 1. If validating MLContext given |context| returns false, [=reject=] |promise| with a "{{NotSupportedError}}" {{DOMException}}. + 1. [=Resolve=] |promise| with |context|. +++### The {{ML/createContextSync()}} method ### {#api-ml-createcontextsync} -The {{ML/createContextSync()}} method steps are: -1. If [=this=]'s [=relevant global object=]'s [=associated Document=] is not [=allowed to use=] the [=webnn-feature|webnn=] feature, throw a "{{SecurityError}}" {{DOMException}} and abort these steps. -1. Let |options| be the first argument. -1. Let |context| be the result of running the create context steps given |options|. -1. If the validate MLContext steps given |context| return `false`, throw a "{{NotSupportedError}}" {{DOMException}} and abort these steps. -1. Return |context|. + ++ The createContext(|gpuDevice|) method steps are: +
++ 1. If [=this=]'s [=relevant global object=]'s [=associated Document=] is not [=allowed to use=] the [=webnn-feature|webnn=] feature, return [=a new promise=] [=rejected=] with a "{{SecurityError}}" {{DOMException}}. + 1. Let |promise| be [=a new promise=]. + 1. Return |promise| and run the following steps [=in parallel=]. + 1. Let |context| be the result of [=creating a context=] given |gpuDevice|. + 1. If validating MLContext given |context| returns false, [=reject=] |promise| with a "{{NotSupportedError}}" {{DOMException}}. + 1. [=Resolve=] |promise| with |context|. ++++ ++ The createContextSync(|options|) method steps are: +
++ 1. If [=this=]'s [=relevant global object=]'s [=associated Document=] is not [=allowed to use=] the [=webnn-feature|webnn=] feature, then [=exception/throw=] a "{{SecurityError}}" {{DOMException}}. + 1. Let |context| be the result [=creating a context=] |options|. + 1. If validating MLContext given |context| return false, then [=exception/throw=] a "{{NotSupportedError}}" {{DOMException}}. + 1. Return |context|. +++## The MLGraph interface ## {#api-mlgraph} The {{MLGraph}} interface represents a compiled computational graph. A compiled graph once constructed is immutable and cannot be subsequently changed. @@ -651,9 +856,9 @@ The {{MLGraph}} interface represents a compiled computational graph. A compiled interface MLGraph {}; ++ The createContextSync(|gpuDevice|) method steps are: +
++ 1. If [=this=]'s [=relevant global object=]'s [=associated Document=] is not [=allowed to use=] the [=webnn-feature|webnn=] feature, then [=exception/throw=] a "{{SecurityError}}" {{DOMException}}. + 1. Let |context| be the result [=creating a context=] with |gpuDevice|. + 1. If validating MLContext given |context| return false, then [=exception/throw=] a "{{NotSupportedError}}" {{DOMException}}. + 1. Return |context|. ++{{MLGraph}} has the following internal slots: - -### The MLOperandDescriptor dictionary ### {#api-mloperanddescriptor} -+
+: \[[context]] of type {{MLContext}} :: The context of type {{MLContext}} associated with this {{MLGraph}}. @@ -669,7 +874,8 @@ interface MLGraph {}; : \[[implementation]] :: The underlying implementation provided by the User Agent. -
+++ ### The MLOperand interface ### {#api-mloperand} @@ -717,9 +926,9 @@ For instance, an {{MLOperand}} may represent a constant feeding to an operation interface MLOperand {}; -{{MLOperand}} has the following internal slots:+The byte length of an {{MLOperandDescriptor}} |desc| is the value returned by the following steps: - +
+1. Let |elementLength| be 1. - 1. For each |dimension| of |desc|.{{MLOperandDescriptor/dimensions}}: + 1. [=map/For each=] |dimension| of |desc|.{{MLOperandDescriptor/dimensions}}: 1. Set |elementLength| to |elementLength| × |dimension|. 1. Let |elementSize| be the [=element size=] of one of the {{ArrayBufferView}} types that matches |desc|.{{MLOperandDescriptor/type}} according to [this table](#appendices-mloperandtype-arraybufferview-compatibility). 1. Return |elementLength| × |elementSize|. -+-+ ++{{MLOperand}} has the following internal slots: +
+: \[[builder]] of type {{MLGraphBuilder}} :: The {{MLOperand}}'s associated builder object. @@ -739,7 +948,14 @@ interface MLOperand {}; : \[[operator]] of type [=object=] :: Reference to {{MLOperand}}'s corresponding [=implementation-defined=] platform operator object. -
++To get the rank of an {{MLOperand}} |operand|, run the following steps: +Since the {{MLOperand/[[builder]]}} object is bound by the {{MLGraphBuilder/constructor()}} constructor to an {{MLContext}} object, an {{MLOperand}} is also always bound to the same {{MLContext}} object. @@ -747,24 +963,58 @@ Since the {{MLOperand/[[builder]]}} object is bound by the {{MLGraphBuilder/cons #### Creating {{MLOperand}} #### {#api-mloperand-create} The {{MLOperand}} objects are created by the methods of {{MLGraphBuilder}}, internally using the following algorithms. -To create MLOperand given |builder| and |desc|, run the following steps: -+ 1. Return the [=list/size=] of |operand|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}. +- 1. If |builder| is not an instance of {{MLGraphBuilder}}, then throw a "{{TypeError}}" {{DOMException}} and stop. - 1. If |desc| is not an [=object=] that [=implements=] {{MLOperandDescriptor}}, then throw a "{{TypeError}}" {{DOMException}} and stop. ++ + +++ To create an MLOperand given |builder| and |desc|, run the following steps: +
++ 1. [=Assert=]: the type of |builder| is {{MLGraphBuilder}}. + 1. [=Assert=]: the type of |desc| is {{MLOperandDescriptor}}. 1. Let |operand| be a new [=object=]. 1. Set |operand|.{{MLOperand/[[builder]]}} to |builder|. 1. Set |operand|.{{MLOperand/[[descriptor]]}} to |desc|. 1. Return |operand|. -- -To check dimensions given |dimensions| and |type|, run the following steps: -- 1. If |dimensions| is not an array of positive numbers, return `false`; - 1. If |dimensions|.length is 0, return `false`. - 1. If |dimensions|.length is too large to be supported by the implementation, return `false`. - 1. If any element of |dimensions| is not a positive number, or it is too large to be supported by the implementation given |type|, return `false`. - 1. Return `true`. -+++ ++ To copy an MLOperand given |operand|, run the following steps: +
++ 1. [=Assert=]: the type of |operand| is {{MLOperand}}. + 1. Let |result| be a new [=object=]. + 1. Set |result|.{{MLOperand/[[builder]]}} to |operand|.{{MLOperand/[[builder]]}}. + 1. Set |result|.{{MLOperand/[[descriptor]]}} to |operand|.{{MLOperand/[[descriptor]]}}. + 1. If |operand|.{{MLOperand/[[name]]}} [=map/exists=], then set |result|.{{MLOperand/[[name]]}} to |operand|.{{MLOperand/[[name]]}}. + 1. Return |result|. ++++ ++ To check dimensions given |dimensions| and |type|, run the following steps: +
++ 1. If the [=list/size=] of |dimensions| is 0, return false. + 1. If the [=list/size=] of |dimensions| is too large to be supported by the implementation, return false. + 1. If any element of |dimensions| is not a positive number, or it is too large to be supported by the implementation given |type|, return false. + 1. Return true. +++### The MLActivation interface ### {#api-mlactivation} @@ -772,17 +1022,58 @@ Objects implementing the {{MLActivation}} interface represent activation functio ++ To validate MLOperand given |operand| and |builder|, run the following steps: +
++ 1. [=Assert=]: the type of |operand|.{{MLOperand/[[builder]]}} is {{MLGraphBuilder}}. + 1. If |builder| is not equal to |operand|.{{MLOperand/[[builder]]}}, return false. + 1. Let |desc| be |operand|.{{MLOperand/[[descriptor]]}}. + 1. If |desc|.{{MLOperandDescriptor/dimensions}} [=map/exists=] and invoking check dimensions given |desc|.{{MLOperandDescriptor/dimensions}} and |desc|.{{MLOperandDescriptor/type}} returns false, then return false. + 1. Return true. +++{{MLActivation}} has the following internal slots: +++ : \[[name]] of type [=string=] + :: + The {{MLActivation}}'s name. + : \[[builder]] of type {{MLGraphBuilder}} + :: + The graph builder object this {{MLActivation}} belongs to. + : \[[options]] of type [=object=] + :: + A dictionary containing {{MLActivation}} options. + : \[[operator]] of type [=object=] + :: + Reference to {{MLActivation}}'s corresponding [=implementation-defined=] platform operator object. +
+These activations function types are used to create other operations. One such use of this interface is for when an activation function is fused into another operation such as [[#api-mlgraphbuilder-conv2d]] or [[#api-mlgraphbuilder-batchnorm]] during a graph construction session. Such fused activation functions can provide a significant performance improvement when supported natively by the underlying implementation. This is intended as an optimization opportunity for implementers.+#### Creating {{MLActivation}} #### {#api-mlactivation-create}-The implementation of the {{MLActivation}} interface can simply be a struct that holds a string type of the activation function along with other properties needed. The actual creation of the activation function e.g. a [[#api-mlgraphbuilder-sigmoid]] or [[#api-mlgraphbuilder-relu]] can then be deferred until when the rest of the graph is ready to connect with it such as during the construction of [[#api-mlgraphbuilder-conv2d]] for example. +The {{MLActivation}} objects (including the ones passed as input to methods) are created by the methods of {{MLGraphBuilder}} and are identified by their name. The |options| dictionary is defined by those methods. The actual creation of the activation function e.g. a [[#api-mlgraphbuilder-sigmoid-method]] or [[#api-mlgraphbuilder-relu-method]] can then be deferred until when the rest of the graph is ready to connect with it such as during the construction of [[#api-mlgraphbuilder-conv2d]] for example.+++ ## The MLContext interface ## {#api-mlcontext} The {{MLContext}} interface represents a global state of neural network compute workload and execution processes. Each {{MLContext}} object has associated [=context type=], [=device type=] and [=power preference=]. @@ -819,9 +1110,9 @@ typedef record+ To create an MLActivation given |builder|, |name|, |options| and |init-steps|, run the following steps: +
++ 1. [=Assert=]: the type of |builder| is {{MLGraphBuilder}}. + 1. If |name| is empty, then [=exception/throw=] a "{{TypeError}}". + 1. Let |activation| be a new [=object=]. + 1. Set |activation|.{{MLActivation/[[builder]]}} to |builder|. + 1. Set |activation|.{{MLActivation/[[name]]}} to |name|. + 1. If |options| is an [=object=], set |activation|.{{MLActivation/[[options]]}} to |options|. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Make a request to the underlying platform to: + 1. Create an [=implementation-defined=] platform operator |opImpl| for the given |name| operation. + 1. Store a reference of |opImpl| in |activation|.{{MLActivation/[[operator]]}}. + 1. If |init-steps| are defined, run |init-steps| with |options|. + 1. Otherwise, initialize |activation|.{{MLActivation/[[operator]]}} given |options| in an [=implementation-defined=] way for the given |name| operation. + 1. Return |activation|. ++MLNamedArrayBufferViews; interface MLContext {}; + {{MLContext}} has the following internal slots: - -+
+: \[[contextType]] of type [=context type=] :: The {{MLContext}}'s [=context type=]. @@ -831,22 +1122,30 @@ interface MLContext {}; : \[[powerPreference]] of type [=power preference=] :: The {{MLContext}}'s [=power preference=]. -
+When the {{[[contextType]]}} is set to [=default-context|default=] with the {{MLContextOptions}}.{{deviceType}} set to [=device-type-gpu|gpu=], the user agent is responsible for creating an internal GPU device that operates within the context and is capable of ML workload submission on behalf of the calling application. In this setting however, only {{ArrayBufferView}} inputs and outputs are allowed in and out of the graph execution since the application has no way to know what type of internal GPU device is being created on their behalf. In this case, the user agent is responsible for automatic uploads and downloads of the inputs and outputs to and from the GPU memory using this said internal device.### The {{MLContext}} validation algorithm ### {#api-mlcontext-validate} -To validate {{MLContext}}, given |context|, run these steps: -1. If |context|.{{[[contextType]]}} is not "[=webgpu-context|webgpu=]" or "[=default-context|default=], return `false`. -1. If |context|.{{[[deviceType]]}} is not "[=device-type-cpu|cpu=]" or "[=device-type-gpu|gpu=]", return `false`. -1. If |context|.{{[[powerPreference]]}} is not "[=power-preference-default|default=]" or "[=power-preference-high-performance|high-performance=]" or "[=power-preference-low-power|low-power=]", return `false`. -1. If the user agent cannot support |context|.{{[[contextType]]}}, |context|.{{[[deviceType]]}} and |context|.{{[[powerPreference]]}}, return `false`. -1. Return `true`; + ++### Synchronous Execution ### {#api-mlcontext-sync-execution} -Synchronously carries out the computational workload of a compiled graph {{MLGraph}} on the calling thread, which must be a worker thread, to produce results as defined by the operations in the graph. This method of execution requires an {{MLContext}} created with {{MLContextOptions}}. Otherwise, it throws an "{{OperationError}}" {{DOMException}}. +Synchronously carries out the computational workload of a compiled graph {{MLGraph}} on the calling thread, which must be a worker thread, to produce results as defined by the operations in the graph. This method of execution requires an {{MLContext}} created with {{MLContextOptions}}. Otherwise, it[=exception/throws=] an "{{OperationError}}" {{DOMException}}. -+ To validate MLContext, given |context|, run these steps: +
++ 1. If |context|.{{[[contextType]]}} is not "[=webgpu-context|webgpu=]" or "[=default-context|default=]", return false. + 1. If |context|.{{[[deviceType]]}} is not "[=device-type-cpu|cpu=]" or "[=device-type-gpu|gpu=]", return false. + 1. If |context|.{{[[powerPreference]]}} is not "[=power-preference-default|default=]" or "[=power-preference-high-performance|high-performance=]" or "[=power-preference-low-power|low-power=]", return false. + 1. If the user agent cannot support |context|.{{[[contextType]]}}, |context|.{{[[deviceType]]}} and |context|.{{[[powerPreference]]}}, return false. + 1. Return true; ++- ++ #### Examples #### {#api-mlcontext-sync-execution-examples}**Arguments:** - *graph*: an {{MLGraph}}. The compiled graph to be executed. - *inputs*: an {{MLNamedArrayBufferViews}}. The resources of inputs. - *outputs*: an {{MLNamedArrayBufferViews}}. The pre-allocated resources of required outputs. **Returns:** {{undefined}}. +-The {{MLContext/computeSync(graph, inputs, outputs)}} method steps are: - 1. If |graph|.{{MLGraph/[[context]]}}.{{MLContext/[[contextType]]}} is not "[=default-context|default=], throw an "{{OperationError}}" {{DOMException}} and stop. - 1. If invoking the validate graph resources algorithm given |inputs| and |graph|.{{MLGraph/[[inputDescriptors]]}} returns `false`, then throw a "{{DataError}}" {{DOMException}} and stop. - 1. If invoking the validate graph resources algorithm given |outputs| and |graph|.{{MLGraph/[[outputDescriptors]]}} returns `false`, then throw a "{{DataError}}" {{DOMException}} and stop. +++ ++ The computeSync(|graph|, |inputs|, |outputs|) method steps are: +
++ 1. If |graph|.{{MLGraph/[[context]]}}.{{MLContext/[[contextType]]}} is not "[=default-context|default=]", [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. If validating graph resources given |inputs| and |graph|.{{MLGraph/[[inputDescriptors]]}} returns false, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If validating graph resources given |outputs| and |graph|.{{MLGraph/[[outputDescriptors]]}} returns false, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. 1. Invoke execute graph given |graph|, |inputs| and |outputs|. - 1. If that throws an error, re-throw the error and stop. + 1. If that [=exception/throws=] an error, re-[=exception/throw=] the error. 1. Return {{undefined}}. - -+-To validate graph resources, given |resources| and |descriptors|, run the following steps: ++ + +++ To validate graph resources, given |resources| and |descriptors|, run the following steps: +
+1. [=Assert=]: the type of |resources| is {{MLNamedArrayBufferViews}}. - 1. For each [=record=] <|key|, |value|> of |resources|: - 1. If |descriptors|[|key|] does not [=map/exist=], return `false`. + 1. [=map/For each=] [=record=] <|key|, |value|> of |resources|: + 1. If |descriptors|[|key|] does not [=map/exist=], return false. 1. [=Assert=]: the type of |value| is {{ArrayBufferView}}. - 1. If running the validate buffer with descriptor given |value| and |descriptors|[|key|] return `false`, return `false`. - 1. Return `true`. -- --To validate buffer with descriptor given |bufferView| and |descriptor|, run the following steps: - 1. If |bufferView| is not an {{MLBufferView}}, return `false`. - 1. If |bufferView|'s [=element type=] does not match to |descriptor|.{{MLOperandDescriptor/type}} according to [this table](#appendices-mloperandtype-arraybufferview-compatibility), return `false`. - 1. If |bufferView|.\[[ByteLength]] is not equal to the [=byte length=] of |descriptor|, return `false`. -- -To execute graph, given |graph|, |inputs| and |outputs|, run the following steps: + 1. If validating buffer with descriptor given |value| and |descriptors|[|key|] returns false, then return false. + 1. Return true. +++ ++ To validate buffer with descriptor given |bufferView| and |descriptor|, run the following steps: +
++ 1. If |bufferView| is not an {{MLBufferView}}, return false. + 1. If |bufferView|'s [=element type=] does not match to |descriptor|.{{MLOperandDescriptor/type}} according to [this table](#appendices-mloperandtype-arraybufferview-compatibility), return false. + 1. If |bufferView|.\[[ByteLength]] is not equal to the [=byte length=] of |descriptor|, return false. ++++ To execute graph, given |graph|, |inputs| and |outputs|, run the following steps: +
+1. [=Assert=]: the type of |inputs| is {{MLNamedArrayBufferViews}}. 1. Let |inputResources| denote the input resources of |graph|.{{MLGraph/[[implementation]]}}. - 1. For each <|key|, |inputValue|> of |inputs|: + 1. [=map/For each=] <|key|, |inputValue|> of |inputs|: 1. Let |inputDescriptor| be |graph|.{{MLGraph/[[inputDescriptors]]}}[|key|]. 1. Let |inputTensor| be a new tensor for |graph|.{{MLGraph/[[implementation]]}} as follows: 1. Set the data type of |inputTensor| to the one that matches the [=element type=] of |inputValue|. @@ -901,66 +1218,78 @@ To execute graph, given |graph|, |inputs| and |out 1. Set the values of elements in |inputTensor| to the values of elements in |inputValue|. 1. Request the underlying implementation of |graph| to bind |inputResources|[|key|] to |inputTensor|. 1. [=Assert=]: the type of |outputs| is {{MLNamedArrayBufferViews}}. - 1. For each <|key|, |outputValue|> of |outputs|: + 1. [=map/For each=] <|key|, |outputValue|> of |outputs|: 1. Issue a compute request to |graph|.{{MLGraph/[[implementation]]}} given |key| and |inputResources| and wait for completion. - 1. If that returns an error, then throw an "{{OperationError}}" {{DOMException}} and stop. + 1. If that returns an error, then [=exception/throw=] an "{{OperationError}}" {{DOMException}}. 1. Otherwise, store the result in |outputTensor|. 1. Let |outputDesc| be |graph|.{{MLGraph/[[outputDescriptors]]}}[|key|]. - 1. If the byte length of |outputTensor| is not equal to the [=byte length=] of |outputDesc|, then throw a "{{DataError}}" {{DOMException}} and stop. - 1. If the [=element type=] of |outputTensor| doesn't match the [=element type=] of |outputValue|, then throw a "{{DataError}}" {{DOMException}} and stop. + 1. If the byte length of |outputTensor| is not equal to the [=byte length=] of |outputDesc|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If the [=element type=] of |outputTensor| doesn't match the [=element type=] of |outputValue|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. 1. Request the underlying implementation of |graph| to set the values of elements in |outputValue| to the values of elements in |outputTensor|. 1. Return {{undefined}}. -+-The following code showcases the synchronous computation with optional outputs in a worker. -### The {{MLNamedArrayBufferViews}} transfer algorithm ### {#mlnamedarraybufferviews-transfer-alg} -To transfer an {{MLNamedArrayBufferViews}} |views|: -1. Let |transferredViews| be a new {{MLNamedArrayBufferViews}}. -1. For each |key| -> |value| of |views|: - 1. Let |transferredBuffer| be the result of [=ArrayBuffer/transfer|transferring=] the [=underlying buffer=] of |value|. - 1. Let |constructor| be the appropriate [=view constructor=] for the type of {{ArrayBufferView}} |value|. - 1. Let |elementsNumber| be the result of the [=buffer byte length|byte length=] of |value| ÷ [=element size=] of |value|. - 1. Let |transferredView| be [=Construct=](|constructor|, |transferredBuffer|, |value|.\[[ByteOffset]], |elementsNumber|). - 1. Set |transferredViews|[|key|] to |transferredView|. -1. Return |transferredViews|. + +-const context = navigator.ml.createContextSync(); - -// Build a graph with two outputs. -const builder = new MLGraphBuilder(context); -const descA = {type: 'float32', dimensions: [3, 4]}; -const a = builder.input('a', descA); -const descB = {type: 'float32', dimensions: [4, 3]}; -const bufferB = new Float32Array(sizeOfShape(descB.dimensions)).fill(0.5); -const b = builder.constant(descB, bufferB); -const descC = {type: 'float32', dimensions: [3, 3]}; -const bufferC = new Float32Array(sizeOfShape(descC.dimensions)).fill(1); -const c = builder.constant(descC, bufferC); -const d = builder.matmul(a, b); -const e = builder.add(d, c); -const graph = builder.buildSync({'d': d, 'e': e}); - -const bufferA = new Float32Array(sizeOfShape(descA.dimensions)).fill(0.5); -const inputs = {'a': bufferA}; - -// Compute d. -const bufferD = new Float32Array(sizeOfShape([3, 3])); -context.computeSync(graph, inputs, {'d': bufferD}); -console.log(`values: ${bufferD}`); - -// Compute e. -const bufferE = new Float32Array(sizeOfShape([3, 3])); -context.computeSync(graph, inputs, {'e': bufferE}); -console.log(`values: ${bufferE}`); -+++ The following code showcases the synchronous computation with optional outputs in a worker. +
++ const context = navigator.ml.createContextSync(); + + // Build a graph with two outputs. + const builder = new MLGraphBuilder(context); + const descA = {type: 'float32', dimensions: [3, 4]}; + const a = builder.input('a', descA); + const descB = {type: 'float32', dimensions: [4, 3]}; + const bufferB = new Float32Array(sizeOfShape(descB.dimensions)).fill(0.5); + const b = builder.constant(descB, bufferB); + const descC = {type: 'float32', dimensions: [3, 3]}; + const bufferC = new Float32Array(sizeOfShape(descC.dimensions)).fill(1); + const c = builder.constant(descC, bufferC); + const d = builder.matmul(a, b); + const e = builder.add(d, c); + const graph = builder.buildSync({'d': d, 'e': e}); + + const bufferA = new Float32Array(sizeOfShape(descA.dimensions)).fill(0.5); + const inputs = {'a': bufferA}; + + // Compute d. + const bufferD = new Float32Array(sizeOfShape([3, 3])); + context.computeSync(graph, inputs, {'d': bufferD}); + console.log(`values: ${bufferD}`); + + // Compute e. + const bufferE = new Float32Array(sizeOfShape([3, 3])); + context.computeSync(graph, inputs, {'e': bufferE}); + console.log(`values: ${bufferE}`); +++### Asynchronous Execution ### {#api-mlcontext-async-execution} -Asynchronously carries out the computational workload of a compiled graph {{MLGraph}} on a separate timeline, either on a worker thread for the CPU execution, or on a GPU timeline for the submission of GPU workload on the command queue. The asynchronous nature of this call avoids blocking the calling thread while the computation for result is ongoing. This method of execution requires an {{MLContext}} created with {{MLContextOptions}}. Otherwise, it throws an "{{OperationError}}" {{DOMException}}. +Asynchronously carries out the computational workload of a compiled graph {{MLGraph}} on a separate timeline, either on a worker thread for the CPU execution, or on a GPU timeline for the submission of GPU workload on the command queue. The asynchronous nature of this call avoids blocking the calling thread while the computation for result is ongoing. This method of execution requires an {{MLContext}} created with {{MLContextOptions}}. Otherwise, it[=exception/throws=] an "{{OperationError}}" {{DOMException}}.+ To transfer an {{MLNamedArrayBufferViews}} |views|: +
++ 1. Let |transferredViews| be a new {{MLNamedArrayBufferViews}}. + 1. [=map/For each=] |key| → |value| of |views|: + 1. Let |transferredBuffer| be the result of [=ArrayBuffer/transfer|transferring=] the [=underlying buffer=] of |value|. + 1. Let |constructor| be the appropriate [=view constructor=] for the type of {{ArrayBufferView}} |value|. + 1. Let |elementsNumber| be the result of the [=BufferSource/byte length=] of |value| ÷ [=element size=] of |value|. + 1. Let |transferredView| be [$Construct$](|constructor|, |transferredBuffer|, |value|.\[[ByteOffset]], |elementsNumber|). + 1. Set |transferredViews|[|key|] to |transferredView|. + 1. Return |transferredViews|. ++In accordance with the [=ArrayBufferView/write|Web IDL warning=], to prevent the calling thread from modifying the input and output resources while the computation is ongoing, this method [=MLNamedArrayBufferViews/transfer|transfers=] the input and output {{MLNamedArrayBufferViews}} to new views that share the same backing memory allocations. The transferred views are returned to the caller via the promise fulfillment with the computation result written into the backing memory of the output views. @@ -977,64 +1306,72 @@ partial interface MLContext { MLGraph graph, MLNamedArrayBufferViews inputs, MLNamedArrayBufferViews outputs); }; - -++ #### Examples #### {#api-mlcontext-async-execution-examples} -**Arguments:** - *graph*: an {{MLGraph}}. The compiled graph to be executed. - *inputs*: an {{MLNamedArrayBufferViews}}. The resources of inputs. Will be [=MLNamedArrayBufferViews/transfer|transferred=] if there are no validation errors. - *outputs*: an {{MLNamedArrayBufferViews}}. The pre-allocated resources of required outputs. Will be [=MLNamedArrayBufferViews/transfer|transferred=] if there are no validation errors. **Returns:** Promise<{{MLComputeResult}}>. +- The {{MLContext/compute(graph, inputs, outputs)}} method steps are: +++ The compute(|graph|, |inputs|, |outputs|) method steps are: +
+1. Let |promise| be [=a new promise=]. 1. Return |promise| and run the following steps [=in parallel=]: - 1. If |graph|.{{MLGraph/[[context]]}}.{{MLContext/[[contextType]]}} is not "[=default-context|default=], [=reject=] |promise| with an "{{OperationError}}" {{DOMException}} and stop. - 1. If invoking the validate graph resources algorithm given |inputs| and |graph|.{{MLGraph/[[inputDescriptors]]}} returns `false`, then [=reject=] |promise| with a "{{DataError}}" {{DOMException}} and stop. - 1. If invoking the validate graph resources algorithm given |outputs| and |graph|.{{MLGraph/[[outputDescriptors]]}} returns `false`, then [=reject=] |promise| with a "{{DataError}}" {{DOMException}} and stop. + 1. If |graph|.{{MLGraph/[[context]]}}.{{MLContext/[[contextType]]}} is not "[=default-context|default=]", [=reject=] |promise| with an "{{OperationError}}" {{DOMException}}. + 1. If validating graph resources given |inputs| and |graph|.{{MLGraph/[[inputDescriptors]]}} returns false, then [=reject=] |promise| with a "{{DataError}}" {{DOMException}}. + 1. If validating graph resources given |outputs| and |graph|.{{MLGraph/[[outputDescriptors]]}} returns false, then [=reject=] |promise| with a "{{DataError}}" {{DOMException}}. 1. Let |transferredInputs| be the result of [=MLNamedArrayBufferViews/transfer|transferring=] {{MLNamedArrayBufferViews}} |inputs|. 1. Let |transferredOutputs| be the result of [=MLNamedArrayBufferViews/transfer|transferring=] {{MLNamedArrayBufferViews}} |outputs|. 1. Invoke execute graph given |graph|, |transferredInputs| and |transferredOutputs|. - 1. If that throws an error, [=reject=] |promise| with the error and stop. + 1. If that [=exception/throws=] an error, [=reject=] |promise| with the error. 1. Otherwise, when execute graph has completed: 1. Let |result| be a new {{MLComputeResult}}. 1. Set |result|.{{MLComputeResult/inputs}} to |transferredInputs|. 1. Set |result|.{{MLComputeResult/outputs}} to |transferredOutputs|. - 1. [=Resolve=] |promise| with |result| and stop. -+ 1. [=Resolve=] |promise| with |result|. +-The following code showcases the asynchronous computation. -### WebGPU Interoperability ### {#api-mlcontext-webgpu-interop} -Create {{MLCommandEncoder}} interface used to record the ML workload onto a WebGPU-compatible {{GPUCommandBuffer}} to allow mixing of ML workload with other GPU workload in an application that leverages WebGPU. This method only succeeds on an {{MLContext}} created with {{GPUDevice}}. Otherwise, it throws an "{{OperationError}}" {{DOMException}}. +Create {{MLCommandEncoder}} interface used to record the ML workload onto a WebGPU-compatible {{GPUCommandBuffer}} to allow mixing of ML workload with other GPU workload in an application that leverages WebGPU. This method only succeeds on an {{MLContext}} created with {{GPUDevice}}. Otherwise, it[=exception/throws=] an "{{OperationError}}" {{DOMException}}. +-const operandType = {type: 'float32', dimensions: [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(0.2); -const A = builder.input('A', operandType); -const B = builder.input('B', operandType); -const C = builder.add(builder.mul(A, constant), B); -// 2. Compile it into an executable. -const graph = await builder.build({'C': C}); -// 3. Bind inputs to the graph and execute for the result. -const bufferA = new Float32Array(4).fill(1.0); -const bufferB = new Float32Array(4).fill(0.8); -const bufferC = new Float32Array(4); -const inputs = {'A': bufferA, 'B': bufferB}; -const outputs = {'C': bufferC}; -const result = await context.compute(graph, inputs, outputs); -// The computed result of [[1, 1], [1, 1]] is in the buffer associated with -// the output operand. -console.log('Output value: ' + result.outputs.C); -// Note: the result.outputs.C buffer is different from the bufferC, but it -// shares the same backing memory allocation. -+++ The following code showcases the asynchronous computation. +
++ const operandType = {type: 'float32', dimensions: [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(0.2); + const A = builder.input('A', operandType); + const B = builder.input('B', operandType); + const C = builder.add(builder.mul(A, constant), B); + // 2. Compile it into an executable. + const graph = await builder.build({'C': C}); + // 3. Bind inputs to the graph and execute for the result. + const bufferA = new Float32Array(4).fill(1.0); + const bufferB = new Float32Array(4).fill(0.8); + const bufferC = new Float32Array(4); + const inputs = {'A': bufferA, 'B': bufferB}; + const outputs = {'C': bufferC}; + const result = await context.compute(graph, inputs, outputs); + // The computed result of [[1, 1], [1, 1]] is in the buffer associated with + // the output operand. + console.log('Output value: ' + result.outputs.C); + // Note: the result.outputs.C buffer is different from the bufferC, but it + // shares the same backing memory allocation. ++{{MLCommandEncoder}} has the following internal slots: - -### Graph Initialization ### {#api-mlcommandencoder-graph-initialization} Record the initialization of the {{MLGraph}}. This is a necessary step for optimal performance during graph execution as it gives the platform an opportunity to prepare and optimize constant input data for the subsequent execution of the graph. This method should only be called once per graph. @@ -1079,16 +1417,23 @@ partial interface MLCommandEncoder { }; -+
+: \[[context]] of type {{MLContext}} :: The context of type {{MLContext}} associated with this {{MLCommandEncoder}}. @@ -1068,7 +1405,8 @@ interface MLCommandEncoder {}; : \[[implementation]] :: The underlying implementation provided by the User Agent. -
++**Arguments:** - *graph*: an {{MLGraph}}. The compiled graph to be initialized with graph constant inputs. **Returns:** {{undefined}}.--Graph initialization stage 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 {{MLGraphBuilder/constant(descriptor, bufferView)|MLGraphBuilder/constant()}} method as constant operands during graph construction time. -++### Dispatch Execution Commands ### {#api-mlcommandencoder-dispatch-commands} Record the {{MLGraph}} execution with the inputs {{MLNamedGPUResources}} and outputs {{MLNamedGPUResources}}. @@ -1099,37 +1444,43 @@ partial interface MLCommandEncoder { }; -+ The initializeGraph(graph) method steps are: +
++++ Graph initialization stage 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 {{MLGraphBuilder/constant(descriptor, bufferView)|MLGraphBuilder/constant(value, type)}} method as constant operands during graph construction time. +++**Arguments:** - *graph*: an {{MLGraph}}. The compiled graph to be executed. - *inputs*: an {{MLNamedGPUResources}}. The resources of inputs. - *outputs*: an {{MLNamedGPUResources}}. The pre-allocated resources of required outputs. **Returns:** {{undefined}}. +- 1. If any of the following requirements are unmet, then throw a "{{DataError}}" {{DOMException}} and stop. -- 1. For each |key| -> |value| of |inputs|: ++ ### Generate GPU Command Buffer ### {#api-mlcommandencoder-generate-gpu-command-buffer} Complete the recording of ML workload and return a WebGPU-compatible {{GPUCommandBuffer}} containing the recorded workload. @@ -1140,13 +1491,27 @@ partial interface MLCommandEncoder { }; -++ The dispatch(|graph|, |inputs|, |outputs|) method steps are: +
++ 1. If any of the following requirements are unmet, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. ++ 1. [=map/For each=] |key| → |value| of |inputs|: + 1. Set the input of |graph|.{{MLGraph/[[implementation]]}} that is associated with |key| to |value|. + 1. [=map/For each=] |key| → |value| of |outputs|: + 1. Set the output of |graph|.{{MLGraph/[[implementation]]}} that is associated with |key| to |value|. + 1. Issue a compute request of |graph|.{{MLGraph/[[implementation]]}}. + 1. If there is an error returned by |graph|.{{MLGraph/[[implementation]]}}, then: + 1. Throw an "{{OperationError}}" {{DOMException}}. + 1. Return {{undefined}}. ++ 1. [=map/For each=] |key| → |value| of |inputs|: 1. |graph|.{{MLGraph/[[inputDescriptors]]}}[|key|] must [=map/exist=]. 1. Let |inputDesc| be |graph|.{{MLGraph/[[inputDescriptors]]}}[|key|]. 1. If |value| is a {{GPUBuffer}}, then: 1. |value|.{{GPUBuffer/size}} must equal to [=byte length=] of |inputDesc|. - 1. For each |key| -> |value| of |outputs|: + 1. [=map/For each=] |key| → |value| of |outputs|: 1. |graph|.{{MLGraph/[[outputDescriptors]]}}[|key|] must [=map/exist=]. 1. Let |outputDesc| be |graph|.{{MLGraph/[[outputDescriptors]]}}[|key|]. 1. If |value| is a {{GPUBuffer}}, then: 1. |value|.{{GPUBuffer/size}} must equal to [=byte length=] of |outputDesc|.- - 1. For each |key| -> |value| of |inputs|: - 1. Set the input of |graph|.{{MLGraph/[[implementation]]}} that is associated with |key| to |value|. - 1. For each |key| -> |value| of |outputs|: - 1. Set the output of |graph|.{{MLGraph/[[implementation]]}} that is associated with |key| to |value|. - 1. Issue a compute request of |graph|.{{MLGraph/[[implementation]]}}. - 1. If there is an error returned by |graph|.{{MLGraph/[[implementation]]}}, then: - 1. Throw an "{{OperationError}}" {{DOMException}} and stop. - 1. Return {{undefined}}. -+**Arguments:** - *descriptor*: an optional {{GPUCommandBufferDescriptor}}. Descriptor of the command buffer. **Returns:** {{GPUCommandBuffer}}.+++ ## The MLGraphBuilder interface ## {#api-mlgraphbuilder} The {{MLGraphBuilder}} interface defines a set of operations as identified by the [[#usecases]] that can be composed into a computational graph. It also represents the intermediate state of a graph building session. @@ -1186,112 +1551,207 @@ interface MLGraphBuilder {+ The finish(|descriptor|) method steps are: +
++ 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Make a request to the underlying platform to complete the recording of the ML workload, given |descriptor|. +++ See the related WebGPU steps. ++ 1. Return a {{GPUCommandBuffer}} containing the recorded workload. +-Both {{MLGraphBuilder}}.{{MLGraphBuilder/build()}} and {{MLGraphBuilder}}.{{MLGraphBuilder/buildSync()}} methods compile the graph builder state up to the specified output operands into a compiled graph according to the type of {{MLContext}} that creates it. Since this operation can be costly in some machine configurations, the calling thread of the {{MLGraphBuilder}}.{{MLGraphBuilder/buildSync()}} method must only be a worker thread to avoid potential disruption of the user experience. When the {{[[contextType]]}} of the {{MLContext}} is set to [=default-context|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. See [[#api-mlcommandencoder-graph-initialization]] for more detail. +Both {{MLGraphBuilder}}.{{MLGraphBuilder/build()}} and {{MLGraphBuilder}}.{{MLGraphBuilder/buildSync()}} methods compile the graph builder state up to the specified output operands into a compiled graph according to the type of {{MLContext}} that creates it. Since this operation can be costly in some machine configurations, the calling thread of the {{MLGraphBuilder}}.{{MLGraphBuilder/buildSync()}} method must only be a worker thread to avoid potential disruption of the user experience. When the {{[[contextType]]}} of the {{MLContext}} is set to "[=default-context|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. See [[#api-mlcommandencoder-graph-initialization]] for more detail.+{{MLBufferResourceView}} has the following members: ++ : resource + :: + A {{GPUBuffer}} object. Specifies the GPU buffer source. + + : offset + :: + Specifies an {{unsigned long long}} offset in the buffer source. + + : size + :: + Specifies the {{unsigned long long}} size of the buffer view. +
+ +{{MLGraphBuilder}} has the following internal slots: -### The {{MLGraphBuilder}} constructor ### {#api-mlgraphbuilder-constructor} -The [=new=] {{MLGraphBuilder}} constructor steps are: -1. If [=this=]'s [=relevant global object=]'s [=associated Document=] is not [=allowed to use=] the [=webnn-feature|webnn=] feature, throw a "{{SecurityError}}" {{DOMException}} and abort these steps. -1. Let |context| be the first argument. -1. If the validate MLContext steps given |context| return `false`, throw a "{{TypeError}}" and abort these steps. -1. Set {{MLGraphBuilder/[[context]]}} to |context|. + ++
+: \[[context]] of type {{MLContext}} :: The context of type {{MLContext}} associated with this {{MLGraphBuilder}}. -
++### The {{MLGraphBuilder/input()}} method ### {#api-mlgraphbuilder-input} Create a named {{MLOperand}} based on a descriptor, that can be used as an input. -+ 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|webnn=] feature, then [=exception/throw=] a "{{SecurityError}}" {{DOMException}}. + 1. If validating MLContext given |context| returns false, then [=exception/throw=] a "{{TypeError}}". + 1. Set {{MLGraphBuilder/[[context]]}} to |context|. +++ +**Arguments:** - *name*: a [=string=] name of the input. - *descriptor*: an {{MLOperandDescriptor}} object. **Returns:**: an {{MLOperand}} object.-- The {{MLGraphBuilder/input(name, descriptor)}} steps are: + +++ +### The build() method ### {#api-mlgraphbuilder-build} +Build a composed graph up to a given output operand into a computational graph, asynchronously or synchronously. + +#### The {{MLGraphBuilder/build(outputs)}} method #### {#api-mlgraphbuilder-build-outputs} + ++ The input(|name|, |descriptor|) method steps are: +
++++ The permissions and context validity have been checked by [[#api-mlgraphbuilder-constructor]] steps. ++ 1. If |name| is empty, then [=exception/throw=] a {{TypeError}}. + 1. [=Assert=]: the type of |descriptor| is {{MLOperandDescriptor}}. + 1. [=Assert=]: If |descriptor|.{{MLOperandDescriptor/dimensions}} does not [=map/exist=], then |descriptor| defines a scalar input. + 1. If |descriptor|.{{MLOperandDescriptor/dimensions}} [=map/exists=]: + 1. If the [=check dimensions=] steps given |descriptor|.{{MLOperandDescriptor/type}} and |descriptor|.{{MLOperandDescriptor/dimensions}} return false, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If the [=byte length=] of |descriptor| is not supported by the underlying platform, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |operand| be the result of creating an MLOperand given [=this=] and |descriptor|. + 1. Set |operand|.{{MLOperand/[[name]]}} to |name|. + 1. Make a request to the underlying platform to: + 1. Create an [=implementation-defined=] platform input operand |operandImpl| given |descriptor|. + 1. Store a reference of |operandImpl| in |operand|.{{MLOperand/[[operand]]}}. + 1. Register |operand| as an input. + 1. Return |operand|. +++ +#### The {{MLGraphBuilder/buildSync(outputs)}} method #### {#api-mlgraphbuilder-buildsync-outputs} + ++ The build(|outputs|) method steps are: +
++The permissions and context validity have been checked by [[#api-mlgraphbuilder-constructor]] steps.- 1. Let |name| be the first argument. - 1. If |name| is `undefined` or an empty [=string=], then throw a "{{TypeError}}" {{DOMException}} and stop. - 1. Let |descriptor| be the second argument. - 1. If |descriptor| is not an an object that [=implements=] {{MLOperandDescriptor}}, then throw a "{{TypeError}}" {{DOMException}} and stop. - 1. [=Assert=]: If |descriptor|.{{MLOperandDescriptor/dimensions}} does not [=map/exist=], then |descriptor| defines a scalar input. - 1. If |descriptor|.{{MLOperandDescriptor/dimensions}} [=map/exists=]: - 1. If the [=check dimensions=] steps given |descriptor|.{{MLOperandDescriptor/type}} and |descriptor|.{{MLOperandDescriptor/dimensions}} return `false`, throw a "{{DataError}}" {{DOMException}} and stop. - 1. If the [=byte length=] of |descriptor| is not supported by the underlying platform, then throw a "{{DataError}}" {{DOMException}} and stop. - 1. Let |operand| be the result of invoking the create MLOperand steps with [=this=] and |descriptor|. - 1. If that throws, re-throw the exception and stop. - 1. Set |operand|.{{MLOperand/[[name]]}} to |name|. - 1. Make a request to the underlying platform to register |operand| as an input and store a reference to the corresponding [=implementation-defined=] platform object in |operand|.{{MLOperand/[[operand]]}}. - 1. If that fails, throw an "{{OperationError}}" {{DOMException}} and abort these steps. + 1. Let |promise| be [=a new promise=]. + 1. Return |promise| and run the following steps [=in parallel=]. + 1. Return the result of invoking {{MLGraphBuilder/buildSync(outputs)}} given |outputs|. + 1. If that [=exception/throws=], re-[=exception/throw=] the error. ++### The constant() method ### {#api-mlgraphbuilder-constant-method} Create a constant {{MLOperand}} that can be used in {{MLGraphBuilder}} methods. #### The {{MLGraphBuilder/constant(descriptor, bufferView)}} method #### {#api-mlgraphbuilder-constant} -+ The buildSync(|outputs|) method steps are: +
++++ The permissions and context validity have been checked by [[#api-mlgraphbuilder-constructor]] steps. ++ 1. [=Assert=]: the type of |outputs| is {{MLNamedOperands}}. + 1. If |outputs| is empty, then [=exception/throw=] a {{TypeError}}. + 1. [=map/For each=] |element| in |outputs|: + 1. [=Assert=]: the type of |element|.key is [=string=]. + 1. If |element|.key is empty, then [=exception/throw=] a {{TypeError}}. + 1. [=Assert=]: the type of |element|.value is {{MLOperand}}. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |graph| be a new {{MLGraph}}: + 1. Set |graph|.{{MLGraph/[[context]]}} to [=this=].{{MLGraphBuilder/[[context]]}}. + 1. Make a request to the underlying platform to: + 1. Connect |graph| to a new [=implementation-defined=] graph implementation |graphImpl| given |graph|. + 1. Store a reference to |graphImpl| in |graph|.{{MLGraph/[[implementation]]}}. + 1. Make a request to the underlying platform to initialize the graph: + 1. [=map/For each=] |operand| in |outputs|: + 1. If validating MLOperand given |operand| and [=this=] returns false, then [=exception/throw=] a {{TypeError}}. + 1. If |operand| was created as an input by the underlying platform: + 1. If |operand|.{{MLOperand/[[name]]}}] is not unique for |graphImpl|, then [=exception/throw=] a {{TypeError}}. + 1. Add |operand|.{{MLOperand/[[descriptor]]}} to |graph|.{{MLGraph/[[inputDescriptors]]}}[|operand|.{{MLOperand/[[name]]}}]. + 1. If |operand| was created as a constant by the underlying platform: + 1. Implementations MAY preprocess and optimize the tensor data of |operand| for the underlying platform. + 1. Register |operand|.{{MLOperand/[[operand]]}} in |graphImpl| as graph output. + 1. Register |operand|.{{MLOperand/[[operator]]}} to |graphImpl|. + 1. Return |graph|. ++**Arguments:** - *descriptor*: an {{MLOperandDescriptor}} object - *bufferView*: an {{MLBufferView}} **Returns:**: an {{MLOperand}} object.--The {{MLGraphBuilder/constant(descriptor, bufferView)}} steps are: ++ #### The {{MLGraphBuilder/constant(value, type)}} method #### {#api-mlgraphbuilder-constant-value-type} -++ The constant(|descriptor|, |bufferView|) method steps are: +
++The permissions and context validity have been checked by [[#api-mlgraphbuilder-constructor]] steps.- 1. Let |descriptor| be the first argument. - 1. If |descriptor| is not an an object that [=implements=] {{MLOperandDescriptor}}, then throw a "{{TypeError}}" {{DOMException}} and stop. - 1. If the [=byte length=] of |descriptor| is not supported by the underlying platform, then throw a "{{DataError}}" {{DOMException}} and stop. - 1. If the [=check dimensions=] steps given |descriptor|.{{MLOperandDescriptor/type}} and |descriptor|.{{MLOperandDescriptor/dimensions}} return `false`, throw a "{{DataError}}" {{DOMException}} and stop. - 1. Let |bufferView| be the second argument. - 1. If invoking validate buffer with descriptor given |bufferView| and |descriptor| return `false`, then throw a "{{TypeError}}" {{DOMException}} and stop. - 1. Let |operand| be the result of invoking the create MLOperand steps with [=this=] and |descriptor|. - 1. If that throws, re-throw the exception and stop. - 1. Let |bytes| be the result of invoking [[=get a copy of the bytes held by the buffer source=]] given |bufferView|. - 1. Make a request to the underlying platform to register |operand| as a tensor constant with |bytes| as value and store a reference to the corresponding [=implementation-defined=] object to |operand|.{{MLOperand/[[operand]]}}. - 1. If that fails, throw an "{{OperationError}}" {{DOMException}} and stop. + 1. [=Assert=]: the type of |descriptor| is {{MLOperandDescriptor}}. + 1. If the [=byte length=] of |descriptor| is not supported by the underlying platform, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If the [=check dimensions=] steps given |descriptor|.{{MLOperandDescriptor/type}} and |descriptor|.{{MLOperandDescriptor/dimensions}} return false, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If validating buffer with descriptor given |bufferView| and |descriptor| returns false, then [=exception/throw=] a {{TypeError}}. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |operand| be the result of creating an MLOperand given [=this=] and |descriptor|. + 1. Let |bytes| be the result of invoking the [=get a copy of the bytes held by the buffer source=] steps given |bufferView|. + 1. Make a request to the underlying platform to: + 1. Create an [=implementation-defined=] platform operand |constantImpl| to represent a constant, given |descriptor|. + 1. Store a reference of |constantImpl| in |operand|.{{MLOperand/[[operand]]}}. + 1. Register |operand| as a tensor constant with |bytes| as value. 1. Return |operand|. -+**Arguments:** - *value*: a number - *type*: an optional {{MLOperandType}}, by default *"float32"*. **Returns:**: an {{MLOperand}} object.--The {{MLGraphBuilder/constant(value, type)}} steps are: ++ ### The batchNormalization() method ### {#api-mlgraphbuilder-batchnorm} Normalize the tensor values of input features across the batch dimension using [[Batch-Normalization]]. For each input feature, the mean and variance values of that feature supplied in this calculation as parameters are previously computed across the batch dimension of the input during the model training phase of this operation. + -++ The constant(|value|, |type|) method steps are: +
++The permissions and context validity have been checked by [[#api-mlgraphbuilder-constructor]] steps.- 1. If |value| is not a [=number=], then then throw a "{{TypeError}}" {{DOMException}} and stop. - 1. If |type| is `undefined`, let |type| be `"float32"`. - 1. Otherwise, if |type| is not one of {{MLOperandType}}, then throw a "{{TypeError}}" {{DOMException}} and stop. 1. Let |descriptor| be a new {{MLOperandDescriptor}}. 1. Set |descriptor|.{{MLOperandDescriptor/type}} to |type|. 1. Set |descriptor|.{{MLOperandDescriptor/dimensions}} to `undefined`.In the case of a scalar constant, |descriptor|.{{MLOperandDescriptor/dimensions}} is ignored.- 1. Let |operand| be the result of invoking the create MLOperand steps with [=this=] and |descriptor|. - 1. If that throws, re-throw the exception and stop. - 1. Make a request to the underlying platform to register |operand| as a scalar constant with |value| as value and store a reference of the [=implementation-defined=] platform object for the corresponding (scalar or tensor constant) operand to |operand|.{{MLOperand/[[operand]]}}. - 1. If that throws, re-throw the error and stop. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |operand| be the result of creating an MLOperand given [=this=] and |descriptor|. + 1. Make a request to the underlying platform to: + 1. Create an [=implementation-defined=] platform operand |constantImpl| to represent a constant, given |descriptor|. + 1. Store a reference of |constantImpl| in |operand|.{{MLOperand/[[operand]]}}. + 1. Register |operand| as a scalar constant with |value| as value. 1. Return |operand|. -+ +{{MLBatchNormalizationOptions}} has the following members: ++ : scale + :: + An {{MLOperand}}. Specifies the 1-D tensor of the scaling values whose is equal to the size of the input dimension denoted by {{MLBatchNormalizationOptions/axis}}. + + : bias + :: + An {{MLOperand}}. Specifies the 1-D tensor of the bias values whose [=list/size=] is equal to the size of the input dimension denoted by {{MLBatchNormalizationOptions/axis}}. + + : axis + :: + A {{long}} scalar. Specifies 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 + :: + A {{float}} scalar. Specifies A small value to prevent computational error due to divide-by-zero. + + : activation + :: + An {{MLActivation}} object. Specifies the optional activation function that immediately follows the normalization operation. +
+ +**Arguments:** - *input*: an {{MLOperand}}. The input N-D tensor. - - *mean*: an {{MLOperand}}. The 1-D tensor of the mean values of the input features across the batch whose length is equal to the size of the input dimension denoted by *options.axis*. - - *variance*: an {{MLOperand}}. The 1-D tensor of the variance values of the input features across the batch whose length is equal to the size of the input dimension denoted by *options.axis*. - - *options*: an optional {{MLBatchNormalizationOptions}}. The optional parameters of the operation. - - *scale*: an {{MLOperand}}. The 1-D tensor of the scaling values whose length is equal to the size of the input dimension denoted by *options.axis*. - - *bias*: an {{MLOperand}}. The 1-D tensor of the bias values whose length is equal to the size of the input dimension denoted by *options.axis*. - - *axis*: an {{unsigned long}} scalar. 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 input tensor. When it's not specified, the default value is 1. - - *epsilon*: a {{float}} scalar. A small value to prevent computational error due to divide-by-zero. The default value is 0.00001 when not specified. - - *activation*: an {{MLActivation}}. The optional activation function that immediately follows the normalization operation. + - *mean*: an {{MLOperand}}. Specifies the 1-D tensor of the mean values of the input features across the batch. Its [=list/size=] is equal to the size of the input dimension denoted by {{MLBatchNormalizationOptions/axis}}. + - *variance*: an {{MLOperand}}. The 1-D tensor of the variance values of the input features across the batch whose [=list/size=] is equal to the size of the input dimension denoted by {{MLBatchNormalizationOptions/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 the input tensor. + **Returns:** an {{MLOperand}}. The batch-normalized N-D tensor of the same shape as *input*. +- When *input* is a 4-D tensor of the *"nchw"* or *"nhwc"* layout, *options.axis* should be set to 1 or 3 respectively. The axis value designates the feature or channel count dimension of the input tensor. ++-+ The batchNormalization(|input|, |mean|, |variance|, |options|) method steps are: +
++ 1. [=Assert=]: the type of |input|, |mean| and |variance| is {{MLOperand}}. + 1. If |options|.axis is not in [=the range=] 0 to the [=rank=] of |input|, exclusive, then [=exception/throw=] a {{TypeError}}. + 1. If the [=list/size=] of |mean|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}} is not 1, then [=exception/throw=] a {{TypeError}}. + 1. If |mean|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[0] is not equal to |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[|options|.{{MLBatchNormalizationOptions/axis}}], then [=exception/throw=] a {{TypeError}}. + 1. If the [=list/size=] of |variance|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}} is not 1, then [=exception/throw=] a {{TypeError}}. + 1. If |variance|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[0] is not equal to |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[|options|.{{MLBatchNormalizationOptions/axis}}], then [=exception/throw=] a {{TypeError}}. + 1. If |options|.{{MLBatchNormalizationOptions/scale}} [=map/exists=]: + 1. If its [=list/size=] is not 1, then [=exception/throw=] a {{TypeError}}. + 1. If |options|.{{MLBatchNormalizationOptions/scale}}.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[0] is not equal to |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[|options|.{{MLBatchNormalizationOptions/axis}}], then [=exception/throw=] a {{TypeError}}. + 1. If |options|.{{MLBatchNormalizationOptions/bias}} [=map/exists=]: + 1. If its [=list/size=] is not 1, then [=exception/throw=] a {{TypeError}}. + 1. If |options|.{{MLBatchNormalizationOptions/bias}}.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[0] is not equal to |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[|options|.{{MLBatchNormalizationOptions/axis}}], then [=exception/throw=] a {{TypeError}}. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of creating an MLOperand given [=this=] and |input|.{{MLOperand/[[descriptor]]}}, that may use the same underlying data as |input|. + 1. Make a request to the underlying platform to initialize the batch normalization: + 1. Create an [=implementation-defined=] platform operator |batchNormImpl| for this method, given |input|, |mean|, |variance| and |options|. + 1. If |options|.activation [=map/exists=],register it as activation to |batchNormImpl|. + 1. Connect |output| as output to |batchNormImpl|. + 1. Return |output|. +++### The clamp() method ### {#api-mlgraphbuilder-clamp} @@ -1350,46 +1858,104 @@ dictionary MLClampOptions { }; partial interface MLGraphBuilder { - MLOperand clamp(MLOperand x, optional MLClampOptions options = {}); + MLOperand clamp(MLOperand operand, optional MLClampOptions options = {}); MLActivation clamp(optional MLClampOptions options = {}); }; -+++The behavior of this operation when the input tensor is 4-D of the *"nchw"* layout and the activation is of operator type *relu* can be generically emulated from the usage of other operations as follow. However, user agents typically have a more efficient implementation for it, therefore its usage is encouraged from the performance standpoint. +
const shape = [1,null,1,1]; return builder.relu( @@ -1338,7 +1846,7 @@ partial interface MLGraphBuilder { )), builder.reshape(options.bias, shape)));-- **Arguments:** - - *x*: an {{MLOperand}}. The input tensor. - - *options*: an optional {{MLClampOptions}}. The optional parameters of the operation. - - *minValue*: a {{float}} scalar. Specifies the minimum value of the range. When it is not specified, the clamping is not performed on the lower limit of the range. - - *maxValue*: a {{float}} scalar. Specifies the maximum value of the range. When it is not specified, the clamping is not performed on the upper limit of the range. - - **Returns:** - - an {{MLOperand}}. The output tensor of the same shape as *x*. - - an {{MLActivation}}. The activation function representing the clamp operation. -++ +++ + ++The behavior of this operation can be generically emulated from the usage of other operations as follow. However, user agents typically have a more efficient implementation for it, therefore its usage is encouraged from the performance standpoint. -
++if (options.minValue === undefined) { if (options.maxValue === undefined) { - return x; + return operand; } else { - return builder.min(x, builder.constant(options.maxValue)); + return builder.min(operand, builder.constant(options.maxValue)); } } else { if (options.maxValue === undefined) { - return builder.max(x, builder.constant(options.minValue)); + return builder.max(operand, builder.constant(options.minValue)); } else { return builder.min( - builder.max(x, builder.constant(options.minValue)), + builder.max(operand, builder.constant(options.minValue)), builder.constant(options.maxValue)); } } --++ +#### The {{MLGraphBuilder/clamp(operand, options)}} method #### {#api-mlgraphbuilder-clamp-operand-options} ++ To check clamp options given |options|, run the following steps: +
++ 1. If |options|.{{MLClampOptions/minValue}} is greater than |options|.{{MLClampOptions/maxValue}}, then return false. + 1. Return true. +++ **Arguments:** + - *operand*: an {{MLOperand}}. The input tensor. + - *options*: an optional {{MLClampOptions}}. The optional parameters of the operation. + - *minValue*: a {{float}} scalar. Specifies the minimum value of the range. When it is not specified, the clamping is not performed on the lower limit of the range. + - *maxValue*: a {{float}} scalar. Specifies the maximum value of the range. When it is not specified, the clamping is not performed on the upper limit of the range. + **Returns:** + - an {{MLOperand}}. The output tensor of the same shape as *operand*. ++ ++ ++ +#### The {{MLGraphBuilder/clamp(options)}} method #### {#api-mlgraphbuilder-clamp-options} ++ The clamp(|operand|, |options|) method steps are: +
++ 1. [=Assert=]: the type of |operand| is {{MLOperand}}. + 1. If running the check clamp options steps given |options| returns false, then [=exception/throw=] a {{TypeError}}. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of copying an MLOperand given |operand|. + 1. Make a request to the underlying platform to: + 1. Create an [=implementation-defined=] platform operator |clampImpl| for this method, given |options|.{{MLClampOptions/minValue}} and |options|.{{MLClampOptions/maxValue}}. + 1. Store a reference of |clampImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent clamp output, given |output| and |clampImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |operand|.{{MLOperand/[[operand]]}} as input to |clampImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |clampImpl|. + 1. Return |output|. +++ **Arguments:** + - *options*: an optional {{MLClampOptions}}. The optional parameters of the operation. + - *minValue*: a {{float}} scalar. Specifies the minimum value of the range. When it is not specified, the clamping is not performed on the lower limit of the range. + - *maxValue*: a {{float}} scalar. Specifies the maximum value of the range. When it is not specified, the clamping is not performed on the upper limit of the range. + **Returns:** + - an {{MLActivation}}. The operator representing the clamp operation.++ ++ ### The concat() method ### {#api-mlgraphbuilder-concat} Concatenates the input tensors along a given axis. -+ The clamp(|options|) method steps are: +
++ 1. If running the check clamp options steps given |options| returns false, then [=exception/throw=] a {{TypeError}}. + 1. Let |op| be the result of creating an MLActivation given [=this=], `"clamp"` and |options|. + 1. If that [=exception/throws=] an error, re-[=exception/throw=] the error. + 1. Return |op|. +++**Arguments:** - *inputs*: a sequence of {{MLOperand}}. All input tensors must have the same shape, except for the size of the dimension to concatenate on. - - *axis*: an {{unsigned long}} scalar. The axis that the inputs concatenate along. Its value must be in the range [0, N-1] where N is the rank of input tensors. + - *axis*: an {{unsigned long}} scalar. The axis that the inputs concatenate along. Its value must be in the range [0, N-1] where N is the [=rank=] of the input tensors. **Returns:** an {{MLOperand}}. The concatenated tensor of all the inputs along the *axis*. The output tensor has the same shape except on the dimension @@ -1409,10 +1975,50 @@ partial interface MLGraphBuilder { computed as the sum of all the input sizes of the same dimension.-### The conv2d() method ### {#api-mlgraphbuilder-conv2d} -Compute a 2-D convolution given 4-D input and filter tensors - -- **Arguments:** - - *input*: an {{MLOperand}}. The input 4-D tensor. The logical shape - is interpreted according to the value of *options.inputLayout*. - - *filter*: an {{MLOperand}}. The filter 4-D tensor. The logical shape is - interpreted according to the value of *options.filterLayout* and *options.groups*. - - *options*: an optional {{MLConv2dOptions}}. The optional parameters of the operation. - - *padding*: a sequence of {{unsigned long}} of length 4. The additional rows and columns added to the beginning and ending of each spatial dimension of *input*, [beginning_height, ending_height, beginning_width, ending_width]. If not present, the values are assumed to be [0,0,0,0]. - - *strides*: a sequence of {{unsigned long}} of length 2. The stride of the sliding window for each spatial dimension of *input*, [stride_height, stride_width]. If not present, the values are assumed to be [1,1]. - - *dilations*: a sequence of {{unsigned long}} of length 2. The dilation factor for each spatial dimension of *input*, [dilation_height, dilation_width]. If not present, the values are assumed to be [1,1]. - - *autoPad*: an {{MLAutoPad}}. The automatic input padding options. By default, this argument is set to *"explicit"*, which means that the values in the *options.padding* array should be used for input padding. When the option is set other than *"explicit"*, the values in the *options.padding* array are ignored. With the *"same-upper"* option, the padding values are automatically computed such that the additional ending padding of the spatial input dimensions would allow all of the input values in the corresponding dimension to be filtered. The *"same-lower"* option is similar but padding is applied to the beginning padding of the spatial input dimensions instead of the ending one. - - *groups*: an {{unsigned long}} scalar. The number of groups that input channels and output channels are divided into, default to 1. - - *inputLayout*: an {{MLInputOperandLayout}}. The default value is *"nchw"*. This option specifies the layout format of the input and output tensor as follow: - "nchw": - - input tensor: [batches, input_channels, height, width] - - output tensor: [batches, output_channels, height, width] +{{MLConv2dOptions}} has the following members: ++ : padding + :: + A sequence of {{unsigned long}} of length 4: [beginningHeight, endingHeight, beginningWidth, endingWidth]. + Specifies the additional rows and columns added to the beginning and ending of each spatial dimension of the convolution input. + The default value is [0, 0, 0, 0]. - "nhwc": - - input tensor: [batches, height, width, input_channels] - - output tensor: [batches, height, width, output_channels] + : strides + :: + A sequence of {{unsigned long}} of length 2: [strideHeight, strideWidth]. + Specifies the stride of the sliding window for each spatial dimension of the convolution input. + The default value is [1, 1]. - - *filterLayout*: an {{MLConv2dFilterOperandLayout}}. The default value is *"oihw"*. This option specifies the layout format of the filter tensor as follow: + : dilations + :: + A sequence of {{unsigned long}} of length 2: [dilationHeight, dilationWidth]. Specifies the dilation factor for each spatial dimension applied on the convolution filter (kernel). + The default value is [1, 1]. - "oihw": - - [output_channels, input_channels/groups, height, width] + : autoPad + :: + An {{MLAutoPad}} [=string=]. + Specifies the automatic input padding options. + The default value is *"explicit"*, which means that the values in the {{MLConv2dOptions/padding}} array should be used for input padding. + When the option is set other than *"explicit"*, the values in the {{MLConv2dOptions/padding}} array are ignored. - "hwio": - - [height, width, input_channels/groups, output_channels] + With the *"same-upper"* option, the padding values are automatically computed such that the additional ending padding of the spatial input dimensions would allow all of the input values in the corresponding dimension to be filtered. - "ohwi": - - [output_channels, height, width, input_channels/groups] + The *"same-lower"* option is similar but padding is applied to the beginning padding of the spatial input dimensions instead of the ending one. - "ihwo": - - [input_channels/groups, height, width, output_channels] + : groups + :: + An {{unsigned long}} scalar. + Specifies the number of groups that input channels and output channels are divided into. + The default value is 1. - - *bias*: an {{MLOperand}}. The additional 1-D tensor with the shape of [output_channels] whose values are to be added to the convolution result. - - *activation*: an {{MLActivation}}. The optional activation function that immediately follows the convolution operation. + : inputLayout + :: + An {{MLInputOperandLayout}} [=string=]. + Specifies the layout format of the input and output tensor as follows: + - **"nchw"** + - input tensor: *[batches, inputChannels, height, width]* + - output tensor: *[batches, outputChannels, height, width]* + - **"nhwc"**: + - input tensor: *[batches, height, width, inputChannels]* + - output tensor: *[batches, height, width, outputChannels]* + The default value is *"nchw"*. + + : filterLayout + :: + An {{MLConv2dFilterOperandLayout}} [=string=]. + Specifies the layout format of the filter tensor as follow: + - **"oihw"**: *[outputChannels, inputChannels/groups, height, width]* + - **"hwio"**: *[height, width, inputChannels/groups, outputChannels]* + - **"ohwi"**: *[outputChannels, height, width, inputChannels/groups]* + - **"ihwo"**: *[inputChannels/groups, height, width, outputChannels]* + The default value is *"oihw"*. + + : bias + :: + An {{MLOperand}} object. + Specifies the additional 1-D tensor with the shape of *[outputChannels]* whose values are to be added to the convolution result. - **Returns:** an {{MLOperand}}. The output 4-D tensor that contains the convolution result. The output shape is interpreted according to the *options.inputLayout* value. More specifically, the spatial dimensions or the sizes of the last two dimensions of the output tensor for the *nchw* input layout can be calculated as follow: + : activation + :: + An {{MLActivation}} object. + Specifies the optional activation function that immediately follows the convolution operation. +
- *output size = 1 + (input size - (filter size - 1) ** *dilation - 1 + beginning padding + ending padding) / stride* ++ **Arguments:** + - *input*: an {{MLOperand}}. The input 4-D tensor. The logical shape + is interpreted according to the value of *options*.{{MLConv2dOptions/inputLayout}}. + - *filter*: an {{MLOperand}}. The filter 4-D tensor. The logical shape is + interpreted according to the value of *options*.{{MLConv2dOptions/filterLayout}} and *options*.{{MLConv2dOptions/groups}}. + - *options*: an {{MLConv2dOptions}}. The optional parameters of the operation. -+- A *depthwise* conv2d operation is a variant of grouped convolution, used in models like the MobileNet, where the *options.groups* = input_channels = output_channels and the shape of filter tensor is [options.groups, 1, height, width] + **Returns:** an {{MLOperand}}. The output 4-D tensor that contains the convolution result. The output shape is interpreted according to the *options*.{{MLConv2dOptions/inputLayout}} value. More specifically, the spatial dimensions or the sizes of the last two dimensions of the output tensor for the *nchw* input layout can be calculated as follow: + + *outputSize = 1 + (inputSize - (filterSize - 1) ** *dilation - 1 + beginningPadding + endingPadding) / stride* ++ ++ A *depthwise* conv2d operation is a variant of grouped convolution, used in models like the MobileNet, where the *options.groups* = inputChannels = outputChannels and the shape of filter tensor is [options.groups, 1, height, width] for *"oihw"* layout, [height, width, 1, options.groups] for *"hwio"* layout, [options.groups, height, width, 1] for *"ohwi"* layout and [1, height, width, options.groups] for *"ihwo"* layout. -+ ++ ### The convTranspose2d() method ### {#api-mlgraphbuilder-convtranspose2d} Compute a 2-D transposed convolution given 4-D input and filter tensors -+ The conv2d(|input|, |filter|, |options|) method steps are: +
++ 1. [=Assert=]: the type of |input| and |filter| is {{MLOperand}}. + 1. Let |inputSize| be the [=list/size=] of |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}. + 1. Let |filterSize| be the [=list/size=] of |filter|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}. + 1. If |inputSize| is not 4, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |filterSize| is not 4, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/type}} is not the same as |filter|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/type}}, then [=exception/throw=] a {{TypeError}}. + 1. If |options|.{{MLConv2dOptions/padding}} does not [=map/exist=], set it to `« 0, 0, 0, 0 »`. + 1. Else if the [=list/size=] of |options|.{{MLConv2dOptions/padding}} is not 4, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLConv2dOptions/strides}} does not [=map/exist=], set it to `« 1, 1 »`. + 1. Else if the [=list/size=] of |options|.{{MLConv2dOptions/strides}} is not 2, then [=exception/throw=] a {{TypeError}}. + 1. If any element in |options|.{{MLConv2dOptions/strides}} is equal to 0, then [=exception/throw=] a {{TypeError}}. + 1. If |options|.{{MLConv2dOptions/dilations}} does not [=map/exist=], set it to `« 1, 1 »`. + 1. Else if the [=list/size=] of |options|.{{MLConv2dOptions/dilations}} is not 2, then [=exception/throw=] a {{TypeError}}. + 1. If |options|.{{MLConv2dOptions/autoPad}} does not [=map/exist=], set it to `"explicit"`. + 1. If |options|.{{MLConv2dOptions/groups}} is 0, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |inputSize| / |options|.{{MLConv2dOptions/groups}} is not equal to |filterSize|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. Else if |inputSize| % |options|.{{MLConv2dOptions/groups}} is not 0, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLConv2dOptions/bias}} [=map/exists=]: + 1. [=Assert=]: the type of |options|.{{MLConv2dOptions/bias}} is {{MLOperand}}. + 1. If the [=list/size=] of |options|.{{MLConv2dOptions/bias}}.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}} is not 1, then [=exception/throw=] a {{TypeError}}. + 1. If |options|.{{MLConv2dOptions/bias}}.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/type}} is not the same as |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/type}}, then [=exception/throw=] a {{TypeError}}. + 1. If |options|.{{MLConv2dOptions/activation}} [=map/exists=]: + 1. [=Assert=]: the type of |options|.{{MLConv2dOptions/activation}} is {{MLActivation}}. + 1. Let |outputShape| be the result of invoking the underlying implementation for calculating output dimensions, given |options|. + 1. If |outputShape| is not the same as the shape of |options|.{{MLConv2dOptions/bias}}.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. Let |desc| a new {{MLOperandDescriptor}}. + 1. Set |desc|.{{MLOperandDescriptor/type}} to |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/type}}. + 1. Set |desc|.{{MLOperandDescriptor/dimensions}} to |outputShape|. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of creating an MLOperand given [=this=] and |desc|. + 1. Make a request to the underlying platform to: + 1. Create an [=implementation-defined=] platform operator |conv2dImpl| for this method, given |options| and |filter|. + 1. If |options|.{{MLConv2dOptions/activation}} [=map/exists=],register it as activation to |conv2dImpl|. + 1. Store a reference of |conv2dImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |conv2dImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |conv2dImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |conv2dImpl|. + 1. Return |output|. ++- **Arguments:** - - *input*: an {{MLOperand}}. The input 4-D tensor. The logical shape - is interpreted according to the value of *options.inputLayout*. - - *filter*: an {{MLOperand}}. The filter 4-D tensor. The logical shape is - interpreted according to the value of *options.filterLayout* and *options.groups*. - - *options*: an optional {{MLConvTranspose2dOptions}}. The optional parameters of the operation. - - *padding*: a sequence of {{unsigned long}} of length 4. The additional rows and columns added to the beginning and ending of each spatial dimension of *input*, [beginning_height, ending_height, beginning_width, ending_width]. If not present, the values are assumed to be [0,0,0,0]. - - *strides*: a sequence of {{unsigned long}} of length 2. The stride of the sliding window for each spatial dimension of *input*, [stride_height, stride_width]. If not present, the values are assumed to be [1,1]. - - *dilations*: a sequence of {{unsigned long}} of length 2. The dilation factor for each spatial dimension of *input*, [dilation_height, dilation_width]. If not present, the values are assumed to be [1,1]. - - *outputPadding*: a sequence of {{unsigned long}} of length 2. The padding values applied to each spatial dimension of the output tensor. This explicit padding values are needed to disambiguate the output tensor shape for transposed convolution when the value of the *options.strides* is greater than 1. Note that these values are only used to disambiguate output shape when needed; it does not necessarily cause any padding value to be written to the output tensor. If not specified, the values are assumed to be [0,0]. - - *outputSizes*: a sequence of {{unsigned long}} of length 2. The sizes of the last two dimensions of the output tensor. When the output sizes are explicitly specified, the output padding values in *options.outputPadding* are ignored. If not specified, the output sizes are automatically computed. - - *autoPad*: an {{MLAutoPad}}. The automatic input padding options. By default, this argument is set to *"explicit"*, which means that the values in the *options.padding* array should be used for input padding. When the option is set other than *"explicit"*, the values in the *options.padding* array are ignored. With the *"same-upper"* option, the padding values are automatically computed such that the additional ending padding of the spatial input dimensions would allow all of the input values in the corresponding dimension to be filtered. The *"same-lower"* option is similar but padding is applied to the beginning padding of the spatial input dimensions instead of the ending one. - - *groups*: an {{unsigned long}} scalar. The number of groups that input channels and output channels are divided into, default to 1. - - *inputLayout*: an {{MLInputOperandLayout}}. The default value is *"nchw"*. This option specifies the layout format of the input and output tensor as follow: - "nchw": - - input tensor: [batches, input_channels, height, width] - - output tensor: [batches, output_channels, height, width] +{{MLConvTranspose2dOptions}} has the following members: ++ : padding + :: + A sequence of {{unsigned long}} of length 4: [beginningHeight, endingHeight, beginningWidth, endingWidth]. + Specifies the additional rows and columns added to the beginning and ending of each spatial dimension of the convolution input. + The default value is [0, 0, 0, 0]. + + : strides + :: + A sequence of {{unsigned long}} of length 2: [strideHeight, strideWidth]. + Specifies the stride of the sliding window for each spatial dimension of the convolution input. + The default value is [1, 1]. + + : dilations + :: + A sequence of {{unsigned long}} of length 2: [dilationHeight, dilationWidth]. Specifies the dilation factor for each spatial dimension applied on the convolution filter (kernel). + The default value is [1, 1]. + + : outputPadding + :: + A sequence of {{unsigned long}} of length 2. + Specifies the padding values applied to each spatial dimension of the output tensor. The explicit padding values are needed to disambiguate the output tensor shape for transposed convolution when the value of the *options*.{{MLConvTranspose2dOptions/strides}} is greater than 1. + + Note that these values are only used to disambiguate output shape when needed; it does not necessarily cause any padding value to be written to the output tensor. + + The default values is [0, 0]. + + : outputSizes + :: + A sequence of {{unsigned long}} of length 2. + Specifies the sizes of the last two dimensions of the output tensor. When the output sizes are explicitly specified, the output padding values in {{MLConvTranspose2dOptions/outputPadding}} are ignored. + + If not specified, the output sizes are automatically computed. - "nhwc": - - input tensor: [batches, height, width, input_channels] - - output tensor: [batches, height, width, output_channels] + : autoPad + :: + An {{MLAutoPad}} [=string=]. + Specifies the automatic input padding options. + The default value is *"explicit"*, which means that the values in the {{MLConvTranspose2dOptions/padding}} array should be used for input padding. - - *filterLayout*: an {{MLConvTranspose2dFilterOperandLayout}}. The default value is *"iohw"*. This option specifies the layout format of the filter tensor as follow: + When the option is set other than *"explicit"*, the values in the {{MLConvTranspose2dOptions/padding}} array are ignored. - "iohw": - - [input_channels, output_channels/groups, height, width] + With the *"same-upper"* option, the padding values are automatically computed such that the additional ending padding of the spatial input dimensions would allow all of the input values in the corresponding dimension to be filtered. - "hwoi": - - [height, width, output_channels/groups, input_channels] + The *"same-lower"* option is similar but padding is applied to the beginning padding of the spatial input dimensions instead of the ending one. - "ohwi": - - [output_channels/groups, height, width, input_channels] + : groups + :: + An {{unsigned long}} scalar. + Specifies the number of groups that input channels and output channels are divided into. + The default value is 1. - - *bias*: an {{MLOperand}}. The additional 1-D tensor with the shape of [output_channels] whose values are to be added to the transposed convolution result. - - *activation*: an {{MLActivation}}. The optional activation function that immediately follows the transposed convolution operation. + : inputLayout + :: + An {{MLInputOperandLayout}} [=string=]. + Specifies the layout format of the input and output tensor as follows: + - **"nchw"** + - input tensor: *[batches, inputChannels, height, width]* + - output tensor: *[batches, outputChannels, height, width]* + - **"nhwc"**: + - input tensor: *[batches, height, width, inputChannels]* + - output tensor: *[batches, height, width, outputChannels]* + The default value is *"nchw"*. + + : filterLayout + :: + An {{MLConvTranspose2dFilterOperandLayout}} [=string=]. + Specifies the layout format of the filter tensor as follow: + - **"iohw"**: [inputChannels, outputChannels/groups, height, width] + - **"hwoi"**: [height, width, outputChannels/groups, inputChannels] + - **"ohwi"**: [outputChannels/groups, height, width, inputChannels] + The default value is *"iohw"*. + + : bias + :: + An {{MLOperand}} object. + Specifies the additional 1-D tensor with the shape of *[outputChannels]* whose values are to be added to the convolution result. - **Returns:** an {{MLOperand}}. The output 4-D tensor that contains the transposed convolution result. The output shape is interpreted according to the *options.inputLayout* value. More specifically, unless the *options.outputSizes* values are explicitly specified, the *options.outputPadding* may be needed to compute the spatial dimension values of the output tensor as follow: + : activation + :: + An {{MLActivation}} object. + Specifies the optional activation function that immediately follows the convolution operation. +
- *output size = (input size - 1) ** *stride + (filter size - 1) ** *dilation + 1 - beginning padding - ending padding + output padding* ++ **Arguments:** + - *input*: an {{MLOperand}}. The input 4-D tensor. The logical shape + is interpreted according to the value of *options*.{{MLConvTranspose2dOptions/inputLayout}}. + - *filter*: an {{MLOperand}}. The filter 4-D tensor. The logical shape is + interpreted according to the value of *options*.{{MLConvTranspose2dOptions/filterLayout}} and {{MLConvTranspose2dOptions/groups}}. + - *options*: an optional {{MLConvTranspose2dOptions}}. + + **Returns:** an {{MLOperand}}. The output 4-D tensor that contains the transposed convolution result. The output shape is interpreted according to the *options*.{{MLConvTranspose2dOptions/inputLayout}} value. More specifically, unless the *options*.{{MLConvTranspose2dOptions/outputSizes}} values are explicitly specified, the *options*.{{MLConvTranspose2dOptions/outputPadding}} may be needed to compute the spatial dimension values of the output tensor as follow: + + *outputSize = (inputSize - 1) ** *stride + (filterSize - 1) ** *dilation + 1 - beginningPadding - endingPadding + outputPadding*++ ++ ### Element-wise binary operations ### {#api-mlgraphbuilder-binary} -Compute the element-wise binary addition, subtraction, multiplication, division, -maximum and minimum of the two input tensors. +Compute the element-wise binary addition, subtraction, multiplication, division, power, maximum and minimum of the two input tensors. + +The element-wise binary operations will be broadcasted according to +[[!numpy-broadcasting-rule]]. The [=rank=] of the output tensor is the maximum +[=rank=] of the input tensors. For each dimension of the output tensor, its size +is the maximum size along that dimension of the input tensors. + -+ The convTranspose2d(|input|, |filter|, |options|) method steps are: +
++ 1. [=Assert=]: the type of |input| and |filter| is {{MLOperand}}. + 1. Let |inputSize| be the [=list/size=] of |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}. + 1. Let |filterSize| be the [=list/size=] of |filter|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}. + 1. If |inputSize| is not 4, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |filterSize| is not 4, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/type}} is not the same as {{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/type}}, then [=exception/throw=] a {{TypeError}}. + 1. If |options|.{{MLConvTranspose2dOptions/padding}} does not [=map/exist=], set it to `« 0, 0, 0, 0 »`. + 1. Else if the [=list/size=] of |options|.{{MLConvTranspose2dOptions/padding}} is not 4, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLConvTranspose2dOptions/strides}} does not [=map/exist=], set it to `« 1, 1 »`. + 1. Else if the [=list/size=] of |options|.{{MLConvTranspose2dOptions/strides}} is not 2, then [=exception/throw=] a {{TypeError}}. + 1. If any element in |options|.{{MLConv2dOptions/strides}} is equal to 0, then [=exception/throw=] a {{TypeError}}. + 1. If |options|.{{MLConvTranspose2dOptions/dilations}} does not [=map/exist=], set it to `« 1, 1 »`. + 1. Else if the [=list/size=] of |options|.{{MLConvTranspose2dOptions/dilations}} is not 2, then [=exception/throw=] a {{TypeError}}. + 1. If |options|.{{MLConvTranspose2dOptions/outputPadding}} does not [=map/exist=], set it to `« 0, 0 »`. + 1. Else if the [=list/size=] of |options|.{{MLConvTranspose2dOptions/outputPadding}} is not 2, then [=exception/throw=] a {{TypeError}}. + 1. If |options|.{{MLConvTranspose2dOptions/outputSizes}} [=map/exists=]: + 1. If the [=list/size=] of |options|.{{MLConvTranspose2dOptions/outputSizes}} is not 2, then [=exception/throw=] a {{TypeError}}. + 1. If the elements of |options|.{{MLConvTranspose2dOptions/outputSizes}} are not smaller than the elements at the same dimension (index) for |options|.{{MLConvTranspose2dOptions/strides}}, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |inputSize| / |options|.{{MLConvTranspose2dOptions/groups}} is not equal to |filterSize|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. Else if |inputSize| % |options|.{{MLConvTranspose2dOptions/groups}} is not 0, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLConvTranspose2dOptions/bias}} [=map/exists=]: + 1. [=Assert=]: the type of |options|.{{MLConvTranspose2dOptions/bias}} is {{MLOperand}}. + 1. If the [=list/size=] of |options|.{{MLConvTranspose2dOptions/bias}}.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}} is not 1, then [=exception/throw=] a {{TypeError}}. + 1. If |options|.{{MLConvTranspose2dOptions/bias}}.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/type}} is not the same as |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/type}}, then [=exception/throw=] a {{TypeError}}. + 1. If |options|.{{MLConvTranspose2dOptions/activation}} [=map/exists=]: + 1. [=Assert=]: the type of |options|.{{MLConvTranspose2dOptions/activation}} is {{MLActivation}}. + 1. Let |outputShape| be the result of invoking the underlying implementation for calculating output dimensions, given |options|. + 1. If |outputShape| is not the same as the shape of |options|.{{MLConvTranspose2dOptions/bias}}.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. Let |desc| a new {{MLOperandDescriptor}}. + 1. Set |desc|.{{MLOperandDescriptor/type}} to |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/type}}. + 1. Set |desc|.{{MLOperandDescriptor/dimensions}} to |outputShape|. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of creating an MLOperand given [=this=] and |desc|. + 1. Make a request to the underlying platform to: + 1. Create an [=implementation-defined=] platform operator |convTranspose2dImpl| for this method, given |options| and |filter|. + 1. If |options|.{{MLConvTranspose2dOptions/activation}} [=map/exists=],register it as activation to |convTranspose2dImpl|. + 1. Store a reference of |convTranspose2dImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |convTranspose2dImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |convTranspose2dImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |convTranspose2dImpl|. + 1. Return |output|. +++ +**Arguments:** - *a*: an {{MLOperand}}. The first input tensor. - *b*: an {{MLOperand}}. The second input tensor. **Returns:** an {{MLOperand}}. The output tensor that contains the result of element-wise binary operation of the two input tensors. - - The element-wise binary operation will be broadcasted according to - [[!numpy-broadcasting-rule]]. The rank of the output tensor is the maximum - rank of the input tensors. For each dimension of the output tensor, its size - is the maximum size along that dimension of the input tensors. - ++**Operation types:** - *add*: Add the values of the two input tensors, element-wise. - *sub*: Subtract the values of the second input tensor from the values of the first input tensor, element-wise. @@ -1599,29 +2401,129 @@ partial interface MLGraphBuilder { - *pow*: Compute the values of the values of the first input tensor to the power of the values of the second input tensor, element-wise.++ ++ ++ To create element-wise binary operation given |op|, |a| and |b|, run the following steps: +
++ 1. [=Assert=]: |op| is one of "add", "sub", "mul", "div", "max", "min", "pow". + 1. [=Assert=]: the type of |a| and |b| is {{MLOperand}}. + 1. If |a|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/type}} is not equal to |b|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/type}}, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. Let |descriptor| be a new {{MLOperandDescriptor}}. + 1. Set |descriptor|.{{MLOperandDescriptor/type}} to |a|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/type}}. + 1. Let |descriptor|.{{MLOperandDescriptor/dimensions}} be the result of running the [=MLGraphBuilder/broadcast-shapes=] steps given |a|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}} and |b|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}. + 1. If that [=exception/throws=] an error, re-[=exception/throw=] the error. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of creating an MLOperand given [=this=] and |descriptor|. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the binary operation |op|, given |a| and |b|. + 1. Store a reference of |opImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |a|.{{MLOperand/[[operand]]}} and |b|.{{MLOperand/[[operand]]}} as inputs to |opImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |opImpl|. + 1. Return |output|. +++ ++ ++ To broadcast-shapes given |shape1| and |shape2|, run the following steps: +
++ 1. [=Assert=]: The type of |shape1| and |shape2| is `sequence of unsigned long`. + 1. Let |output| be the result of invoking the [=implementation-defined=] shape broadcast on |shape1| and |shape2|. + 1. If that fails, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. Return |output|. +++ The most common implementation is that two shapes are compatible, when each of their corresponding dimensions are equal, or one of them is 1. The output shape consists of the maximum of the corresponding dimensions. ++++ ### Element-wise unary operations ### {#api-mlgraphbuilder-unary} Compute the element-wise unary operation for input tensor. -+ The element-wise binary operation algorithms invoke the [=MLGraphBuilder/element-wise-binary-op | create element-wise binary operation=] steps as follows. +
++++ The add(|a|, |b|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/element-wise-binary-op | create element-wise binary operation=] given "add", |a| and |b|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. ++ ++ The sub(|a|, |b|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/element-wise-binary-op | create element-wise binary operation=] given "sub", |a| and |b|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. ++ ++ The mul(|a|, |b|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/element-wise-binary-op | create element-wise binary operation=] given "mul", |a| and |b|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. ++ ++ The div(|a|, |b|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/element-wise-binary-op | create element-wise binary operation=] given "div", |a| and |b|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. ++ ++ The max(|a|, |b|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/element-wise-binary-op | create element-wise binary operation=] given "max", |a| and |b|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. ++ ++ The min(|a|, |b|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/element-wise-binary-op | create element-wise binary operation=] given "min", |a| and |b|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. ++ ++ The pow(|a|, |b|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/element-wise-binary-op | create element-wise binary operation=] given "pow", |a| and |b|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. +++ +**Arguments:** - - *x*: an {{MLOperand}}. The input tensor. + - *input*: an {{MLOperand}}. The input tensor. **Returns:** an {{MLOperand}}. The output tensor that contains the result of element-wise unary operation of the input tensor. The shape of the output tensor is the same as the shape of input tensor. - ++**Operation types:** - *abs*: Compute the absolute value of the input tensor, element-wise. - *ceil*: Compute the ceiling of the input tensor, element-wise. @@ -1634,33 +2536,119 @@ partial interface MLGraphBuilder { - *tan*: Compute the tangent of the input tensor, element-wise.++ ++ ++ To create element-wise unary operation given |op| and |input|, run the following steps: +
++ 1. [=Assert=]: |op| is one of "abs", "ceil", "cos", "exp", "floor", "log", "neg", "sin", "tan". + 1. [=Assert=]: the type of |input| is {{MLOperand}}. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of copying an MLOperand given |input|. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the unary operation |op|. + 1. Store a reference of |opImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |opImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |opImpl|. + 1. Return |output|. ++++ ### The elu() method ### {#api-mlgraphbuilder-elu} -Calculate the exponential linear unit function on the input tensor element-wise. The calculation follows the expression `max(0, x) + alpha * (exp(min(0, x)) - 1)`. +Calculate the exponential linear unit function (ELU) on the input tensor element-wise. The calculation follows the expression `max(0, x) + alpha * (exp(min(0, x)) - 1)`. + -+ The element-wise unary operation algorithms invoke the [=MLGraphBuilder/element-wise-unary-op | create element-wise unary operation=] steps as follows. +
++++ The abs(|input|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/element-wise-unary-op | create element-wise unary operation=] given "abs" and |input|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. ++ ++ The ceil(|input|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/element-wise-unary-op | create element-wise unary operation=] given "ceil" and |input|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. ++ ++ The cos(|input|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/element-wise-unary-op | create element-wise unary operation=] given "cos" and |input|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. ++ ++ The exp(|input|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/element-wise-unary-op | create element-wise unary operation=] given "exp" and |input|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. ++ ++ The floor(|input|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/element-wise-unary-op | create element-wise unary operation=] given "floor" and |input|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. ++ ++ The log(|input|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/element-wise-unary-op | create element-wise unary operation=] given "log" and |input|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. ++ ++ The neg(|input|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/element-wise-unary-op | create element-wise unary operation=] given "neg" and |input|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. ++ ++ The sin(|input|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/element-wise-unary-op | create element-wise unary operation=] given "sin" and |input|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. ++ ++ The tan(|input|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/element-wise-unary-op | create element-wise unary operation=] given "tan" and |input|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. ++- **Arguments:** - - *x*: an {{MLOperand}}. The input tensor. - - *options*: an optional {{MLEluOptions}}. The optional parameters of the operation. - - *alpha*: a {{float}} scalar multiplier, default to 1. - - **Returns:** - - an {{MLOperand}}. The output tensor of the same shape as *x*. - - an {{MLActivation}}. The activation function representing the elu operation. -++ +#### The {{MLGraphBuilder/elu(input, options)}} method #### {#api-mlgraphbuilder-elu-input-options} +++ ++The behavior of this operation can be generically emulated from the usage of other operations as follow. However, user agents typically have a more efficient implementation for it, therefore its usage is encouraged from the performance standpoint. +
return builder.add( builder.max(builder.constant(0), x), @@ -1670,11 +2658,63 @@ partial interface MLGraphBuilder { builder.exp(builder.min(builder.constant(0), x)), builder.constant(1))));-+ **Arguments:** + - *input*: an {{MLOperand}}. The input tensor. + - *options*: an optional {{MLEluOptions}}. The optional parameters of the operation. + - *alpha*: a {{float}} scalar multiplier, default to 1. + + **Returns:** + - an {{MLOperand}}. The output tensor of the same shape as *input*.++ ++ +#### The {{MLGraphBuilder/elu(options)}} method #### {#api-mlgraphbuilder-elu-options} ++ The elu(|input|, |options|) method steps are: +
++ 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of copying an MLOperand given |input|. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the ELU operation, given |options|. + 1. Store a reference of |opImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |opImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |opImpl|. + 1. Return |output|. +++ **Arguments:** + - *options*: an optional {{MLEluOptions}}. The optional parameters of the operation. + - *alpha*: a {{float}} scalar multiplier, default to 1. + + **Returns:** + - an {{MLActivation}}. The activation function representing the elu operation. ++ ++ ++ ### The gemm() method ### {#api-mlgraphbuilder-gemm} Calculate the [general matrix multiplication of the Basic Linear Algebra Subprograms](https://en.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms#Level_3). The calculation follows the expression `alpha * A * B + beta * C`, where `A` is a 2-D tensor with shape [M, K] or [K, M], `B` is a 2-D tensor with shape [K, N] or [N, K], and `C` is broadcastable to the shape [M, N]. `A` and `B` may optionally be transposed prior to the calculation. + -+ The elu(|options|) method steps are: +
++ 1. Let |op| be the result of creating an MLActivation given [=this=], `"elu"` and |options|. + 1. Return |op|. +++ +{{MLGemmOptions}} has the following members: ++ : c + :: + An {{MLOperand}}. Specifies the third input tensor. It is either a scalar, or of the shape that is unidirectionally broadcastable to the shape [M, N] according to [[!numpy-broadcasting-rule]]. When it is not specified, the computation is done as if *c* is a scalar 0.0. + + : alpha + :: + A {{float}} scalar multiplier for the first input. + + : beta + :: + A {{float}} scalar multiplier for the third input {{MLGemmOptions/c}}. + + : aTranspose + :: + A {{boolean}} indicating if the first input should be transposed prior to calculating the output. + + : bTranspose + :: + A {{boolean}} indicating if the second input should be transposed prior to calculating the output. +
+ +**Arguments:** - *a*: an {{MLOperand}}. The first input 2-D tensor with shape [M, K] if *aTranspose* is false, or [K, M] if *aTranspose* is true. - *b*: an {{MLOperand}}. The second input 2-D tensor with shape [K, N] if *bTranspose* is false, or [N, K] if *bTranspose* is true. - *options*: an optional {{MLGemmOptions}}. The optional parameters of the operation. - - *c*: an {{MLOperand}}. The third input tensor. It is either a scalar, or of the shape that is unidirectionally broadcastable to the shape [M, N] according to [[!numpy-broadcasting-rule]]. When it is not specified, the computation is done as if *c* is a scalar 0.0. - - *alpha*: a {{float}} scalar multiplier for the first input, default to 1.0. - - *beta*: a {{float}} scalar multiplier for the third input, default to 1.0. - - *aTranspose*: a {{boolean}} indicating if the first input should be transposed prior to calculating the output, default to false. - - *bTranspose*: a {{boolean}} indicating if the second input should be transposed prior to calculating the output, default to false. **Returns:** an {{MLOperand}}. The output 2-D tensor of shape [M, N] that contains the calculated product of all the inputs. +-+### The gru() method ### {#api-mlgraphbuilder-gru} @@ -1747,28 +2843,91 @@ partial interface MLGraphBuilder { optional MLGruOptions options = {}); }; -+ ++ ++ The gemm(|a|, |b|, |options|) method steps are: +
++ 1. [=Assert=]: the type of |a| and |b| is {{MLOperand}}. + 1. Let |shapeA| be |a|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}} and |sizeA| the [=list/size=] of |shapeA|. + 1. Let |shapeB| be |b|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}} and |sizeB| the [=list/size=] of |shapeB|. + 1. If |sizeA| is not 2 or |sizeB| is not 2, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLGemmOptions/aTranspose}} is true, then let |shapeA| be the reverse array of |shapeA|. + 1. If |options|.{{MLGemmOptions/bTranspose}} is true, then let |shapeB| be the reverse array of |shapeB|. + 1. If |shapeA|[1] is not equal to |shapeB|[0], then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLGemmOptions/c}} [=map/exists=] and is not unidirectionally broadcastable to the shape [|shapeA|[0], |shapeB|[1]] according to the [[!numpy-broadcasting-rule]], then [=exception/throw=] a "{{DataError}}" {{DOMException}}. +++ Type compatibility between |a|, |b| and |options|.{{MLGemmOptions/c}} can be also checked. ++ 1. Let |desc| a new {{MLOperandDescriptor}}. + 1. Set |desc|.{{MLOperandDescriptor/dimensions}} to [|shapeA|[0], |shapeB|[1]]. + 1. Set |desc|.{{MLOperandDescriptor/type}} to |a|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/type}}. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of creating an MLOperand given [=this=] and |desc|. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the GEMM operation, given |options|. + 1. Store a reference of |opImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |a|.{{MLOperand/[[operand]]}} and |b|.{{MLOperand/[[operand]]}} as inputs to |opImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |opImpl|. + 1. Return |output|. +++ ++The behavior of this operation can be generically emulated from the usage of other operations as follow. However, user agents typically have a more efficient implementation for it, therefore its usage is encouraged from the performance standpoint. -
++if (options.aTranspose) a = builder.transpose(a); @@ -1712,8 +2808,8 @@ partial interface MLGraphBuilder { let ab = builder.matmul(builder.mul(builder.constant(options.alpha), a), b); return (c ? builder.add(ab, builder.mul(builder.constant(options.beta), c)) : ab); --+ +{{MLGruOptions}} has the following members: ++ : bias + :: + An {{MLOperand}}. Specifies the 2-D input bias tensor of shape [numDirections, 3 * hiddenSize]. The ordering of the bias vectors in the second dimension of the tensor shape is specified according to the {{MLGruOptions/layout}} argument. + + : recurrentBias + :: + An {{MLOperand}}. Specifies the 2-D recurrent bias tensor of shape [numDirections, 3 * hiddenSize]. The ordering of the bias vectors in the second dimension of the tensor shape is specified according to the {{MLGruOptions/layout}} argument. + + : initialHiddenState + :: + An {{MLOperand}}. The 3-D initial hidden state tensor of shape [numDirections, batchSize, hiddenSize]. + When not specified, implementations SHOULD use a tensor filled with zero. + + : resetAfter + :: + A {{boolean}} indicating whether to apply the reset gate after or before matrix multiplication. The default value is true. + + : returnSequence + :: + A {{boolean}} indicating whether to also return the entire sequence with every output from each time step in it in addition to the output of the last time step. + The default value is false. + + : direction + :: + An {{MLRecurrentNetworkDirection}}. Specifies the processing direction of the input sequence. When set to `"both"`, the size of the first dimension of the weight and the bias tensor shapes must be 2, and the input is processed in both directions. + + : layout + :: + An {{MLGruWeightLayout}}. The ordering of the weight and bias vectors for the internal gates of GRU, specifically the `update (z)`, `reset (r)`, and `new (n)` gate, as indicated in the second dimension of the weight and bias tensor shape. When not specified, the default layout is `"zrn"`.bias + + : activations + :: + A sequence of {{MLActivation}}. Specifies a pair of activation functions with the first function used for the update and reset gate, and the second used for the new gate. When not specified, implementations SHOULD use the the pair of sigmoid (`"sigmoid"`) and the hyperbolic tangent (`"tanh"`) functions, respectively. +
+ +**Arguments:** - - *input*: an {{MLOperand}}. The input 3-D tensor of shape [steps, batch_size, input_size]. - - *weight*: an {{MLOperand}}. The 3-D input weight tensor of shape [num_directions, 3 * hidden_size, input_size]. The ordering of the weight vectors in the second dimension of the tensor shape is specified according to the *options.layout* argument. - - *recurrentWeight*: an {{MLOperand}}. The 3-D recurrent weight tensor of shape [num_directions, 3 * hidden_size, hidden_size]. The ordering of the weight vectors in the second dimension of the tensor shape is specified according to the *options.layout* argument. + - *input*: an {{MLOperand}}. The input 3-D tensor of shape [steps, batchSize, inputSize]. + - *weight*: an {{MLOperand}}. The 3-D input weight tensor of shape [numDirections, 3 * hiddenSize, inputSize]. The ordering of the weight vectors in the second dimension of the tensor shape is specified according to the |options|.{{MLGruOptions/layout}} argument. + - *recurrentWeight*: an {{MLOperand}}. The 3-D recurrent weight tensor of shape [numDirections, 3 * hiddenSize, hiddenSize]. The ordering of the weight vectors in the second dimension of the tensor shape is specified according to the |options|.{{MLGruOptions/layout}} argument. - *steps*: an {{unsigned long}} scalar. The number of time steps in the recurrent network. The value must be greater than 0. - *hiddenSize*: an {{unsigned long}} scalar. The value of the third dimension of the cell output tensor shape. It indicates the number of features in the hidden state. - *options*: an optional {{MLGruOptions}}. The optional parameters of the operation. - - *bias*: an {{MLOperand}}. The 2-D input bias tensor of shape [num_directions, 3 * hidden_size]. The ordering of the bias vectors in the second dimension of the tensor shape is specified according to the *options.layout* argument. - - *recurrentBias*: an {{MLOperand}}. The 2-D recurrent bias tensor of shape [num_directions, 3 * hidden_size]. The ordering of the bias vectors in the second dimension of the tensor shape is specified according to the *options.layout* argument. - - *initialHiddenState*: an {{MLOperand}}. The 3-D initial hidden state tensor of shape [num_directions, batch_size, hidden_size]. When not specified, it's assumed to be a tensor filled with zero. - - *resetAfter*: a {{boolean}} indicating whether to apply the reset gate after or before matrix multiplication. Default to true. - - *returnSequence*: a {{boolean}} indicating whether to also return the entire sequence with every output from each time step in it in addition to the output of the last time step. Default to false. - - *direction*: an {{MLRecurrentNetworkDirection}}. The processing direction of the input sequence. When set to *"both"*, the size of the first dimension of the weight and the bias tensor shapes must be 2, and the input is processed in both directions. - - *layout*: an {{MLGruWeightLayout}}. The ordering of the weight and bias vectors for the internal gates of GRU, specifically the *update (z)*, *reset (r)*, and *new (n)* gate, as indicated in the second dimension of the weight and bias tensor shape. When not specified, the default layout is *"zrn"*. - - *activations*: a sequence of {{MLActivation}}. A pair of activation functions with the first function used for the update and reset gate, and the second used for the new gate. When not specified, it's assumed to be the sigmoid (*"sigmoid"*) and the hyperbolic tangent (*"tanh"*) function respectively. - **Returns:** a sequence of {{MLOperand}}. The first element of the sequence is a 3-D tensor of shape [num_directions, batch_size, hidden_size], the cell output from the last time step of the network. Additionally, if *options.returnSequence* is set to true, the second element is the 4-D output tensor of shape [steps, num_directions, batch_size, hidden_size] containing every cell outputs from each time step in the temporal sequence. + **Returns:** a sequence of {{MLOperand}}. The first element of the sequence is a 3-D tensor of shape [numDirections, batchSize, hiddenSize], the cell output from the last time step of the network. Additionally, if |options|.{{MLGruOptions/returnSequence}} is set to true, the second element is the 4-D output tensor of shape [steps, numDirections, batchSize, hiddenSize] containing every cell outputs from each time step in the temporal sequence. +-+### The gruCell() method ### {#api-mlgraphbuilder-grucell} A single time step of the Gated Recurrent Unit [[GRU]] recurrent network using an update gate and a reset gate to compute the hidden state that rolls into the output across the temporal sequence of a recurrent network. + -+ ++ ++ The gru(|input|, |weight|, |recurrentWeight|, |steps|, |hiddenSize|, |options|) method steps are: +
++ 1. [=Assert=]: the type of |input|, |weight| and |recurrentWeight| is {{MLOperand}}. + 1. If the [=rank=] of |input| or |weight| or |recurrentWeight| is not 3, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLGruOptions/bias}} [=map/exists=]. + 1. [=Assert=]: its type is {{MLOperand}}. + 1. If |options|.{{MLGruOptions/bias}}.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[1] is not equal to 3 * |hiddenSize|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLGruOptions/recurrentBias}} [=map/exists=]. + 1. [=Assert=]: its type is {{MLOperand}}. + 1. If |options|.{{MLGruOptions/recurrentBias}}.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[1] is not equal to 3 * |hiddenSize|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLGruOptions/initialHiddenState}} [=map/exists=]. + 1. [=Assert=]: its type is {{MLOperand}}. + 1. If its rank is not 3, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLGruOptions/activations}} [=map/exists=] and its [=list/size=] is not 2, then [=exception/throw=] a {{TypeError}}. + 1. If |steps| is not equal to |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[0], then [=exception/throw=] a {{TypeError}}. + 1. Let |output| be an empty sequence of {{MLOperand}} objects. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for `"gru"`, given |weight|, |recurrentWeight|, |steps|, |hiddenSize| and |options| as parameters. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |opImpl|. + 1. Connect |output| as output to |opImpl|. + 1. Return |output|. ++++ ++The behavior of this operation can be generically emulated from the usage of other operations as follows. However, user agents typically have a more efficient implementation for it, therefore its usage is encouraged from the performance standpoint. -
++const numDirections = (options.direction == "both" ? 2 : 1); let hiddenState = options.initialHiddenState; @@ -1785,11 +2944,11 @@ partial interface MLGraphBuilder { let currentRecurrentBias = []; for (let dir = 0; dir < numDirections; ++dir) { - currentWeight.push(builder.squeeze(builder.slice(weight, [dir, 0, 0], [1, 3 * hidden_size, input_size]), { axes: [0] })); - currentRecurrentWeight.push(builder.squeeze(builder.slice(recurrentWeight, [dir, 0, 0], [1, 3 * hidden_size, hidden_size]), { axes: [0] })); - currentBias.push(options.bias ? (builder.squeeze(builder.slice(options.bias, [dir, 0], [1, 3 * hidden_size]), { axes: [0] })) : null); + currentWeight.push(builder.squeeze(builder.slice(weight, [dir, 0, 0], [1, 3 * hiddenSize, inputSize]), { axes: [0] })); + currentRecurrentWeight.push(builder.squeeze(builder.slice(recurrentWeight, [dir, 0, 0], [1, 3 * hiddenSize, hiddenSize]), { axes: [0] })); + currentBias.push(options.bias ? (builder.squeeze(builder.slice(options.bias, [dir, 0], [1, 3 * hiddenSize]), { axes: [0] })) : null); currentRecurrentBias.push(options.recurrentBias ? - (builder.squeeze(builder.slice(options.recurrentBias, [dir, 0], [1, 3 * hidden_size]), { axes: [0] })) : null); + (builder.squeeze(builder.slice(options.recurrentBias, [dir, 0], [1, 3 * hiddenSize]), { axes: [0] })) : null); } for (let step = 0; step < steps; ++step) { @@ -1797,12 +2956,12 @@ partial interface MLGraphBuilder { let currentOutput = null; for (let dir = 0; dir < numDirections; ++dir) { - currentHidden.push(builder.squeeze(builder.slice(hiddenState, [dir, 0, 0], [1, batch_size, hidden_size]), { axes: [0] })); + currentHidden.push(builder.squeeze(builder.slice(hiddenState, [dir, 0, 0], [1, batchSize, hiddenSize]), { axes: [0] })); } for (let dir = 0; dir < numDirections; ++dir) { let slice = (dir == 1 || options.direction == "backward" ? steps - step - 1 : step); - let currentInput = builder.squeeze(builder.slice(input, [slice, 0, 0], [1, batch_size, input_size]), { axes: [0] }); + let currentInput = builder.squeeze(builder.slice(input, [slice, 0, 0], [1, batchSize, inputSize]), { axes: [0] }); let result = builder.reshape( builder.gruCell( @@ -1824,12 +2983,13 @@ partial interface MLGraphBuilder { } return (sequence ? [hiddenState, sequence] : [hiddenState]); --+ +{{MLGruCellOptions}} has the following members: ++ : bias + :: + An {{MLOperand}}. Specifies the 1-D input bias tensor of shape [3 * hiddenSize]. The ordering of the bias vectors in the second dimension of the tensor shape is specified according to the {{MLGruOptions/layout}} argument. + + : recurrentBias + :: + An {{MLOperand}}. Specifies the 1-D recurrent bias tensor of shape [3 * hiddenSize]. The ordering of the bias vectors in the second dimension of the tensor shape is specified according to the {{MLGruOptions/layout}} argument. + + : resetAfter + :: + A {{boolean}} indicating whether to apply the reset gate after or before matrix multiplication. The default value is true. + + : layout + :: + An {{MLGruWeightLayout}}. The ordering of the weight and bias vectors for the internal gates of GRU, specifically the `update (z)`, `reset (r)`, and `new (n)` gate, as indicated in the second dimension of the weight and bias tensor shape. When not specified, the default layout is `"zrn"`. + + : activations + :: + A sequence of {{MLActivation}}. Specifies a pair of activation functions with the first function used for the update and reset gate, and the second used for the new gate. When not specified, implementations SHOULD use the the pair of sigmoid (`"sigmoid"`) and the hyperbolic tangent (`"tanh"`) functions, respectively. +
+ +**Arguments:** - - *input*: an {{MLOperand}}. The input 2-D tensor of shape [batch_size, input_size]. - - *weight*: an {{MLOperand}}. The 2-D input weight tensor of shape [3 * hidden_size, input_size]. The ordering of the weight vectors in the first dimension of the tensor shape is specified according to the *options.layout* argument. - - *recurrentWeight*: an {{MLOperand}}. The 2-D recurrent weight tensor of shape [3 * hidden_size, hidden_size]. The ordering of the weight vectors in the first dimension of the tensor shape is specified according to the *options.layout* argument. - - *hiddenState*: an {{MLOperand}}. The 2-D input hidden state tensor of shape [batch_size, hidden_size]. + - *input*: an {{MLOperand}}. The input 2-D tensor of shape [batchSize, inputSize]. + - *weight*: an {{MLOperand}}. The 2-D input weight tensor of shape [3 * hiddenSize, inputSize]. The ordering of the weight vectors in the first dimension of the tensor shape is specified according to the *options.layout* argument. + - *recurrentWeight*: an {{MLOperand}}. The 2-D recurrent weight tensor of shape [3 * hiddenSize, hiddenSize]. The ordering of the weight vectors in the first dimension of the tensor shape is specified according to the *options.layout* argument. + - *hiddenState*: an {{MLOperand}}. The 2-D input hidden state tensor of shape [batchSize, hiddenSize]. - *hiddenSize*: an {{unsigned long}} scalar. The value of the second dimension of the output tensor shape. It indicates the number of features in the hidden state. - *options*: an optional {{MLGruCellOptions}}. The optional parameters of the operation. - - *bias*: an {{MLOperand}}. The 1-D input bias tensor of shape [3 * hidden_size]. The ordering of the bias vectors in the first dimension of the tensor shape is specified according to the *options.layout* argument. - - *recurrentBias*: an {{MLOperand}}. The 1-D recurrent bias tensor of shape [3 * hidden_size]. The ordering of the bias vectors in the first dimension of the tensor shape is specified according to the *options.layout* argument. - - *resetAfter*: a {{boolean}} indicating whether to apply the reset gate after or before matrix multiplication. Default to true. - - *layout*: an {{MLGruWeightLayout}}. The ordering of the weight and bias vectors for the internal gates of GRU, specifically the *update (z)*, *reset (r)*, and *new (n)* gate, as indicated in the first dimension of the weight and bias tensor shapes. When not specified, the default layout is *"zrn"*. - - *activations*: a sequence of {{MLActivation}}. A pair of activation functions with the first function used for the *update (z)* and *reset (r)* gate, and the second used for the *new (n)* gate. When not specified, it's default to the sigmoid (*"sigmoid"*) and the hyperbolic tangent (*"tanh"*) function respectively. - **Returns:** an {{MLOperand}}. The 2-D tensor of shape [batch_size, hidden_size], the cell output hidden state of a single time step of the recurrent network. + **Returns:** an {{MLOperand}}. The 2-D tensor of shape [batchSize, hiddenSize], the cell output hidden state of a single time step of the recurrent network. +-+### The hardSigmoid() method ### {#api-mlgraphbuilder-hard-sigmoid} -Calculate the non-smooth function used in place of a sigmoid function on the input tensor. +Calculate the non-smooth hard sigmoid function on the input tensor, used instead of the sigmoid function for faster computation. -+ ++ ++ The gruCell(|input|, |weight|, |recurrentWeight|, |hiddenState|, |hiddenSize|, |options|) method steps are: +
++ 1. [=Assert=]: the type of |input|, |weight| and |recurrentWeight| is {{MLOperand}}. + 1. If the [=rank=] of |input| or |weight| or |recurrentWeight| or |hiddenState| is not 2, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |weight|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[0] is not equal to 3 * |hiddenSize|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |recurrentWeight|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[0] is not equal to 3 * |hiddenSize|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLGruOptions/bias}} [=map/exists=]: + 1. [=Assert=]: its type is {{MLOperand}}. + 1. If its rank is not equal to 3 * |hiddenSize|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLGruOptions/recurrentBias}} [=map/exists=]: + 1. [=Assert=]: its type is {{MLOperand}}. + 1. If its rank is not equal to 3 * |hiddenSize|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLGruOptions/activations}} [=map/exists=] and its [=list/size=] is not 2, then [=exception/throw=] a {{TypeError}}. + 1. Let |desc| a new {{MLOperandDescriptor}}. + 1. Set |desc|.{{MLOperandDescriptor/dimensions}} to [ |input|.{{MLOperandDescriptor/dimensions}}[0], |hiddenSize| ]. + 1. Set |desc|.{{MLOperandDescriptor/type}} to |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/type}}. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of creating an MLOperand given [=this=] and |desc|. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for `"gruCell"`, given |weight|, |recurrentWeight|, |hiddenState|, |hiddenSize| and |options| as parameters. + 1. Store a reference of |opImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |opImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |opImpl|. + 1. Return |output|. ++++ ++The behavior of this operation can be generically emulated via other operations as shown below, when the weight layout is the default *"zrn"* layout, and the activation functions of the update/reset gate and new gate are of the operator types *sigmoid* and *tanh* respectively. -
++const one = builder.constant(1); const zero = builder.constant(0); @@ -1877,11 +3093,11 @@ partial interface MLGraphBuilder { builder.add( builder.matmul( input, - builder.transpose(builder.slice(weight, [0, 0], [hiddenSize, input_size])) + builder.transpose(builder.slice(weight, [0, 0], [hiddenSize, inputSize])) ), builder.matmul( hiddenState, - builder.transpose(builder.slice(recurrentWeight, [0, 0], [hiddenSize, hidden_size])) + builder.transpose(builder.slice(recurrentWeight, [0, 0], [hiddenSize, hiddenSize])) ) ) ) @@ -1897,11 +3113,11 @@ partial interface MLGraphBuilder { builder.add( builder.matmul( input, - builder.transpose(builder.slice(weight, [hiddenSize, 0], [hiddenSize, input_size])) + builder.transpose(builder.slice(weight, [hiddenSize, 0], [hiddenSize, inputSize])) ), builder.matmul( hiddenState, - builder.transpose(builder.slice(recurrentWeight, [hiddenSize, 0], [hiddenSize, hidden_size])) + builder.transpose(builder.slice(recurrentWeight, [hiddenSize, 0], [hiddenSize, hiddenSize])) ) ) ) @@ -1916,7 +3132,7 @@ partial interface MLGraphBuilder { builder.add( builder.matmul( input, - builder.transpose(builder.slice(weight, [2 * hiddenSize, 0], [hiddenSize, input_size])) + builder.transpose(builder.slice(weight, [2 * hiddenSize, 0], [hiddenSize, inputSize])) ), builder.mul( r, @@ -1924,7 +3140,7 @@ partial interface MLGraphBuilder { (options.recurrentBias ? builder.slice(options.recurrentBias, [2 * hiddenSize], [hiddenSize]) : zero), builder.matmul( hiddenState, - builder.transpose(builder.slice(recurrentWeight, [2 * hiddenSize, 0], [hiddenSize, hidden_size])) + builder.transpose(builder.slice(recurrentWeight, [2 * hiddenSize, 0], [hiddenSize, hiddenSize])) ) ) ) @@ -1942,11 +3158,11 @@ partial interface MLGraphBuilder { builder.add( builder.matmul( input, - builder.transpose(builder.slice(weight, [2 * hiddenSize, 0], [hiddenSize, input_size])) + builder.transpose(builder.slice(weight, [2 * hiddenSize, 0], [hiddenSize, inputSize])) ), builder.matmul( builder.mul(r, hiddenState), - builder.transpose(builder.slice(recurrentWeight, [2 * hiddenSize, 0], [hiddenSize, hidden_size])) + builder.transpose(builder.slice(recurrentWeight, [2 * hiddenSize, 0], [hiddenSize, hiddenSize])) ) ) ) @@ -1955,12 +3171,12 @@ partial interface MLGraphBuilder { // compute the new hidden state return builder.add(builder.mul(z, hiddenState), builder.mul(n, builder.sub(one, z))); --- **Arguments:** - - *x*: an {{MLOperand}}. The input tensor. - - *options*: an optional {{MLHardSigmoidOptions}}. The optional parameters of the operation. - - *alpha*: a {{float}} scalar multiplier, default to 0.2. - - *beta*: a {{float}} scalar addition, default to 0.5. - **Returns:** - - an {{MLOperand}}. The output tensor of the same shape as *x*. - - an {{MLActivation}}. The activation function representing the hard sigmoid operation. - -++ +{{MLHardSigmoidOptions}} has the following members: +++ ++The behavior of this operation can be generically emulated from the usage of other operations as follow. However, user agents typically have a more efficient implementation for it, therefore its usage is encouraged from the performance standpoint. +
return builder.max( builder.min( @@ -1997,31 +3206,90 @@ partial interface MLGraphBuilder { builder.constant(1)), builder.constant(0));-+ : alpha + :: + A {{float}} scalar multiplier. + The default value is 0.2. + : beta + :: + A {{float}} scalar addition. + The default value is 0.5. +
+ +#### The {{MLGraphBuilder/hardSigmoid(input, options)}} method #### {#api-mlgraphbuilder-hardsigmoid-input-options} ++ **Arguments:** + - *input*: an {{MLOperand}}. The input tensor. + - *options*: an optional {{MLHardSigmoidOptions}}. The optional parameters of the operation. + + **Returns:** + - an {{MLOperand}}. The output tensor of the same shape as *input*. ++ ++ ++ +#### The {{MLGraphBuilder/hardSigmoid(options)}} method #### {#api-mlgraphbuilder-hardsigmoid-options} ++ The hardSigmoid(|input|, |options|) method steps are: +
++ 1. [=Assert=]: the type of |input| is {{MLOperand}}. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of copying an MLOperand given |input|. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the hard sigmoid operation, given |options|. + 1. Store a reference of |opImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |opImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |opImpl|. + 1. Return |output|. +++ **Arguments:** + - *options*: an optional {{MLHardSigmoidOptions}}. The optional parameters of the operation. + + **Returns:** + - an {{MLActivation}}. The activation function representing the hard sigmoid operation.++ ++ ### The hardSwish() method ### {#api-mlgraphbuilder-hard-swish} Computes the nonlinear function `y = x * max(0, min(6, (x + 3))) / 6` that is introduced by [[MobileNetV3]] on the input tensor element-wise. -+ The hardSigmoid(|options|) method steps are: +
++ 1. Let |op| be the result of creating an MLActivation given [=this=], `"hardSigmoid"` and |options|. + 1. If that [=exception/throws=] an error, re-[=exception/throw=] the error. + 1. Return |op|. ++- **Arguments:** - - *x*: an {{MLOperand}}. The input tensor. - - **Returns:** - - an {{MLOperand}}. The output tensor of the same shape as *x*. - - an {{MLActivation}}. The activation function representing the hard-swish operation. -++#### The {{MLGraphBuilder/hardSwish(input)}} method #### {#api-mlgraphbuilder-hardswish-input} +++ ++The behavior of this operation can be generically emulated from the usage of other operations as follow. However, user agents typically have a more efficient implementation for it, therefore its usage is encouraged from the performance standpoint. -
++return builder.div( builder.mul( x, @@ -2031,12 +3299,61 @@ partial interface MLGraphBuilder { builder.constant(6), builder.add(x, builder.constant(3))))), builder.constant(6)); --+ **Arguments:** + - *input*: an {{MLOperand}}. The input tensor. + + **Returns:** + - an {{MLOperand}}. The output tensor of the same shape as *input*. ++ ++ ++ +#### The {{MLGraphBuilder/hardSwish()}} method #### {#api-mlgraphbuilder-hardswish} ++ The hardSwish(|input|) method steps are: +
++ 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of copying an MLOperand given |input|. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the hard-swish operation. + 1. Store a reference of |opImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |opImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |opImpl|. + 1. Return |output|. +++ **Arguments:** + - None. + + **Returns:** + - an {{MLActivation}}. The activation function representing the hard-swish operation. ++ +++ ### The instanceNormalization() method ### {#api-mlgraphbuilder-instancenorm} Normalize the input features using [[Instance-Normalization]]. Unlike [[#api-mlgraphbuilder-batchnorm]] where the mean and variance values used in the calculation are previously computed across the batch dimension during the model training phase, the mean and variance values used in the calculation of an instance normalization are computed internally on the fly per input feature. + -+ The hardSwish() method steps are: +
++ 1. Let |op| be the result of creating an MLActivation given [=this=] and `"hardSwish"`. + 1. If that [=exception/throws=] an error, re-[=exception/throw=] the error. + 1. Return |op|. +++ +The {{MLInstanceNormalizationOptions}} members are: ++ : scale + :: + An {{MLOperand}}. Specifies the 1-D tensor of the scaling values whose [=list/size=] is equal to the number of channels, i.e. the size of the feature dimension of the input. For example, for an |input| tensor with `nchw` layout, the [=list/size=] is the value of |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[1]. + + : bias + :: + An {{MLOperand}}. Specifies the 1-D tensor of the bias values whose [=list/size=] is equal to the size of the feature dimension of the input. For example, for an |input| tensor with `nchw` layout, the len[=list/size=]gth is the value of |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[1]. + + : epsilon + :: + A {{float}} scalar. Specifies a small value to prevent computational error due to divide-by-zero. + + : layout + :: + An {{MLInputOperandLayout}}. Specifies the layout format of the input. + +
+ +**Arguments:** - *input*: an {{MLOperand}}. The input 4-D tensor. - *options*: an optional {{MLInstanceNormalizationOptions}}. The optional parameters of the operation. - - *scale*: an {{MLOperand}}. The 1-D tensor of the scaling values whose length is equal to the size of the feature dimension of the input e.g. for the input tensor with *nchw* layout, the feature dimension is 1. - - *bias*: an {{MLOperand}}. The 1-D tensor of the bias values whose length is equal to the size of the feature dimension of the input e.g. for the input tensor with *nchw* layout, the feature dimension is 1. - - *epsilon*: a {{float}} scalar. A small value to prevent computational error due to divide-by-zero. The default value is 0.00001 when not specified. - - *layout*: an {{MLInputOperandLayout}}. This option specifies the layout format of the input. The default value is *"nchw"*. - **Returns:** an {{MLOperand}}. The instance-normalized 4-D tensor of the same shape as the input tensor. + **Returns:** an {{MLOperand}}. The instance-normalized 4-D tensor of the same shape as *input*. +-+### The leakyRelu() method ### {#api-mlgraphbuilder-leakyrelu} Calculate the leaky version of rectified linear function on the input tensor element-wise. The calculation follows the expression `max(0, x) + alpha ∗ min(0, x)`. + -+ ++ ++ The instanceNormalization(|input|, |options|) method steps are: +
++ 1. [=Assert=]: the type of |input| is {{MLOperand}}. + 1. If the [=rank=] of |input| is not 4, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. [=Assert=]: the type of |options|.{{MLInstanceNormalizationOptions/scale}} is {{MLOperand}}. + 1. If the [=rank=] of |options|.{{MLInstanceNormalizationOptions/scale}} is not equal to the [=list/size=] of the channel dimension of |input|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. [=Assert=]: the type of |options|.{{MLInstanceNormalizationOptions/bias}} is {{MLOperand}}. + 1. If the [=rank=] of |options|.{{MLInstanceNormalizationOptions/bias}} is not equal to the [=list/size=] of the channel dimension of |input|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of copying an MLOperand given |input|. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the instance normalization operation, given |options|. + 1. Store a reference of |opImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |opImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |opImpl|. + 1. Return |output|. ++++ ++The behavior of this operation when the input tensor is 4-D of the *"nchw"* layout can be generically emulated from the usage of other operations as follow. However, user agents typically have a more efficient implementation for it, therefore its usage is encouraged from the performance standpoint. -
++// The mean reductions happen over the spatial dimensions of the input // e.g. axis 2 and 3 of the input tensor. const reduceOptions = { axes: [2,3], keepDimensions: true }; @@ -2092,46 +3455,100 @@ partial interface MLGraphBuilder { ), builder.reshape(options.bias, shape) ); --- **Arguments:** - - *x*: an {{MLOperand}}. The input tensor. - - *options*: an optional {{MLLeakyReluOptions}}. The optional parameters of the operation. - - *alpha*: a {{float}} scalar multiplier, default to 0.01. - - **Returns:** - - an {{MLOperand}}. The output tensor of the same shape as *x*. - - an {{MLActivation}}. The activation function representing the leaky relu operation. -++{{MLLeakyReluOptions}} has the following members: ++++The behavior of this operation can be generically emulated from the usage of other operations as follow. However, user agents typically have a more efficient implementation for it, therefore its usage is encouraged from the performance standpoint. +
return builder.add(builder.max(builder.constant(0), x), builder.mul(builder.constant(options.alpha), builder.min(builder.constant(0), x)));-+ : alpha + :: + A {{float}} scalar multiplier. + The default value is 0.01. +
+ +#### The {{MLGraphBuilder/leakyRelu(input, options)}} method #### {#api-mlgraphbuilder-leaky-relu-input-options} ++ **Arguments:** + - *input*: an {{MLOperand}}. The input tensor. + - *options*: an optional {{MLLeakyReluOptions}}. The optional parameters of the operation. + + **Returns:** + - an {{MLOperand}}. The output tensor of the same shape as *input*. ++ ++ ++ +#### The {{MLGraphBuilder/leakyRelu(options)}} method #### {#api-mlgraphbuilder-leaky-relu-options} ++ The leakyRelu(|input|, |options|) method steps are: +
++ 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of copying an MLOperand given |input|. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the Leaky RELU operation, given |options|. + 1. Store a reference of |opImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |opImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |opImpl|. + 1. Return |output|. +++ **Arguments:** + - *options*: an optional {{MLLeakyReluOptions}}. The optional parameters of the operation. + + **Returns:** + - an {{MLActivation}}. The activation function representing the leaky relu operation. ++ ++ ++ ### The linear() method ### {#api-mlgraphbuilder-linear} Calculate a linear function `y = alpha * x + beta` on the input tensor. + -+ The leakyRelu(|options|) method steps are: +
++ 1. Let |op| be the result of creating an MLActivation given [=this=], `"leakyRelu"` and |options|. + 1. If that [=exception/throws=] an error, re-[=exception/throw=] the error. + 1. Return |op|. ++- **Arguments:** - - *x*: an {{MLOperand}}. The input tensor. - - *options*: an optional {{MLLinearOptions}}. The optional parameters of the operation. - - *alpha*: a {{float}} scalar multiplier, default to 1. - - *beta*: a {{float}} scalar addition, default to 0. - - **Returns:** - - an {{MLOperand}}. The output tensor of the same shape as *x*. - - an {{MLActivation}}. The activation function representing the linear operation. -++ +{{MLLinearOptions}} has the following members: +++ ++The behavior of this operation can be generically emulated from the usage of other operations as follow. However, user agents typically have a more efficient implementation for it, therefore its usage is encouraged from the performance standpoint. +
return builder.add( builder.mul(x, builder.constant(options.alpha)), builder.constant(options.beta));-+ : alpha + :: + A {{float}} scalar multiplier. + The default value is 1. + : beta + :: + A {{float}} scalar addition. + The default value is 0. +
+ +#### The {{MLGraphBuilder/linear(input, options)}} method #### {#api-mlgraphbuilder-linear-input-options} ++ **Arguments:** + - *input*: an {{MLOperand}}. The input tensor. + - *options*: an optional {{MLLinearOptions}}. The optional parameters of the operation. + + **Returns:** + - an {{MLOperand}}. The output tensor of the same shape as *input*. ++ ++ ++ +#### The {{MLGraphBuilder/linear(options)}} method #### {#api-mlgraphbuilder-linear-options} ++ The linear(|input|, |options|) method steps are: +
++ 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of copying an MLOperand given |input|. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the linear operation, given |options|. + 1. Store a reference of |opImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |opImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |opImpl|. + 1. Return |output|. +++ **Arguments:** + - *options*: an optional {{MLLinearOptions}}. The optional parameters of the operation. + + **Returns:** + - an {{MLActivation}}. The activation function representing the linear operation.++ ++ ### The lstm() method ### {#api-mlgraphbuilder-lstm} Long Short-Term Memory [[LSTM]] recurrent network uses an input, output, forget, and cell gate to compute the output state that rolls into the output across the temporal sequence of the network. + -+ The linear(|options|) method steps are: +
++ 1. Let |op| be the result of creating an MLActivation given [=this=], `"linear"` and |options|. + 1. If that [=exception/throws=] an error, re-[=exception/throw=] the error. + 1. Return |op|. +++ +{{MLLstmOptions}} has the following members: ++ : bias + :: + An {{MLOperand}}. Specifies the 2-D input bias tensor of shape [numDirections, 4 * hiddenSize]. The ordering of the bias vectors in the second dimension of the tensor shape is specified according to {{MLLstmOptions/layout}}. + + : recurrentBias + :: + An {{MLOperand}}. Specifies the 2-D recurrent bias tensor of shape [numDirections, 4 * hiddenSize]. The ordering of the bias vectors in the first dimension of the tensor shape is specified according to {{MLLstmOptions/layout}}. + + : peepholeWeight + :: + An {{MLOperand}}. Specifies the 2-D weight tensor for peepholes of shape [numDirections, 3 * hiddenSize]. The pack ordering of the weight vectors is for the `input (i)`, `output (o)`, and `forget (f)` gate, respectively. + + : initialHiddenState + :: + An {{MLOperand}}. Specifies the 3-D initial hidden state tensor of shape [numDirections, batchSize, hiddenSize]. When not specified, implementations SHOULD use a tensor filled with zero. + + : initialCellState + :: + An {{MLOperand}}. Specifies the 3-D initial hidden state tensor of shape [numDirections, batchSize, hiddenSize]. When not specified, implementations SHOULD use a tensor filled with zero. + + : returnSequence + :: + A {{boolean}} indicating whether to also return the entire sequence with every output from each time step in it in addition to the output of the last time step. + + : direction + :: + An {{MLRecurrentNetworkDirection}}. Specifies the processing direction of the input sequence. When set to `"both"`, the size of the first dimension of the weight and the bias tensor shapes must be 2, and the input is processed in both directions. + + : layout + :: + An {{MLLstmWeightLayout}}. The ordering of the weight and bias vectors for the internal gates of LSTM, specifically the `input (i)`, `output (o)`, `forget (f)`, and `cell (g)` gate, as indicated in the first dimension of the weight and bias tensor shapes. When not specified, the default layout is `"iofg"`. + + : activations + :: + A sequence of {{MLActivation}}. A sequence of three activation functions, the first one is used for the `input (i)`, `forget (f)`, and `output (o)` gate, the second one is used for the `cell (g)` gate, and the last used for filtering the output cell state before combining it with the result of the output gate to form the output hidden state. When not specified, implementations SHOULD use the sequence of the sigmoid function (`"sigmoid"`) followed by two hyperbolic tangent functions (`"tanh"`) respectively. +
+ +**Arguments:** - - *input*: an {{MLOperand}}. The input 3-D tensor of shape [steps, batch_size, input_size]. - - *weight*: an {{MLOperand}}. The 3-D input weight tensor of shape [num_directions, 4 * hidden_size, input_size]. The ordering of the weight vectors in the second dimension of the tensor shape is specified according to the *options.layout* argument. - - *recurrentWeight*: an {{MLOperand}}. The 3-D recurrent weight tensor of shape [num_directions, 4 * hidden_size, hidden_size]. The ordering of the weight vectors in the second dimension of the tensor shape is specified according to the *options.layout* argument. + - *input*: an {{MLOperand}}. The input 3-D tensor of shape [steps, batchSize, inputSize]. + - *weight*: an {{MLOperand}}. The 3-D input weight tensor of shape [numDirections, 4 * hiddenSize, inputSize]. The ordering of the weight vectors in the second dimension of the tensor shape is specified according to the |options|.{{MLLstmOptions/layout}}. + - *recurrentWeight*: an {{MLOperand}}. The 3-D recurrent weight tensor of shape [numDirections, 4 * hiddenSize, hiddenSize]. The ordering of the weight vectors in the second dimension of the tensor shape is specified according to the |options|.{{MLLstmOptions/layout}} argument. - *steps*: an {{unsigned long}} scalar. The number of time steps in the recurrent network. The value must be greater than 0. - *hiddenSize*: an {{unsigned long}} scalar. The value of the third dimension of the cell output tensor shape. It indicates the number of features in the hidden state. - - *options*: an optional {{MLGruOptions}}. The optional parameters of the operation. - - *bias*: an {{MLOperand}}. The 2-D input bias tensor of shape [num_directions, 4 * hidden_size]. The ordering of the bias vectors in the second dimension of the tensor shape is specified according to the *options.layout* argument. - - *recurrentBias*: an {{MLOperand}}. The 2-D recurrent bias tensor of shape [num_directions, 4 * hidden_size]. The ordering of the bias vectors in the second dimension of the tensor shape is specified according to the *options.layout* argument. - - *peepholeWeight*: an {{MLOperand}}. The 2-D weight tensor for peepholes of shape [num_directions, 3 * hidden_size]. The pack ordering of the weight vectors is for the *input (i)*, *output (o)*, and *forget (f)* gate respectively. - - *initialHiddenState*: an {{MLOperand}}. The 3-D initial hidden state tensor of shape [num_directions, batch_size, hidden_size]. When not specified, it's assumed to be a tensor filled with zero. - - *initialCellState*: an {{MLOperand}}. The 3-D initial hidden state tensor of shape [num_directions, batch_size, hidden_size]. When not specified, it's assumed to be a tensor filled with zero. - - *returnSequence*: a {{boolean}} indicating whether to also return the entire sequence with every output from each time step in it in addition to the output of the last time step. Default to false. - - *direction*: an {{MLRecurrentNetworkDirection}}. The processing direction of the input sequence. When set to *"both"*, the size of the first dimension of the weight and the bias tensor shapes must be 2, and the input is processed in both directions. - - *layout*: an {{MLLstmWeightLayout}}. The ordering of the weight and bias vectors for the internal gates of LSTM, specifically the *input (i)*, *output (o)*, *forget (f)*, and *cell (g)* gate, as indicated in the second dimension of the weight and bias tensor shapes. When not specified, the default layout is *"iofg"*. - - *activations*: a sequence of {{MLActivation}}. A sequence of three activation functions, the first one is used for the *input (i)*, *forget (f)*, and *output (o)* gate, the second one is used for the *cell (g)* gate, and the last used for filtering the output cell state before combining it with the result of the output gate to form the output hidden state. When not specified, they are assumed to be of the sigmoid function (*"sigmoid"*) followed by two hyperbolic tangent functions (*"tanh"*) respectively. - - **Returns:** a sequence of {{MLOperand}}. The first element of the sequence is a 3-D tensor of shape [num_directions, batch_size, hidden_size], the output hidden state from the last time step of the network. The second element is a 3-D tensor of shape [num_directions, batch_size, hidden_size], the output cell state from the last time step of the network. Additionally, if *options.returnSequence* is set to true, the third element is the 4-D output tensor of shape [steps, num_directions, batch_size, hidden_size] containing every output from each time step in the temporal sequence. + - *options*: an optional {{MLLstmOptions}}. The optional parameters of the operation. -### The lstmCell() method ### {#api-mlgraphbuilder-lstmcell} @@ -2309,26 +3882,91 @@ partial interface MLGraphBuilder { optional MLLstmCellOptions options = {}); }; -+ **Returns:** a sequence of {{MLOperand}}. The first element of the sequence is a 3-D tensor of shape [numDirections, batchSize, hiddenSize], the output hidden state from the last time step of the network. The second element is a 3-D tensor of shape [numDirections, batchSize, hiddenSize], the output cell state from the last time step of the network. Additionally, if |options|.{{MLLstmOptions/returnSequence}} is set to true, the third element is the 4-D output tensor of shape [steps, numDirections, batchSize, hiddenSize] containing every output from each time step in the temporal sequence. ++ ++ ++ ++ The lstm(|input|, |weight|, |recurrentWeight|, |steps|, |hiddenSize|, |options|) method steps are: +
++ 1. Let |numDirections| be 1 if |options|.{{MLLstmOptions/direction}} is `"forward"`, or otherwise let it be 2. + 1. [=Assert=]: the type of |input|, |weight| and |recurrentWeight| is {{MLOperand}}. +++ The shape of |input|, |weight| or |recurrentWeight| could be also checked here. ++ 1. If |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[0] is not equal to |steps|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. Let |batchSize| be |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[1]. + 1. If |options|.{{MLLstmOptions/bias}} [=map/exists=]: + 1. [=Assert=]: its type is {{MLOperand}}. + 1. If its rank is not 2, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLLstmOptions/bias}}.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[0] is not |numDirections|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLLstmOptions/bias}}.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[1] is not 4 * |hiddenSize|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLLstmOptions/recurrentBias}} [=map/exists=]: + 1. [=Assert=]: its type is {{MLOperand}}. + 1. If its rank is not 2, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLLstmOptions/recurrentBias}}.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[0] is not |numDirections|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLLstmOptions/recurrentBias}}.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[1] is not 4 * |hiddenSize|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLLstmOptions/peepholeWeight}} [=map/exists=]: + 1. [=Assert=]: its type is {{MLOperand}}. + 1. If its rank is not 2, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLLstmOptions/peepholeWeight}}.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[0] is not |numDirections|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLLstmOptions/peepholeWeight}}.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[1] is not 4 * |hiddenSize|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLLstmOptions/initialHiddenState}} [=map/exists=]: + 1. [=Assert=]: its type is {{MLOperand}}. + 1. If its rank is not 3, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLLstmOptions/initialHiddenState}}.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[0] is not |numDirections|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLLstmOptions/initialHiddenState}}.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[1] is not equal to |batchSize|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLLstmOptions/initialHiddenState}}.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[2] is not |hiddenSize|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLLstmOptions/initialCellState}} [=map/exists=]: + 1. [=Assert=]: its type is {{MLOperand}}. + 1. If its rank is not 3, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLLstmOptions/initialCellState}}.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[0] is not |numDirections|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLLstmOptions/initialCellState}}.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[1] is not equal to |batchSize|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLLstmOptions/initialCellState}}.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[2] is not |hiddenSize|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLLstmOptions/activations}} [=map/exists=]: + 1. If its [=list/size=] is not 3, then [=exception/throw=] a {{TypeError}}. + 1. [=Assert=]: the type of its elements is {{MLActivation}}. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |desc| a new {{MLOperandDescriptor}}. + 1. Set |desc|.{{MLOperandDescriptor/dimensions}} to [ |numDirections|, |batchSize|, |hiddenSize| ]. + 1. Set |desc|.{{MLOperandDescriptor/type}} to |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/type}}. + 1. Let |output0| be the result of creating an MLOperand given [=this=] and |desc|. + 1. Let |output1| be the result of creating an MLOperand given [=this=] and |desc|. + 1. Set |desc|.{{MLOperandDescriptor/dimensions}} to [ |steps|, |numDirections|, |batchSize|, |hiddenSize| ]. + 1. If |options|.{{MLLstmOptions/returnSequence}} is set to true: + 1. Let |output2| be the result of creating an MLOperand given [=this=] and |desc|. + 1. Let |output| be the array [ |output0|, |output1|, |output2| ]. + 1. Otherwise, Let |output| be the array [ |output0|, |output1| ]. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the LSTM operation, given |weight|, |recurrentWeight|, |steps|, |hiddenSize| and |options|. + 1. Store a reference of |opImpl| in |output0|.{{MLOperand/[[operator]]}}, |output1|.{{MLOperand/[[operator]]}} and |output2|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output0|.{{MLOperand/[[operand]]}}, |output1|.{{MLOperand/[[operand]]}} and |output2|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |opImpl|. + 1. Connect |output| as output to |opImpl|. + 1. Return |output|. +++ return (sequence ? [hiddenState, cellState, sequence] : [hiddenState, cellState]); + ++The behavior of this operation can be generically emulated from the usage of other operations as follow. However, user agents typically have a more efficient implementation for it, therefore its usage is encouraged from the performance standpoint. -
++const numDirections = (options.direction == "both" ? 2 : 1); let hiddenState = options.initialHiddenState; let cellState = options.initialCellState; @@ -2240,13 +3813,13 @@ partial interface MLGraphBuilder { let currentPeepholeWeight = []; for (let dir = 0; dir < numDirections; ++dir) { - currentWeight.push(builder.squeeze(builder.slice(weight, [dir, 0, 0], [1, 4 * hidden_size, input_size]), { axes: [0] })); - currentRecurrentWeight.push(builder.squeeze(builder.slice(recurrentWeight, [dir, 0, 0], [1, 4 * hidden_size, hidden_size]), { axes: [0] })); - currentBias.push(options.bias ? (builder.squeeze(builder.slice(options.bias, [dir, 0], [1, 4 * hidden_size]), { axes: [0] })) : null); + currentWeight.push(builder.squeeze(builder.slice(weight, [dir, 0, 0], [1, 4 * hiddenSize, inputSize]), { axes: [0] })); + currentRecurrentWeight.push(builder.squeeze(builder.slice(recurrentWeight, [dir, 0, 0], [1, 4 * hiddenSize, hiddenSize]), { axes: [0] })); + currentBias.push(options.bias ? (builder.squeeze(builder.slice(options.bias, [dir, 0], [1, 4 * hiddenSize]), { axes: [0] })) : null); currentRecurrentBias.push(options.recurrentBias ? - (builder.squeeze(builder.slice(options.recurrentBias, [dir, 0], [1, 4 * hidden_size]), { axes: [0] })) : null); + (builder.squeeze(builder.slice(options.recurrentBias, [dir, 0], [1, 4 * hiddenSize]), { axes: [0] })) : null); currentPeepholeWeight.push(options.peepholeWeight ? - (builder.squeeze(builder.slice(options.peepholeWeight, [dir, 0], [1, 3 * hidden_size]), { axes: [0] })) : null); + (builder.squeeze(builder.slice(options.peepholeWeight, [dir, 0], [1, 3 * hiddenSize]), { axes: [0] })) : null); } for (let step = 0; step < steps; ++step) { @@ -2256,13 +3829,13 @@ partial interface MLGraphBuilder { let nextCell = null; for (let dir = 0; dir < numDirections; ++dir) { - currentHidden.push(builder.squeeze(builder.slice(hiddenState, [dir, 0, 0], [1, batch_size, hidden_size]), { axes: [0] })); - currentCell.push(builder.squeeze(builder.slice(cellState, [dir, 0, 0], [1, batch_size, hidden_size]), { axes: [0] })); + currentHidden.push(builder.squeeze(builder.slice(hiddenState, [dir, 0, 0], [1, batchSize, hiddenSize]), { axes: [0] })); + currentCell.push(builder.squeeze(builder.slice(cellState, [dir, 0, 0], [1, batchSize, hiddenSize]), { axes: [0] })); } for (let dir = 0; dir < numDirections; ++dir) { let slice = (dir == 1 || options.direction == "backward" ? steps - step - 1 : step); - let currentInput = builder.squeeze(builder.slice(input, [slice, 0, 0], [1, batch_size, input_size]), { axes: [0] }); + let currentInput = builder.squeeze(builder.slice(input, [slice, 0, 0], [1, batchSize, inputSize]), { axes: [0] }); let results = builder.lstmCell( currentInput, currentWeight[dir], currentRecurrentWeight[dir], @@ -2286,9 +3859,9 @@ partial interface MLGraphBuilder { } } - return (sequence ? [hiddenState, cellState, sequence] : [hiddenState, cellState]); --+ +{{MLLstmCellOptions}} has the following members: ++ : bias + :: + An {{MLOperand}}. The 1-D input bias tensor of shape [4 * hiddenSize]. The ordering of the bias vectors in the first dimension of the tensor shape is specified according to the {{MLLstmCellOptions/layout}} argument. + + : recurrentBias + :: + An {{MLOperand}}. The 1-D recurrent bias tensor of shape [4 * hiddenSize]. The ordering of the bias vectors in the first dimension of the tensor shape is specified according to the {{MLLstmCellOptions/layout}} argument. + + : peepholeWeight + :: + An {{MLOperand}}. The 1-D weight tensor for peepholes of shape [3 * hiddenSize]. The pack ordering of the weight vectors is for the `input (i)`, `output (o)`, and `forget (f)` gate, respectively. + + : layout + :: + An {{MLLstmWeightLayout}}. The ordering of the weight and bias vectors for the internal gates of LSTM, specifically the `input (i)`, `output (o)`, `forget (f)`, and `cell (g)` gate, as indicated in the first dimension of the weight and bias tensor shapes. When not specified, the default layout is `"iofg"`. + + : activations + :: + A sequence of {{MLActivation}}. A sequence of three activation functions, the first one is used for the `input (i)`, `forget (f)`, and `output (o)` gate, the second one is used for the `cell (g)` gate, and the last used for filtering the output cell state before combining it with the result of the output gate to form the output hidden state. When not specified, they are assumed to be of the sigmoid function (`"sigmoid"`) followed by two hyperbolic tangent functions (`"tanh"`) respectively. +
+ +**Arguments:** - - *input*: an {{MLOperand}}. The input 2-D tensor of shape [batch_size, input_size]. - - *weight*: an {{MLOperand}}. The 2-D input weight tensor of shape [4 * hidden_size, input_size]. The ordering of the weight vectors in the first dimension of the tensor shape is specified according to the *options.layout* argument. - - *recurrentWeight*: an {{MLOperand}}. The 2-D recurrent weight tensor of shape [4 * hidden_size, hidden_size]. The ordering of the weight vectors in the first dimension of the tensor shape is specified according to the *options.layout* argument. - - *hiddenState*: an {{MLOperand}}. The 2-D input hidden state tensor of shape [batch_size, hidden_size]. - - *cellState*: an {{MLOperand}}. The 2-D input cell state tensor of shape [batch_size, hidden_size]. + - *input*: an {{MLOperand}}. The input 2-D tensor of shape [batchSize, inputSize]. + - *weight*: an {{MLOperand}}. The 2-D input weight tensor of shape [4 * hiddenSize, inputSize]. The ordering of the weight vectors in the first dimension of the tensor shape is specified according to the *options.layout* argument. + - *recurrentWeight*: an {{MLOperand}}. The 2-D recurrent weight tensor of shape [4 * hiddenSize, hiddenSize]. The ordering of the weight vectors in the first dimension of the tensor shape is specified according to the *options.layout* argument. + - *hiddenState*: an {{MLOperand}}. The 2-D input hidden state tensor of shape [batchSize, hiddenSize]. + - *cellState*: an {{MLOperand}}. The 2-D input cell state tensor of shape [batchSize, hiddenSize]. - *hiddenSize*: an {{unsigned long}} scalar. The value of the second dimension of the output tensor shape. It indicates the number of features in the hidden state. - *options*: an optional {{MLLstmCellOptions}}. The optional parameters of the operation. - - *bias*: an {{MLOperand}}. The 1-D input bias tensor of shape [4 * hidden_size]. The ordering of the bias vectors in the first dimension of the tensor shape is specified according to the *options.layout* argument. - - *recurrentBias*: an {{MLOperand}}. The 1-D recurrent bias tensor of shape [4 * hidden_size]. The ordering of the bias vectors in the first dimension of the tensor shape is specified according to the *options.layout* argument. - - *peepholeWeight*: an {{MLOperand}}. The 1-D weight tensor for peepholes of shape [3 * hidden_size]. The pack ordering of the weight vectors is for the *input (i)*, *output (o)*, and *forget (f)* gate respectively. - - *layout*: an {{MLLstmWeightLayout}}. The ordering of the weight and bias vectors for the internal gates of LSTM, specifically the *input (i)*, *output (o)*, *forget (f)*, and *cell (g)* gate, as indicated in the first dimension of the weight and bias tensor shapes. When not specified, the default layout is *"iofg"*. - - *activations*: a sequence of {{MLActivation}}. A sequence of three activation functions, the first one is used for the *input (i)*, *forget (f)*, and *output (o)* gate, the second one is used for the *cell (g)* gate, and the last used for filtering the output cell state before combining it with the result of the output gate to form the output hidden state. When not specified, they are assumed to be of the sigmoid function (*"sigmoid"*) followed by two hyperbolic tangent functions (*"tanh"*) respectively. - **Returns:** a sequence of {{MLOperand}}. The first element of the sequence is the output hidden state of the current time step of the recurrent network. The following element is the output cell state. Both elements are 2-D tensors of shape [batch_size, hidden_size]. + **Returns:** a sequence of {{MLOperand}}. The first element of the sequence is the output hidden state of the current time step of the recurrent network. The following element is the output cell state. Both elements are 2-D tensors of shape [batchSize, hiddenSize]. ++ ++ +-+ The lstmCell(|input|, |weight|, |recurrentWeight|, |hiddenState|, |cellState|, |hiddenSize|, |options|) method steps are: +
++ 1. [=Assert=]: the type of |input|, |weight|, |recurrentWeight|, |hiddenState| and |cellState| is {{MLOperand}}. + 1. If the [=rank=] of |input|, |weight|, |recurrentWeight|, |hiddenState| or |cellState| is not 2, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. Let |batchSize| be |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[0]. + 1. If |options|.{{MLLstmCellOptions/bias}} [=map/exists=]: + 1. [=Assert=]: its type is {{MLOperand}}. + 1. If its rank is not 1, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLLstmCellOptions/bias}}.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[0] is not 4 * |hiddenSize|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLLstmCellOptions/recurrentBias}} [=map/exists=]: + 1. [=Assert=]: its type is {{MLOperand}}. + 1. If its rank is not 1, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLLstmCellOptions/recurrentBias}}.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[0] is not 4 * |hiddenSize|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLLstmCellOptions/peepholeWeight}} [=map/exists=]: + 1. [=Assert=]: its type is {{MLOperand}}. + 1. If its rank is not 1, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLLstmCellOptions/peepholeWeight}}.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[0] is not 3 * |hiddenSize|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLLstmCellOptions/activations}} [=map/exists=]: + 1. If its [=list/size=] is not 3, then [=exception/throw=] a {{TypeError}}. + 1. [=Assert=]: the type of its elements is {{MLActivation}}. + 1. Let |desc| a new {{MLOperandDescriptor}}. + 1. Set |desc|.{{MLOperandDescriptor/dimensions}} to [ |batchSize|, |hiddenSize| ]. + 1. Set |desc|.{{MLOperandDescriptor/type}} to |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/type}}. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output0| be the result of creating an MLOperand given [=this=] and |desc|. + 1. Let |output1| be the result of creating an MLOperand given [=this=] and |desc|. + 1. Let |output| be the array [ |output0|, |output1| ]. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the LSTM cell operation, given |weight|, |recurrentWeight|, |hiddenState|, |cellState|, |hiddenSize| and |options|. + 1. Store a reference of |opImpl| in |output0|.{{MLOperand/[[operator]]}} and |output1|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output0|.{{MLOperand/[[operand]]}} and |output1|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |opImpl|. + 1. Connect |output| as output to |opImpl|. + 1. Return |output|. +++### The matmul() method ### {#api-mlgraphbuilder-matmul} @@ -2447,31 +4085,67 @@ partial interface MLGraphBuilder { MLOperand matmul(MLOperand a, MLOperand b); }; -++ ++The behavior of this operation can be generically emulated via other operations as shown below, when the weight layout is the default *"iofg"* layout, and the activation functions of the input/forget/output gate and the cell gate/the cell state's filter for the output hidden state are of the operator types *sigmoid* and *tanh* respectively. -
++const zero = builder.constant(0); // input gate (i) @@ -2346,11 +3984,11 @@ partial interface MLGraphBuilder { builder.add( builder.matmul( input, - builder.transpose(builder.slice(weight, [0, 0], [hiddenSize, input_size])) + builder.transpose(builder.slice(weight, [0, 0], [hiddenSize, inputSize])) ), builder.matmul( hiddenState, - builder.transpose(builder.slice(recurrentWeight, [0, 0], [hiddenSize, hidden_size])) + builder.transpose(builder.slice(recurrentWeight, [0, 0], [hiddenSize, hiddenSize])) ) ) ) @@ -2372,11 +4010,11 @@ partial interface MLGraphBuilder { builder.add( builder.matmul( input, - builder.transpose(builder.slice(weight, [2 * hiddenSize, 0], [hiddenSize, input_size])) + builder.transpose(builder.slice(weight, [2 * hiddenSize, 0], [hiddenSize, inputSize])) ), builder.matmul( hiddenState, - builder.transpose(builder.slice(recurrentWeight, [2 * hiddenSize, 0], [hiddenSize, hidden_size])) + builder.transpose(builder.slice(recurrentWeight, [2 * hiddenSize, 0], [hiddenSize, hiddenSize])) ) ) ) @@ -2393,11 +4031,11 @@ partial interface MLGraphBuilder { builder.add( builder.matmul( input, - builder.transpose(builder.slice(weight, [3 * hiddenSize, 0], [hiddenSize, input_size])) + builder.transpose(builder.slice(weight, [3 * hiddenSize, 0], [hiddenSize, inputSize])) ), builder.matmul( hiddenState, - builder.transpose(builder.slice(recurrentWeight, [3 * hiddenSize, 0], [hiddenSize, hidden_size])) + builder.transpose(builder.slice(recurrentWeight, [3 * hiddenSize, 0], [hiddenSize, hiddenSize])) ) ) ) @@ -2418,11 +4056,11 @@ partial interface MLGraphBuilder { builder.add( builder.matmul( input, - builder.transpose(builder.slice(weight, [hiddenSize, 0], [hiddenSize, input_size])) + builder.transpose(builder.slice(weight, [hiddenSize, 0], [hiddenSize, inputSize])) ), builder.matmul( hiddenState, - builder.transpose(builder.slice(recurrentWeight, [hiddenSize, 0], [hiddenSize, hidden_size])) + builder.transpose(builder.slice(recurrentWeight, [hiddenSize, 0], [hiddenSize, hiddenSize])) ) ) ) @@ -2436,8 +4074,8 @@ partial interface MLGraphBuilder { let ht = builder.mul(o, builder.tanh(ct)); return [ht, ct]; --+ +**Arguments:** - - *a*: an {{MLOperand}}. The first input N-D tensor. - - *b*: an {{MLOperand}}. The second input N-D tensor. + - *a*: an {{MLOperand}}. The first N-dimensional input tensor. + - *b*: an {{MLOperand}}. The second N-dimensional input tensor. - **Returns:** an {{MLOperand}}. The output N-D tensor that contains the matrix + **Returns:** an {{MLOperand}}. The output tensor that contains the matrix product of two input tensors. - - Compute the matrix product of two input tensors. It behaves as following: - - If both *a* and *b* are 2-D, they are multiplied like conventional - matrices and produce a 2-D tensor as the output. - - If either *a* or *b* is N-D, N > 2, it is treated as a stack of - matrices with dimensions corresponding to the last two indices. The - matrix multiplication will be broadcasted accordingly by following - [[!numpy-broadcasting-rule]]. The output is a N-D tensor whose rank - is the maximum rank of the input tensors. For each dimension, except - the last two, of the output tensor, its size is the maximum size - along that dimension of the input tensors. - - If *a* is 1-D, it is converted to a 2-D tensor by prepending a 1 to - its dimensions. - - If *b* is 1-D, it is converted to a 2-D tensor by by appending a 1 to - its dimensions. - - If both *a* and *b* are 1-D, the operation is a vector dot-product, - which produces a scalar output.++ Computes the matrix product of two input tensors as follows: + - If both *a* and *b* are 2-dimensional, they are multiplied like conventional + matrices and produce a 2-dimensional tensor as the output. + - If either *a* or *b* is `N`-dimensional where `N > 2`, it is treated as a stack of matrices with dimensions corresponding to the last two indices. The matrix multiplication will be broadcasted accordingly by following the [[!numpy-broadcasting-rule]]. The output is a `N`-dimensional tensor whose rank is the maximum [=rank=] of the input tensors. For each dimension, except the last two, of the output tensor, its size is the maximum size along that dimension of the input tensors. + - If *a* is 1-dimensional, it is converted to a 2-dimensional tensor by prepending a 1 to its dimensions. + - If *b* is 1-dimensional, it is converted to a 2-dimensional tensor by by appending a 1 to its dimensions. + - If both *a* and *b* are 1-dimensional, the operation is a vector dot-product, which produces a scalar output. ++ +++ ++ To calculate matmul output sizes, given |a| and |b| run the following steps: +
++ 1. Let |shapeA| be |a|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}} and |sizeA| the [=list/size=] of |shapeA|. + 1. Let |shapeB| be |b|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}} and |sizeB| the [=list/size=] of |shapeB|. + 1. If |sizeA| and |sizeB| is 1, return `« 1 »`. + 1. If |sizeA| is 1 and |sizeB| is not, then insert 1 in the front of |shapeA| to become [ 1 | |shapeA| ] and let |sizeA| be 2. + 1. If |shapeA|[0] is not equal to |shapeB|[|sizeB| - 2], then [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. If |sizeB| is 1 and |sizeA| is not, then append 1 to |shapeB| to become [ |shapeB| | 1 ] and let |sizeB| be 2. + 1. If |shapeA|[|sizeA| - 1] is not equal to |shapeB|[0], then [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |shape| be an array whose size |size| is the maximum of |sizeA| and |sizeB|. + 1. [=map/For each=] |index| in [=the range=] 0 to |size|, exclusive: + 1. Set |shape|[|index|] to the maximum of |shapeA|[|index|] and |shapeB|[|index|]. + 1. Return |shape|. +++ +### The pad() method ### {#api-mlgraphbuilder-pad} Inflate the tensor with constant or mirrored values on the edges. @@ -2495,21 +4169,76 @@ partial interface MLGraphBuilder { optional MLPadOptions options = {}); }; -+ The matmul(|a|, |b|) method steps are: +
++ 1. [=Assert=]: the type of |a| and |b| is {{MLOperand}}. + 1. Let |desc| a new {{MLOperandDescriptor}}. + 1. Set |desc|.{{MLOperandDescriptor/dimensions}} to the result of invoking the calculate matmul output sizes steps given |a| and |b|. + 1. If that throws an error, re-[=exception/throw=] the error. + 1. Set |desc|.{{MLOperandDescriptor/type}} to |a|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/type}}. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of creating an MLOperand given [=this=] and |desc|. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the matrix multiplication operation. + 1. Store a reference of |opImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |a|.{{MLOperand/[[operand]]}} and |b|.{{MLOperand/[[operand]]}} as inputs to |opImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |opImpl|. + 1. Return |output|. +++ +{{MLPadOptions}} has the following members: ++ : mode + :: + An {{MLPaddingMode}} [=string=]. + Specifies the different ways to pad the tensor. + The default value is `"constant"`. + + : value + :: + A {{float}}. + Specifies the padding value when {{MLPadOptions/mode}} is set to `"constant"`. + The default value is 0. +
+ +**Arguments:** - *input*: an {{MLOperand}}. The input tensor. - - *beginningPadding*: a sequence of {{unsigned long}}. The sequence of unsigned integer values indicating the number of padding values to add at the beginning of each input dimension, of length *N* where *N* is the rank of the input tensor. For each dimension *d* of *input*, *beginningPadding[d]* indicates how many values to add before the content in that dimension. - - *endingPadding*: a sequence of {{unsigned long}}. The sequence of unsigned integer values indicating the number of padding values to add at the ending of each input dimension, of length *N* where *N* is the rank of the input tensor. For each dimension *d* of *input*, *endingPadding[d]* indicates how many values to add after the content in that dimension. + - *beginningPadding*: a sequence of {{unsigned long}}. The sequence of unsigned integer values indicating the number of padding values to add at the beginning of each input dimension, of length *N* where *N* is the [=rank=] of the input tensor. For each dimension *d* of *input*, *beginningPadding[d]* indicates how many values to add before the content in that dimension. + - *endingPadding*: a sequence of {{unsigned long}}. The sequence of unsigned integer values indicating the number of padding values to add at the ending of each input dimension, of length *N* where *N* is the [=rank=] of the input tensor. For each dimension *d* of *input*, *endingPadding[d]* indicates how many values to add after the content in that dimension. - *options*: an optional {{MLPadOptions}}. The optional parameters of the operation. - - *mode*: an {{MLPaddingMode}}. The different ways to pad the tensor. When not set, it's assumed to be "constant". - - *value*: a {{float}}. The pad value when the *options.mode* is set to *"constant"*. When not set, it's assumed to be 0. **Returns:** an {{MLOperand}}. The padded output tensor. Each dimension of the output tensor can be calculated as follow: *output size = beginning padding + input size + ending padding* +--### Pooling operations ### {#api-mlgraphbuilder-pool2d} @@ -2573,34 +4302,12 @@ partial interface MLGraphBuilder { MLOperand maxPool2d(MLOperand input, optional MLPool2dOptions options = {}); }; -++++ ++ To calculate padding output sizes, given |input|, |beginningPadding| and |endingPadding|, run the following steps: +
++ 1. Let |shape| be a copy of |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}. + 1. For |index| in [=the range=] 0 to the [=rank=] of |shape|, exclusive: + 1. Add to |shape|[|index|] the value of |beginningPadding|[|index|]. + 1. Add to |shape|[|index|] the value of |endingPadding|[|index|]. + 1. Return |shape|. +++ ++ ++ The pad(|input|, |beginningPadding|, |endingPadding|, |options|) method steps are: +
++ 1. [=Assert=]: the type of |input| is {{MLOperand}}. + 1. If the [=list/size=] of |beginningPadding| and |endingPadding| is not equal to the [=rank=] of |input|, then then [=exception/throw=] a "{{TypeError}}". + 1. Let |desc| be a copy of |input|.{{MLOperand/[[descriptor]]}}. + 1. Set |desc|.{{MLOperandDescriptor/dimensions}} to the result of invoking the calculate padding output sizes steps given |input|, |beginningPadding| and |endingPadding|. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of creating an MLOperand given [=this=] and |desc|. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the padding operation, given |beginningPadding|, |endingPadding| and |options|. + 1. Store a reference of |opImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |opImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |opImpl|. + 1. Return |output|. ++++++ Examples for constant, edge, reflection and symmetric padding: +
+// input: [[1,2,3], [4,5,6]] const input = builder.constant( { type: 'float32', dimensions: [2,3] }, new Float32Array([1,2,3,4,5,6])); @@ -2544,8 +4273,8 @@ partial interface MLGraphBuilder { // [5,4,4,5,6,6,5], // [5,4,4,5,6,6,5]] builder.pad(input, beginningPadding, endingPadding, { mode: "symmetric" }); --+ +**Arguments:** - *input*: an {{MLOperand}}. The input 4-D tensor. The logical shape is interpreted according to the value of *options.layout*. - *options*: an optional {{MLPool2dOptions}}. The optional parameters of the operation. - - *windowDimensions*: a sequence of {{unsigned long}} of length 2. The dimensions of the sliding window, - [window_height, window_width]. If not present, the window dimensions are assumed to be the height - and width dimensions of the input shape. - - *padding*: a sequence of {{unsigned long}} of length 4. The additional rows and columns added to the beginning and ending of each spatial dimension of *input*, [beginning_height, ending_height, beginning_width, ending_width]. If not present, the values are assumed to be [0,0,0,0]. - - *strides*: a sequence of {{unsigned long}} of length 2. The stride of the - sliding window for each spatial dimension of *input*, - [stride_height, stride_width]. If not present, the values are assumed to be [1,1]. - - *dilations*: a sequence of {{unsigned long}} of length 2. The dilation factor - for each spatial dimension of *input*, [dilation_height, dilation_width]. - If not present, the values are assumed to be [1,1]. - - *autoPad*: an {{MLAutoPad}}. The automatic input padding options. By default, this argument is set to *"explicit"*, which means that the values in the *options.padding* array should be used for input padding. When the option is set other than *"explicit"*, the values in the *options.padding* array are ignored. With the *"same-upper"* option, the padding values are automatically computed such that the additional ending padding of the spatial input dimensions would allow all of the input values in the corresponding dimension to be filtered. The *"same-lower"* option is similar but padding is applied to the beginning padding of the spatial input dimensions instead of the ending one. - - *layout*: an {{MLInputOperandLayout}}. The default value is *"nchw"*. This option specifies the - layout format of the input and output tensor as follow: - - "nchw": - - input tensor: [batches, channels, height, width] - - output tensor: [batches, channels, height, width] - - "nhwc": - - input tensor: [batches, height, width, channels] - - output tensor: [batches, height, width, channels] - - *roundingType*: an {{MLRoundingType}}. The option specifies the rounding function used to compute the output shape. - - *outputSizes*: a sequence of {{unsigned long}} of length 2. The sizes of the two spacial dimensions of the output tensor. When the output sizes are explicitly specified, the options.roundingType is ignored. If not specified, the output sizes are automatically computed. **Returns:** an {{MLOperand}}. The output 4-D tensor that contains the result of the reduction. The logical shape is interpreted according to the @@ -2611,46 +4318,200 @@ partial interface MLGraphBuilder { or if *options.roundingType* is *"ceil"*: *output size = ceil(1 + (input size - filter size + beginning padding + ending padding) / stride)* +-++{{MLPool2dOptions}} has the following members: +A *global* pooling operation such as one for the max pooling operation is a variant of pooling where the window dimensions is the spatial dimensions (last two dimensions) of the input shape, as follow.// 'global' max pooling builder.maxPool2d(input);-+ : windowDimensions + :: + A sequence of {{unsigned long}} of length 2: [windowHeight, windowWidth]. + Specifies the dimensions of the sliding window. + The default value for the window dimensions are the height and width dimensions of the input shape. + + : padding + :: + A sequence of {{unsigned long}} of length 4: [beginningHeight, endingHeight, beginningWidth, endingWidth]. + Specifies the additional rows and columns added to the beginning and ending of each spatial dimension of the convolution input. + The default value is [0,0,0,0]. + + : strides + :: + A sequence of {{unsigned long}} of length 2: [strideHeight, strideWidth]. + Specifies the stride of the sliding window for each spatial dimension of the convolution input. + The default value is [1,1]. + + : dilations + :: + A sequence of {{unsigned long}} of length 2: [dilationHeight, dilationWidth]. Specifies the dilation factor for each spatial dimension applied on the convolution filter (kernel). + The default value is [1,1]. + + : autoPad + :: + An {{MLAutoPad}} [=string=]. + Specifies the automatic input padding options. + The default value is *"explicit"*, which means that the values in the {{MLPool2dOptions/padding}} array should be used for input padding. + When the option is set other than *"explicit"*, the values in the {{MLPool2dOptions/padding}} array are ignored. + + With the *"same-upper"* option, the padding values are automatically computed such that the additional ending padding of the spatial input dimensions would allow all of the input values in the corresponding dimension to be filtered. + + The *"same-lower"* option is similar but padding is applied to the beginning padding of the spatial input dimensions instead of the ending one. + + : layout + :: + An {{MLInputOperandLayout}} [=string=]. + Specifies the layout format of the input and output tensor as follows: + - **"nchw"** + - input tensor: *[batches, inputChannels, height, width]* + - output tensor: *[batches, outputChannels, height, width]* + - **"nhwc"**: + - input tensor: *[batches, height, width, inputChannels]* + - output tensor: *[batches, height, width, outputChannels]* + The default value is *"nchw"*. + + : roundingType + :: + An {{MLRoundingType}} [=string=]. + Specifies the rounding function used to compute the output shape. + + : outputSizes + :: + A sequence of {{unsigned long}} of length 2. + Specifies the sizes of the two spacial dimensions of the output tensor. When the output sizes are explicitly specified, the {{MLPool2dOptions/roundingType}} is ignored. + + If not specified, the output sizes are automatically computed. + +
+ ++ ++ ++ To create pooling operation given |op|, |input| and |options|, run the following steps: +
++ 1. [=Assert=]: |op| is one of "averagePool2d", "l2Pool2d", "maxPool2d". + 1. [=Assert=]: the type of |input| is {{MLOperand}}. + 1. If the [=list/size=] of |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}} is not 4, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLPool2dOptions/windowDimensions}} [=map/exists=] and its [=list/size=] is not 2, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. Otherwise, set |options|.{{MLPool2dOptions/windowDimensions}} to the height and width dimensions of the shape of |input|. + 1. If |options|.{{MLPool2dOptions/outputSizes}} [=map/exists=], or if |options|.{{MLPool2dOptions/padding}} does not [=map/exist=], set |options|.{{MLPool2dOptions/padding}} to `« 0, 0, 0, 0 »`. + 1. If the len[=list/size=]gth of |options|.{{MLPool2dOptions/padding}} is not 4, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLPool2dOptions/strides}} does not [=map/exist=], set |options|.{{MLPool2dOptions/strides}} to `« 1, 1 »`. + 1. If the [=list/size=] of |options|.{{MLPool2dOptions/strides}} is not 2, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If any value in |options|.{{MLPool2dOptions/strides}} is not greater than 0, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLPool2dOptions/outputSizes}} [=map/exists=]: + 1. If the [=list/size=] of |options|.{{MLPool2dOptions/outputSizes}} is not 2, then [=exception/throw=] a {{TypeError}}. + 1. If the elements of |options|.{{MLPool2dOptions/outputSizes}} are not smaller than the elements at the same dimension (index) for |options|.{{MLPool2dOptions/strides}}, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLPool2dOptions/dilations}} does not [=map/exist=], set |options|.{{MLPool2dOptions/dilations}} to `« 1, 1 »`. + 1. If the [=list/size=] of |options|.{{MLPool2dOptions/dilations}} is not 2, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If any value in |options|.{{MLPool2dOptions/dilations}} is not greater than 0, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If |options|.{{MLPool2dOptions/autoPad}} is not `"explicit"`, set |options|.{{MLPool2dOptions/padding}} to `« 0, 0, 0, 0 »`. + 1. Let |desc| be a copy of |input|.{{MLOperand/[[descriptor]]}}. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Make a request to the underlying platform to: + 1. Calculate the output dimensions given |input| and |options|. Let |desc|.{{MLOperandDescriptor/dimensions}} be the result of that. + 1. Let |output| be the result of creating an MLOperand given [=this=] and |desc|. + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the |op| pooling operation, given |options|. + 1. Store a reference of |opImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |opImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |opImpl|. + 1. Return |output|. ++++ ### The prelu() method ### {#api-mlgraphbuilder-prelu} -Calculate the parametric version of rectified linear function (Parametric Relu) on the input tensor element-wise. Parametric Relu is a type of leaky ReLU that, instead of having a scalar slope like 0.01, making the slope (coefficient of leakage) into a parameter that is learned during the model training phase of this operation. The calculation follows the expression `max(0, x) + slope ∗ min(0, x)`. +Calculate the parametric version of rectified linear function (Parametric ReLU) on the input tensor element-wise. Parametric ReLU is a type of leaky ReLU that, instead of having a scalar slope like 0.01, making the slope (coefficient of leakage) into a parameter that is learned during the model training phase of this operation. The calculation follows the expression `max(0, x) + slope ∗ min(0, x)`. -+ The following pooling algorithms are supported. +
++ The averagePool2d(|input|, |options|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/pooling-op | create pooling operation=] given `"averagePool2d"`, |input| and |options|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. ++ ++ The l2Pool2d(|input|, |options|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/pooling-op | create pooling operation=] given `"l2Pool2d"`, |input| and |options|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. ++ ++ The maxPool2d(|input|, |options|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/pooling-op | create pooling operation=] given `"maxPool2d"`, |input| and |options|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. +++ +**Arguments:** - - *x*: an {{MLOperand}}. The input tensor. - - *slope*: an {{MLOperand}}. The slope tensor. Its shape is either the same as, or unidirectionally broadcastable to the shape of input tensor *x* according to [[!numpy-broadcasting-rule]]. + - *input*: an {{MLOperand}}. The input tensor. + - *slope*: an {{MLOperand}}. The slope tensor. Its shape is either the same as, or unidirectionally broadcastable to the shape of input tensor *input* according to [[!numpy-broadcasting-rule]]. **Returns:** - - an {{MLOperand}}. The output tensor of the same shape as *x*. + - an {{MLOperand}}. The output tensor of the same shape as *input*. +-+- ### Reduction operations ### {#api-mlgraphbuilder-reduce} -Reduce the input along the dimensions given in *axes*. +Reduce the input tensor along all dimensions, or along the axes specified in the {{MLReduceOptions/axes}} array parameter. For each specified axis, the dimension with that index is reduced, i.e. the resulting tensor will not contain it, unless the {{MLReduceOptions/keepDimensions}} option is specified. The values of the resulting tensor are calculated using the specified reduction function that takes as parameters all the values across the reduced dimension. -+ ++ ++ The prelu(|input|, |slope|) method steps are: +
++ 1. [=Assert=]: the type of |input| and |slope| is {{MLOperand}}. + 1. Let |descriptor| be a new {{MLOperandDescriptor}}. + 1. Set |descriptor|.{{MLOperandDescriptor/type}} to |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/type}}. + 1. Let |descriptor|.{{MLOperandDescriptor/dimensions}} be the result of running the [=MLGraphBuilder/broadcast-shapes=] steps given |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}} and |slope|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}. + 1. If that [=exception/throws=] an error, re-[=exception/throw=] the error. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of creating an MLOperand given [=this=] and |descriptor|. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the PreLU operation, given |slope|. + 1. Store a reference of |opImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |opImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |opImpl|. + 1. Return |output|. +++++The behavior of this operation can be generically emulated from the usage of other operations as follow. However, user agents typically have a more efficient implementation for it, therefore its usage is encouraged from the performance standpoint. +
return builder.add(builder.max(builder.constant(0), x), builder.mul(slope, builder.min(builder.constant(0), x)));-+ +**Arguments:** - *input*: an {{MLOperand}}. The input tensor. - *options*: an optional {{MLReduceOptions}}. The optional parameters of the operation. - - *axes*: a sequence of {{unsigned long}}. The dimensions to reduce. The values in the sequence must be in the range [0, N-1] where N is the rank of input tensor. + - *axes*: a sequence of {{unsigned long}}. The dimensions to reduce. The values in the sequence must be in the range [0, N-1] where N is the [=rank=] of the input tensor. If not present, all dimensions are reduced. - - *keepDimensions*: a {{boolean}}. If true, retains reduced dimensions with size of 1. + - *keepDimensions*: a {{boolean}}. If true, retains reduced dimensions with [=list/size=] 1. The default value is false. **Returns:** an {{MLOperand}}. The reduced output tensor. ++**Reduction types:** - *L1*: Compute the L1 norm of all the input values along the axes. - *L2*: Compute the L2 norm of all the input values along the axes. @@ -2694,34 +4558,177 @@ partial interface MLGraphBuilder { - *SumSquare*: Compute the sum of the square of all the input values along the axes.-### The relu() method ### {#api-mlgraphbuilder-relu} ++ ++ ++ To create reduce operation given |op|, |input| and |options|, run the following steps: +
++ 1. [=Assert=]: |op| is one of "reduceL1", "reduceL2", "reduceLogSum", "reduceLogSumExp", "reduceMax", "reduceMean", "reduceMin", "reduceProduct", "reduceSum", "reduceSumSquare". + 1. [=Assert=]: the type of |input| is {{MLOperand}}. + 1. If |options|.{{MLReduceOptions/axes}} [=map/exists=], if any of its elements is not in [=the range=] 0 to the [=rank=] of |input|, exclusive, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of copying an MLOperand given |input|. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the |op| reduce operation, given |options|. + 1. Store a reference of |opImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |opImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |opImpl|. + 1. Return |output|. ++++ +### The relu() method ### {#api-mlgraphbuilder-relu-method} Compute the rectified linear function of the input tensor. + -+ The following reduce algorithms are supported. +
++ The reduceL1(|input|, |options|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/reduce-op | create reduce operation=] given "reduceL1", |input| and |options|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. ++ ++ The reduceL2(|input|, |options|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/reduce-op | create reduce operation=] given "reduceL2", |input| and |options|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. ++ ++ The reduceLogSum(|input|, |options|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/reduce-op | create reduce operation=] given "reduceLogSum", |input| and |options|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. ++ ++ The reduceLogSumExp(|input|, |options|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/reduce-op | create reduce operation=] given "reduceLogSumExp", |input| and |options|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. ++ ++ The reduceMax(|input|, |options|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/reduce-op | create reduce operation=] given "reduceMax", |input| and |options|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. ++ ++ The reduceMean(|input|, |options|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/reduce-op | create reduce operation=] given "reduceMean", |input| and |options|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. ++ ++ The reduceMin(|input|, |options|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/reduce-op | create reduce operation=] given "reduceMin", |input| and |options|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. ++ ++ The reduceProduct(|input|, |options|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/reduce-op | create reduce operation=] given "reduceProduct", |input| and |options|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. ++ ++ The reduceSum(|input|, |options|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/reduce-op | create reduce operation=] given "reduceSum", |input| and |options|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. ++ ++ The reduceSumSquare(|input|, |options|) method steps are: + 1. Let |output| be the result of running the [=MLGraphBuilder/reduce-op | create reduce operation=] given "reduceSumSquare", |input| and |options|. + 1. If that [=exception/throws=] an error, then re-[=exception/throw=] the error. + 1. Return |output|. ++- **Arguments:** - - *x*: an {{MLOperand}}. The input tensor. - - **Returns:** - - an {{MLOperand}}. The output tensor of the same shape as *x*. - - an {{MLActivation}}. The activation function representing the relu operation. -++ +#### The {{MLGraphBuilder/relu(input)}} method #### {#api-mlgraphbuilder-relu-input} +++ ++The behavior of this operation can be generically emulated from the usage of other operations as follow. However, user agents typically have a more efficient implementation for it, therefore its usage is encouraged from the performance standpoint. +
return builder.max(builder.constant(0), x);-+ **Arguments:** + - *input*: an {{MLOperand}}. The input tensor. + + **Returns:** + - an {{MLOperand}}. The output tensor of the same shape as *input*. ++ ++ ++ +#### The {{MLGraphBuilder/relu()}} method #### {#api-mlgraphbuilder-relu} ++ The relu(|input|) method steps are: +
++ 1. [=Assert=]: the type of |input| is {{MLOperand}}. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of copying an MLOperand given |input|. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the ReLU operation. + 1. Store a reference of |opImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |opImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |opImpl|. + 1. Return |output|. +++ **Arguments:** + - None. + + **Returns:** + - an {{MLActivation}}. The activation function representing the relu operation.-### The resample2d() method ### {#api-mlgraphbuilder-resample2d} +++ +### The resample2d() method ### {#api-mlgraphbuilder-resample2d-method} Resample the tensor values from the source to the destination spatial dimensions according to the scaling factors. -+ The relu() method steps are: +
++ 1. Let |op| be the result of creating an MLActivation given [=this=] and `"relu"`. + 1. If that [=exception/throws=] an error, re-[=exception/throw=] the error. + 1. Return |op|. +++**Arguments:** - *input*: an {{MLOperand}}. The input 4-D tensor. - *options*: an optional {{MLResample2dOptions}}. The optional parameters of the operation. - - *mode*: an {{MLInterpolationMode}}. The interpolation algorithm used to fill the output tensor values. - If not set, it is assumed to be the *Nearest Neighbor* interpolation. - - *scales*: a sequence of {{float}} of length 2. Each value represents the scaling factor used to scale in each spatial dimensions of input, [scale_height, scale_width]. If not set, the values are assumed to be [1.0, 1.0]. - - *sizes*: a sequence of {{unsigned long}} of length 2. The target sizes for each spatial dimensions of input, [size_height, size_width]. When the target sizes are specified, the *options.scales* argument is ignored as the scaling factor values are derived from the target sizes of each spatial dimension of input. - - *axes*: a sequence of {{unsigned long}} of length 2. The two consecutive dimensions of the input tensor to which the interpolation algorithm applies. The valid values in the sequence are [0, 1], [1, 2] or [2, 3]. When not specified, the sequence is assumed to be [2, 3]. **Returns:** an {{MLOperand}}. The output 4-D tensor.-### The reshape() method ### {#api-mlgraphbuilder-reshape} +{{MLResample2dOptions}} has the following members: ++ : mode + :: + An {{MLInterpolationMode}} [=string=]. + Specifies the interpolation algorithm used to fill the output tensor values. + The default value is `"nearest-neighbor"`, standing for *Nearest Neighbor* interpolation. + + : scales + :: + A sequence of {{float}} of length 2. + Specifies the scaling factor in each spatial dimensions of the input: [scaleHeight, scaleWidth]. + The default value is [1.0, 1.0]. + + : sizes + :: + A sequence of {{unsigned long}} of length 2. + Specifies the target sizes for each spatial dimensions of the input: [sizeHeight, sizeWidth]. When the target sizes are specified, the {{MLResample2dOptions/scales}} argument is ignored, since the scaling factor values are derived from the target sizes of each spatial dimension of the input. + + : axes + :: + A sequence of {{unsigned long}} of length 2. + Specifies the two consecutive dimensions of the input tensor to which the interpolation algorithm applies. The valid values in the sequence are [0, 1], [1, 2] or [2, 3]. + The default value is [2, 3]. +
+ ++ ++ ++ To check resample options given |options|, run the following steps: +
++ 1. If |options|.{{MLResample2dOptions/scales}} does not [=map/exist=], set it to to `« 1.0, 1.0 »`. + 1. Otherwise, if any of its values is not greater than 0, or if its [=list/size=] is not 2, return false. + 1. If |options|.{{MLResample2dOptions/sizes}} [=map/exists=], and if its size is not 2, or if any of its values is not greater than 0, return false. + 1. If |options|.{{MLResample2dOptions/axes}} does not [=map/exists=], set it to `« 2, 3 »`. + 1. Otherwise, if its value is not one of `« 0, 1», « 1, 2», « 2, 3 »`, return false. + 1. Return true. +++ ++ ++ To resample output sizes given |input| and |options|, run the following steps: +
++ 1. Let |desc| be an {{MLOperandDescriptor}} initialized to |input|.{{MLOperand/[[descriptor]]}}. + 1. For |index| in [=the range=] 0 to the [=list/size=] of |options|.{{MLResample2dOptions/axes}}, exclusive: + 1. If |options|.{{MLResample2dOptions/sizes}} [=map/exists=], set |desc|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[|options|.{{MLResample2dOptions/axes}}[|index|]] to |options|.{{MLResample2dOptions/sizes}}[|index|] and return |desc|. + 1. Otherwise, set |desc|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[|options|.{{MLResample2dOptions/axes}}[|index|]] to |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}[|index|] multiplied by |options|.{{MLResample2dOptions/scales}}. + 1. Return |desc|. +++ ++ +### The reshape() method ### {#api-mlgraphbuilder-reshape-method} Alter the shape of a tensor to a new shape. Reshape does not copy or change the content of the tensor. It just changes the tensor's logical dimensions for the subsequent operations. -+ The resample2d(|input|, |options|) method steps are: +
++ 1. If the [=list/size=] of |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}} is not 4, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If running the check resample options steps given |options| returns false, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. Let |desc| be the result of running the resample output sizes steps given |options|. + 1. If that [=exception/throws=] an error, re-[=exception/throw=] the error. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of creating an MLOperand given [=this=] and |desc|. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the resample 2D operation, given |options|. + 1. Store a reference of |opImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |opImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |opImpl|. + 1. Return |output|. +++**Arguments:** - *input*: an {{MLOperand}}. The input tensor. - - *newShape*: a sequence of {{nullable}} {{unsigned long}}. The shape of the output tensor. + - *newShape*: a sequence of [=nullable type|nullable=] {{unsigned long}}. The shape of the output tensor. The number of elements implied by *newShape* must be the same as the number of elements in the input tensor. Only one component of *newShape* can be the special value of `null`. The size of the dimension @@ -2775,27 +4855,55 @@ partial interface MLGraphBuilder { tensor is specified by the *newShape* argument.-### The sigmoid() method ### {#api-mlgraphbuilder-sigmoid} ++ ++ +### The sigmoid() method ### {#api-mlgraphbuilder-sigmoid-method} Compute the sigmoid function of the input tensor. The calculation follows the expression `1 / (exp(-x) + 1)`. -+ The reshape(|input|, |newShape|) method steps are: +
++ 1. [=Assert=]: the type of |input| is {{MLOperand}}. + 1. Let |outputShape| be an empty array of {{unsigned long}}. + 1. If |newShape| is a scalar [=number=], set |outputShape| to `« 1 »`. + 1. Otherwise, if |newShape| is an array of {{unsigned long}}: + 1. If the [=list/size=] of |newShape| is 0, set |outputShape| to `« 1 »` (reshaping to scalar). + 1. If |newShape| contains more than one `null` value, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If any value in |newShape| is 0, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. Let |inputElementCount| be the product of all elements in |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}. + 1. If |newShape| contains a `null` value, set that value to |inputElementCount| divided by the product of all other values in |newShape|. + 1. If that value is too large for {{unsigned long}}, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If product of all values in |newShape| is not equal to |inputElementCount|, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. Let |desc| be a copy of |input|.{{MLOperand/[[descriptor]]}}. + 1. Set |desc|.{{MLOperandDescriptor/dimensions}} to |newShape|. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of creating an MLOperand given [=this=] and |desc|. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the reshape operation. + 1. Store a reference of |opImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |opImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |opImpl|. + 1. Return |output|. ++- **Arguments:** - - *x*: an {{MLOperand}}. The input tensor. - - **Returns:** - - an {{MLOperand}}. The output tensor of the same shape as *x*. - - an {{MLActivation}}. The activation function representing the sigmoid operation. -++ +#### The {{MLGraphBuilder/sigmoid(input)}} method #### {#api-mlgraphbuilder-sigmoid-input} +++ ++The behavior of this operation can be generically emulated from the usage of other operations as follow. However, user agents typically have a more efficient implementation for it, therefore its usage is encouraged from the performance standpoint. +
return builder.div( builder.constant(1), @@ -2803,9 +4911,58 @@ partial interface MLGraphBuilder { builder.exp(builder.neg(x)), builder.constant(1)));-+ **Arguments:** + - *input*: an {{MLOperand}}. The input tensor. + + **Returns:** + - an {{MLOperand}}. The output tensor of the same shape as *input*. ++ ++ ++ +#### The {{MLGraphBuilder/sigmoid()}} method #### {#api-mlgraphbuilder-sigmoid} ++ The sigmoid(|input|) method steps are: +
++ 1. [=Assert=]: the type of |input| is {{MLOperand}}. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of copying an MLOperand given |input|. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the sigmoid operation. + 1. Store a reference of |opImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |opImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |opImpl|. + 1. Return |output|. +++ **Arguments:** + - None. + + **Returns:** + - an {{MLActivation}}. The activation function representing the sigmoid operation.+++ ### The slice() method ### {#api-mlgraphbuilder-slice} Produce a slice of the input tensor. -+ The sigmoid() method steps are: +
++ 1. Let |op| be the result of creating an MLActivation given [=this=] and `"sigmoid"`. + 1. If that [=exception/throws=] an error, re-[=exception/throw=] the error. + 1. Return |op|. +++**Arguments:** - *input*: an {{MLOperand}}. The input tensor. - - *starts*: a sequence of {{unsigned long}}. The sequence of unsigned integer values indicating the starting index to slice of each input dimension, of length N where N is the rank of the input tensor. For each dimension *d* of *input*, *starts[d]* indicates the starting index to slice in that dimension. The starting index must be in the range [0, input size - 1] in that dimension. - - *sizes*: a sequence of {{unsigned long}}. The sequence of unsigned integer values indicating the number of elements to slice of each input dimension, of length N where N is the rank of the input tensor. For each dimension *d* of *input*, *sizes[d]* indicates the number of elements to slice in that dimension. The size must not be 0 and must satisfy the constraint *starting index + size <= input size* in that dimension. + - *starts*: a sequence of {{unsigned long}}. The sequence of unsigned integer values indicating the starting index to slice of each input dimension, of length N where N is the [=rank=] of the input tensor. For each dimension *d* of *input*, *starts[d]* indicates the starting index to slice in that dimension. The starting index must be in the range [0, input size - 1] in that dimension. + - *sizes*: a sequence of {{unsigned long}}. The sequence of unsigned integer values indicating the number of elements to slice of each input dimension, of length N where N is the [=rank=] of the input tensor. For each dimension *d* of *input*, *sizes[d]* indicates the number of elements to slice in that dimension. The size must not be 0 and must satisfy the constraint *starting index + size <= input size* in that dimension. **Returns:** an {{MLOperand}}. The output tensor of the same rank as the input tensor with tensor values stripped to the specified starting and ending indices in each dimension.-### The softmax() method ### {#api-mlgraphbuilder-softmax} ++ ++ +### The softmax() method ### {#api-mlgraphbuilder-softmax-method} Compute the [softmax](https://en.wikipedia.org/wiki/Softmax_function) values of the 2-D input tensor along axis 1. -+ The slice(|input|, |starts|, |sizes|) method steps are: +
++ 1. [=Assert=]: the type of |input| is {{MLOperand}}. + 1. If |sizes|.size is 0, then [=exception/throw=] a {{TypeError}}. + 1. If the [=list/size=] of |starts| and |sizes| is not equal to the rank of |input|, then [=exception/throw=] a {{TypeError}}. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of copying an MLOperand given |input|. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the slice operation, given |starts| and |sizes|. + 1. Store a reference of |opImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |opImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |opImpl|. + 1. Return |output|. ++- **Arguments:** - - *x*: an {{MLOperand}}. The input 2-D tensor. - - **Returns:** - - an {{MLOperand}}. The output 2-D tensor that contains the softmax results, of the same shape as the input tensor. - - an {{MLActivation}}. The activation function representing the softmax operation. -++ +#### The {{MLGraphBuilder/softmax(input)}} method #### {#api-mlgraphbuilder-softmax-input} +++ + ++The behavior of this operation can be generically emulated from the usage of other operations as follow. However, user agents typically have a more efficient implementation for it, therefore its usage is encouraged from the performance standpoint. -
++// This sample deploys a well-known implementation trick [1] to compute the // exponentials of the distances to the max value, instead of the exponentials // of the input values itself, in order to increase the numerical stability of @@ -2853,11 +5028,61 @@ partial interface MLGraphBuilder { const max_x = builder.reduceMax(x, { axes: [1], keepDimensions: true }); const exp_x = builder.exp(builder.sub(x, max_x)); return builder.div(exp_x, builder.reduceSum(exp_x, { axes: [1], keepDimensions: true })); --+ **Arguments:** + - *input*: an {{MLOperand}}. The input 2-D tensor. + + **Returns:** + - an {{MLOperand}}. The output 2-D tensor that contains the softmax results, of the same shape as *input*. ++ ++ ++ +#### The {{MLGraphBuilder/softmax()}} method #### {#api-mlgraphbuilder-softmax} ++ The softmax(|input|) method steps are: +
++ 1. [=Assert=]: the type of |input| is {{MLOperand}}. + 1. If the [=list/size=] of |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}} is not 2, then [=exception/throw=] a "{{DataError}}" {{DOMException}}. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of copying an MLOperand given |input|. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the softmax operation. + 1. Store a reference of |opImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |opImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |opImpl|. + 1. Return |output|. +++ **Arguments:** + - None. + + **Returns:** + - an {{MLActivation}}. The activation function representing the softmax operation.-### The softplus() method ### {#api-mlgraphbuilder-softplus} +++ +### The softplus() method ### {#api-mlgraphbuilder-softplus-method} Compute the softplus function of the input tensor. The calculation follows the expression `ln(1 + exp(steepness * x)) / steepness`. -+ The softmax() method steps are: +
++ 1. Let |op| be the result of creating an MLActivation given and `"softmax"`. + 1. If that [=exception/throws=] an error, re-[=exception/throw=] the error. + 1. Return |op|. ++- **Arguments:** - - *x*: an {{MLOperand}}. The input tensor. - - **Returns:** - - an {{MLOperand}}. The output tensor of the same shape as *x*. - - an {{MLActivation}}. The activation function representing the softplus operation. -++ +{{MLSoftplusOptions}} has the following members: +++ ++The behavior of this operation can be generically emulated from the usage of other operations as follow. However, user agents typically have a more efficient implementation for it, therefore its usage is encouraged from the performance standpoint. +
return builder.div( builder.log( @@ -2890,36 +5111,139 @@ partial interface MLGraphBuilder { builder.constant(1))), builder.constant(options.steepness));-+ : steepness + :: + A {{float}} scalar parameter. + The default value is 1. +
+ +#### The {{MLGraphBuilder/softplus(input, options)}} method #### {#api-mlgraphbuilder-softplus-input-options} ++ **Arguments:** + - *input*: an {{MLOperand}}. The input tensor. + - *options*: an optional {{MLSoftplusOptions}}. The optional parameters of the operation. + + **Returns:** + - an {{MLOperand}}. The output tensor of the same shape as *input*. ++ ++ ++ +#### The {{MLGraphBuilder/softplus(options)}} method #### {#api-mlgraphbuilder-softplus-options} ++ The softplus(|input|, |options|) method steps are: +
++ 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of copying an MLOperand given |input|. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the softplus operation, given |options|. + 1. Store a reference of |opImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |opImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |opImpl|. + 1. Return |output|. +++ **Arguments:** + - *options*: an optional {{MLSoftplusOptions}}. The optional parameters of the operation. + + **Returns:** + - an {{MLActivation}}. The activation function representing the softplus operation.-### The softsign() method ### {#api-mlgraphbuilder-softsign} ++ ++ +### The softsign() method ### {#api-mlgraphbuilder-softsign-method} Compute the softsign function of the input tensor. The calculation follows the expression `x / (1 + |x|)`. -+ The softplus(|options|) method steps are: +
++ 1. Let |op| be the result of creating an MLActivation given [=this=], `"softplus"` and |options|. + 1. If that [=exception/throws=] an error, re-[=exception/throw=] the error. + 1. Return |op|. ++- **Arguments:** - - *x*: an {{MLOperand}}. The input tensor. - - **Returns:** - - an {{MLOperand}}. The output tensor of the same shape as *x*. - - an {{MLActivation}}. The activation function representing the softsign operation. -++ +#### The {{MLGraphBuilder/softsign(input)}} method #### {#api-mlgraphbuilder-softsign-input} +++ ++The behavior of this operation can be generically emulated from the usage of other operations as follow. However, user agents typically have a more efficient implementation for it, therefore its usage is encouraged from the performance standpoint. +
return builder.div(x, builder.add(builder.constant(1), builder.abs(x)));-+ **Arguments:** + - *input*: an {{MLOperand}}. The input tensor. + + **Returns:** + - an {{MLOperand}}. The output tensor of the same shape as *input*. ++ ++ ++ +#### The {{MLGraphBuilder/softsign()}} method #### {#api-mlgraphbuilder-softsign} ++ The softsign(|input|) method steps are: +
++ 1. [=Assert=]: the type of |input| is {{MLOperand}}. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of copying an MLOperand given |input|. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the softsign operation. + 1. Store a reference of |opImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |opImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |opImpl|. + 1. Return |output|. +++ **Arguments:** + - None. + + **Returns:** + - an {{MLActivation}}. The activation function representing the softsign operation.+++ ### The split() method ### {#api-mlgraphbuilder-split} Split the input tensor into a number of sub tensors along the given axis. -+ The softsign() method steps are: +
++ 1. Let |op| be the result of creating an MLActivation given [=this=] and `"softsign"`. + 1. If that [=exception/throws=] an error, re-[=exception/throw=] the error. + 1. Return |op|. +++ +**Arguments:** - *input*: an {{MLOperand}}. The input tensor. - *splits*: an {{unsigned long}} or a sequence of {{unsigned long}}. If an {{unsigned long}}, it specifies the number of output tensors along the axis. The number must evenly divide the dimension size of *input* along *options.axis*. If a sequence of {{unsigned long}}, it specifies the sizes of each output tensor along the *options.axis*. The sum of sizes must equal to the dimension size of *input* along *options.axis*. - *options*: an optional {{MLSplitOptions}}. The optional parameters of the operation. - - *axis*: an {{unsigned long}} scalar. The dimension along which to split. Its value must be in the range [0, N-1] where N is the rank of input tensor. Default to 0. - **Returns:** a sequence of {{MLOperand}}. The splitted output tensors. If *splits* is an {{unsigned long}}, the length of the output sequence equals to *splits*. The shape of each output tensor is the same as *input* except the dimension size of *axis* equals to the quotient of dividing the dimension size of *input* along *axis* by *splits*. If *splits* is a sequence of {{unsigned long}}, the length of the output sequence equals to the length of *splits*. The shape of the i-th output tensor is the same as as *input* except along *axis* where the dimension size is *splits[i]*. + **Returns:** a sequence of {{MLOperand}}. The splitted output tensors. If *splits* is an {{unsigned long}}, the [=list/size=] of the output sequence equals to *splits*. The shape of each output tensor is the same as *input* except the dimension size of *axis* equals to the quotient of dividing the dimension size of *input* along *axis* by *splits*. If *splits* is a sequence of {{unsigned long}}, the [=list/size=] of the output sequence equals to the [=list/size=] of *splits*. The shape of the i-th output tensor is the same as as *input* except along *axis* where the dimension size is *splits[i]*. +-+{{MLSplitOptions}} has the following members: +### The squeeze() method ### {#api-mlgraphbuilder-squeeze} -Reduce the rank of a tensor by eliminating dimensions with size 1 of the tensor shape. Squeeze only affects the tensor's logical dimensions. It does not copy or change the content in the tensor. +Reduce the [=rank=] of a tensor by eliminating dimensions with size 1 of the tensor shape. Squeeze only affects the tensor's logical dimensions. It does not copy or change the content in the tensor. -+ : axis + :: + An {{unsigned long}} scalar. The dimension along which to split. Its value must be in the range [0, N-1] where N is the [=rank=] of the input tensor. + The default value is 0. +
+ ++ ++ ++ The split(|input|, |splits|, |options|) method steps are: +
++ 1. [=Assert=]: the type of |input| is {{MLOperand}}. + 1. If |splits| is an {{unsigned long}}, and |input|.{{MLOperandDescriptor/dimensions}}[|options|.{{MLSplitOptions/axis}}] % |splits| is not 0, then [=exception/throw=] a {{TypeError}}. + 1. If |splits| is a sequence of {{unsigned long}}, and the sum of its elements is not equal to |input|.{{MLOperandDescriptor/dimensions}}[|options|.{{MLSplitOptions/axis}}], then [=exception/throw=] a {{TypeError}}. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of copying an MLOperand given |input|. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the split operation, given |splits| and |options|. + 1. Store a reference of |opImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |opImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |opImpl|. + 1. Return |output|. ++++ ++The behavior of this operation can be generically emulated from the usage of other operations as follow. However, user agents typically have a more efficient implementation for it, therefore its usage is encouraged from the performance standpoint. -
++// This sample shows the case that the splits parameter is an array. const outputs = []; let starts = Array(input_rank).fill(0); @@ -2960,12 +5318,12 @@ partial interface MLGraphBuilder { start += size; } return outputs; --+ +**Arguments:** - *input*: an {{MLOperand}}. The input tensor. - *options*: an optional {{MLSqueezeOptions}}. The optional parameters of the operation. - - *axes*: a sequence of {{unsigned long}}. Indices to the shape dimensions of size 1 to eliminate. The values in the sequence must be in the range [0, N-1] where N is the rank of input tensor. When not specified, every shape dimensions of size 1 in the tensor are eliminated. **Returns:** an {{MLOperand}}. The output tensor of the same or reduced rank with the shape dimensions of size 1 eliminated.-### The tanh() method ### {#api-mlgraphbuilder-tanh} +{{MLSqueezeOptions}} has the following members: ++ : axes + :: + A sequence of {{unsigned long}}. + Specifies the indices to the shape dimensions of size 1 to eliminate. The values in the sequence must be in the range [0, N-1] where N is the [=rank=] of the input tensor. + When not specified, every shape dimensions of size 1 in the tensor are eliminated. +
+ ++ ++ +### The tanh() method ### {#api-mlgraphbuilder-tanh-method} Compute the hyperbolic tangent function of the input tensor. The calculation follows the expression `(exp(2 * x) - 1) / (exp(2 * x) + 1)`. -+ The squeeze(|input|, |options|) method steps are: +
++ 1. [=Assert=]: the type of |input| is {{MLOperand}}. + 1. If |options|.{{MLSqueezeOptions/axes}} [=map/exists=], then: + 1. Let |dimensions| be |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}. + 1. Let |axesLength| be the [=list/size=] of |options|.{{MLSqueezeOptions/axes}}. + 1. If |axesLength| is not smaller than the rank of |dimensions|, + 1. For |index| in [=the range=] 0 to |axesLength|, exclusive: + 1. Let |oneDimIndex| be |options|.{{MLSqueezeOptions/axes}}[|index|]. + 1. If |dimensions|[|oneDimIndex|] is not 1, then [=exception/throw=] a {{TypeError}}. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of copying an MLOperand given |input|. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the squeeze operation, given |options|. + 1. Store a reference of |opImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |opImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |opImpl|. + 1. Return |output|. ++- **Arguments:** - - *x*: an {{MLOperand}}. The input tensor. - **Returns:** - - an {{MLOperand}}. The output tensor of the same shape as *x*. - - an {{MLActivation}}. The activation function representing the tanh operation. - -++ +#### The {{MLGraphBuilder/tanh(input)}} method #### {#api-mlgraphbuilder-tanh-input} +++ ++The behavior of this operation can be generically emulated from the usage of other operations as follow. However, user agents typically have a more efficient implementation for it, therefore its usage is encouraged from the performance standpoint. +
return builder.div( builder.sub(builder.exp(builder.mul(builder.constant(2), x)), builder.constant(1)), builder.add(builder.exp(builder.mul(builder.constant(2), x)), builder.constant(1)));-+ **Arguments:** + - *input*: an {{MLOperand}}. The input tensor. + + **Returns:** + - an {{MLOperand}}. The output tensor of the same shape as *input*. ++ ++ ++ +#### The {{MLGraphBuilder/tanh()}} method #### {#api-mlgraphbuilder-tanh} ++ The tanh(|input|) method steps are: +
++ 1. [=Assert=]: the type of |input| is {{MLOperand}}. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of copying an MLOperand given |input|. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the hyperbolic tangent operation. + 1. Store a reference of |opImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |opImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |opImpl|. + 1. Return |output|. +++ **Arguments:** + - None. + + **Returns:** + - an {{MLActivation}}. The activation function representing the tanh operation.+++ ### The transpose() method ### {#api-mlgraphbuilder-transpose} Permute the dimensions of the input tensor according to the *permutation* argument. -+ The tanh() method steps are: +
++ 1. Let |op| be the result of creating an MLActivation given [=this=] and `"tanh"`. + 1. If that [=exception/throws=] an error, re-[=exception/throw=] the error. + 1. Return |op|. +++ +**Arguments:** - *input*: an {{MLOperand}}. The input N-D tensor. - *options*: an optional {{MLTransposeOptions}}. The optional parameters of the operation. - - *permutation*: a sequence of {{unsigned long}} values. The values used to permute the output shape. When it's not specified, it's set to [N-1, ..., 0], where N is the rank of the input tensor, e.g. [2,1,0] for a 3-D tensor. These default values cause the output to become a transposed tensor of the input. When specified, the number of values in the sequence must be the same as the rank of the input tensor, and the values in the sequence must be within the range from 0 to N-1 with no two or more same values found in the sequence. **Returns:** an {{MLOperand}}. The permuted or transposed N-D tensor.+{{MLTransposeOptions}} has the following members: ++ : permutation + :: + A sequence of {{unsigned long}} values. + Specifies the values used to permute the output shape. + The default value is [N-1, ..., 0], where N is the [=rank=] of the input tensor, e.g. [2,1,0] for a 3-D tensor. + These default values cause the output to become a transposed tensor of the input. When specified, the number of values in the sequence must be the same as the [=rank=] of the input tensor, and the values in the sequence must be within the range from 0 to N-1 with no two or more same values found in the sequence. +
+ +++ Examples {#examples} ===================== @@ -3044,49 +5517,54 @@ const context = await navigator.ml.createContext({powerPreference: 'low-power'})+ The transpose(|input|, |options|) method steps are: +
++ 1. [=Assert=]: the type of |input| is {{MLOperand}}. + 1. If |options|.{{MLTransposeOptions/permutation}} does not [=map/exist=], let |options|.{{MLTransposeOptions/permutation}} be the reversed sequence of all indices for |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}. + 1. Otherwise if |options|.{{MLTransposeOptions/permutation}} [=map/exists=]: + 1. If the [=rank=] of |options|.{{MLTransposeOptions/permutation}} is not the same as the [=rank=] of |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}}, then [=exception/throw=] a {{TypeError}}. + 1. If the values in |options|.{{MLTransposeOptions/permutation}} are not in [=the range=] 0 and the [=rank=] of |input|.{{MLOperand/[[descriptor]]}}.{{MLOperandDescriptor/dimensions}} exclusive, then [=exception/throw=] a {{TypeError}}. + 1. If the values in |options|.{{MLTransposeOptions/permutation}} contain duplicate value, then [=exception/throw=] a {{TypeError}}. + 1. If any of the following sub-steps fail, [=exception/throw=] an "{{OperationError}}" {{DOMException}}. + 1. Let |output| be the result of copying an MLOperand given |input|. + 1. Make a request to the underlying platform to: + 1. Let |opImpl| be an [=implementation-defined=] platform operator for the transpose operation, given |options|. + 1. Store a reference of |opImpl| in |output|.{{MLOperand/[[operator]]}}. + 1. Create an [=implementation-defined=] platform operand |outputImpl| to represent the output, given |output| and |opImpl|. + 1. Store a reference to |outputImpl| in |output|.{{MLOperand/[[operand]]}}. + 1. Connect |input|.{{MLOperand/[[operand]]}} as input to |opImpl|. + 1. Connect |output|.{{MLOperand/[[operand]]}} as output to |opImpl|. + 1. Return |output|. ++-The following code builds a graph as: +Given the following build graph:-constant1 ---+ - +--- Add ---> intermediateOutput1 ---+ -input1 ---+ | - +--- Mul---> output -constant2 ---+ | - +--- Add ---> intermediateOutput2 ---+ -input2 ---+ + constant1 ---+ + +--- Add ---> intermediateOutput1 ---+ + input1 ---+ | + +--- Mul---> output + constant2 ---+ | + +--- Add ---> intermediateOutput2 ---+ + input2 ---+--// Use tensors in 4 dimensions. -const TENSOR_DIMS = [1, 2, 2, 2]; -const TENSOR_SIZE = 8; ++++ The following code implements the graph: +
++ // Use tensors in 4 dimensions. + const TENSOR_DIMS = [1, 2, 2, 2]; + const TENSOR_SIZE = 8; -const builder = new MLGraphBuilder(context); + const builder = new MLGraphBuilder(context); -// Create MLOperandDescriptor object. -const desc = {type: 'float32', dimensions: TENSOR_DIMS}; + // Create MLOperandDescriptor object. + const desc = {type: 'float32', dimensions: TENSOR_DIMS}; -// constant1 is a constant MLOperand with the value 0.5. -const constantBuffer1 = new Float32Array(TENSOR_SIZE).fill(0.5); -const constant1 = builder.constant(desc, constantBuffer1); + // constant1 is a constant MLOperand with the value 0.5. + const constantBuffer1 = new Float32Array(TENSOR_SIZE).fill(0.5); + const constant1 = builder.constant(desc, constantBuffer1); -// input1 is one of the input MLOperands. Its value will be set before execution. -const input1 = builder.input('input1', desc); + // input1 is one of the input MLOperands. Its value will be set before execution. + const input1 = builder.input('input1', desc); -// constant2 is another constant MLOperand with the value 0.5. -const constantBuffer2 = new Float32Array(TENSOR_SIZE).fill(0.5); -const constant2 = builder.constant(desc, constantBuffer2); + // constant2 is another constant MLOperand with the value 0.5. + const constantBuffer2 = new Float32Array(TENSOR_SIZE).fill(0.5); + const constant2 = builder.constant(desc, constantBuffer2); -// input2 is another input MLOperand. Its value will be set before execution. -const input2 = builder.input('input2', desc); + // input2 is another input MLOperand. Its value will be set before execution. + const input2 = builder.input('input2', desc); -// intermediateOutput1 is the output of the first Add operation. -const intermediateOutput1 = builder.add(constant1, input1); + // intermediateOutput1 is the output of the first Add operation. + const intermediateOutput1 = builder.add(constant1, input1); -// intermediateOutput2 is the output of the second Add operation. -const intermediateOutput2 = builder.add(constant2, input2); + // intermediateOutput2 is the output of the second Add operation. + const intermediateOutput2 = builder.add(constant2, input2); -// output is the output MLOperand of the Mul operation. -const output = builder.mul(intermediateOutput1, intermediateOutput2); -+ // output is the output MLOperand of the Mul operation. + const output = builder.mul(intermediateOutput1, intermediateOutput2); +@@ -3098,24 +5576,28 @@ const graph = await builder.build({'output': output});-The following code executes the compiled graph. -# Appendices # {#appendices} @@ -3163,6 +5645,8 @@ Benjamin Poulain for their contributions to the API specification. Thanks to Sangwhan Moon and the W3C Technical Architecture Group for review of this specification for web architecture fit, design consistency and developer ergonomics. +Thanks to Zoltan Kis for adding algorithms and making navigating this specification a delightful experience. Thanks to Joshua Bell for aligning the specification with modern editorial conventions. Thanks to Ningxin Hu, Lisha Guo, Shiyi Zou, Mingming Xu, Junwei Fu, Bruce Dai and Bin Miao for careful review and comments. + Thanks to W3C Privacy Interest Group for privacy and security review and feedback. Thanks to Alex Gough and the Chrome Security team for security review and questions.-// Setup the input buffers with value 1. -const inputBuffer1 = new Float32Array(TENSOR_SIZE).fill(1); -const inputBuffer2 = new Float32Array(TENSOR_SIZE).fill(1); -const outputBuffer = new Float32Array(TENSOR_SIZE); - -// Execute the compiled graph with the specified inputs. -const inputs = { - 'input1': inputBuffer1, - 'input2': inputBuffer2, -}; -const outputs = {'output': outputBuffer}; -const result = await context.compute(graph, inputs, outputs); - -console.log('Output value: ' + result.outputs.output); -// Output value: 2.25,2.25,2.25,2.25,2.25,2.25,2.25,2.25 -+++ The following code executes the compiled graph. +
++ // Setup the input buffers with value 1. + const inputBuffer1 = new Float32Array(TENSOR_SIZE).fill(1); + const inputBuffer2 = new Float32Array(TENSOR_SIZE).fill(1); + const outputBuffer = new Float32Array(TENSOR_SIZE); + + // Execute the compiled graph with the specified inputs. + const inputs = { + 'input1': inputBuffer1, + 'input2': inputBuffer2, + }; + const outputs = {'output': outputBuffer}; + const result = await context.compute(graph, inputs, outputs); + + console.log('Output value: ' + result.outputs.output); + // Output value: 2.25,2.25,2.25,2.25,2.25,2.25,2.25,2.25 ++