[JS/Web] The bias input is optional, not required, for LayerNormalization operator (#17143)

### Description
Fix a typo. LayerNormalization takes 2 or 3 inputs. The third input,
bias, is optional.



### Motivation and Context
<!-- - Why is this change required? What problem does it solve?
- If it fixes an open issue, please link to the issue here. -->
This commit is contained in:
satyajandhyala 2023-08-16 10:41:20 -07:00 committed by GitHub
parent 2ae930333b
commit 89b682e3f3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 51 additions and 9 deletions

View file

@ -15,7 +15,7 @@ export interface LayerNormAttributes extends AttributeWithCacheKey {
}
const validateInputs = (inputs: readonly TensorView[]): void => {
if (!inputs || inputs.length <= 2) {
if (!inputs || inputs.length < 2) {
throw new Error('layerNorm requires at least 2 inputs.');
}
@ -41,7 +41,7 @@ const createLayerNormProgramInfo =
const biasSize = bias ? ShapeUtil.size(bias.dims) : 0;
if (scaleSize !== normSize || (bias && biasSize !== normSize)) {
throw new Error(`Size of X.shape()[axis:] == ${normSize}.
Size of scale and bias (if provided) must match this.
Size of scale and bias (if provided) must match this.
Got scale size of ${scaleSize} and bias size of ${biasSize}`);
}
@ -58,17 +58,24 @@ const createLayerNormProgramInfo =
const hasMeanDataOutput = outputCount > 1;
const hasInvStdOutput = outputCount > 2;
let bindingIndex = 0;
const getShaderSource = (shaderHelper: ShaderHelper) => `
const normSize: u32 = ${normSize};
const normSizeTyped: ${dataType} = ${normSize};
const epsilon: f32 = ${attributes.epsilon};
@group(0) @binding(0) var<storage, read> x : array<${dataType}>;
@group(0) @binding(1) var<storage, read> scale : array<${dataType}>;
${bias ? `@group(0) @binding(2) var<storage, read> bias : array<${dataType}>;` : ''}
@group(0) @binding(3) var<storage, read_write> output : array<${dataType}>;
${hasMeanDataOutput ? `@group(0) @binding(4) var<storage, read_write> meanDataOutput : array<${dataType}>` : ''};
${hasInvStdOutput ? `@group(0) @binding(5) var<storage, read_write> invStdOutput : array<${dataType}>` : ''};
@group(0) @binding(${bindingIndex++}) var<storage, read> x : array<${dataType}>;
@group(0) @binding(${bindingIndex++}) var<storage, read> scale : array<${dataType}>;
${bias ? `@group(0) @binding(${bindingIndex++}) var<storage, read> bias : array<${dataType}>;` : ''}
@group(0) @binding(${bindingIndex++}) var<storage, read_write> output : array<${dataType}>;
${
hasMeanDataOutput ?
`@group(0) @binding(${bindingIndex++}) var<storage, read_write> meanDataOutput : array<${dataType}>` :
''};
${
hasInvStdOutput ?
`@group(0) @binding(${bindingIndex++}) var<storage, read_write> invStdOutput : array<${dataType}>` :
''};
${shaderHelper.mainStart()}
let offset = global_idx * normSize;
@ -118,7 +125,8 @@ export const layerNorm = (context: ComputeContext, attributes: LayerNormAttribut
const metadata = {
name: 'LayerNormalization',
inputTypes: [GpuDataType.default, GpuDataType.default, GpuDataType.default],
inputTypes: context.inputs.length === 2 ? [GpuDataType.default, GpuDataType.default] :
[GpuDataType.default, GpuDataType.default, GpuDataType.default],
cacheHint: attributes.cacheKey + context.outputCount.toString(10) + context.inputs.length.toString(10),
};

View file

@ -0,0 +1,33 @@
[
{
"name": "Simple test without bias",
"operator": "LayerNormalization",
"cases": [
{
"name": "Simple test without bias",
"inputs": [
{
"data": [1, 2, 3, 4, 5, 6, 7, 8],
"dims": [1, 2, 4],
"type": "float32"
},
{
"data": [1, 2, 3, 4],
"dims": [4],
"type": "float32"
}
],
"outputs": [
{
"data": [
-1.3416354656219482, -0.8944236636161804, 1.3416354656219482, 5.366541862487793, -1.3416354656219482,
-0.8944236636161804, 1.3416354656219482, 5.366541862487793
],
"dims": [1, 2, 4],
"type": "float32"
}
]
}
]
}
]

View file

@ -1345,6 +1345,7 @@
//"neg.jsonc",
//"not.jsonc",
//"or.jsonc",
"layer-norm.jsonc",
"leaky-relu.jsonc",
"reduce-min.jsonc",
"relu.jsonc",