From 7c3854bf4df1487c4b1158e07f3ac9e184486000 Mon Sep 17 00:00:00 2001 From: Honry Date: Thu, 19 Sep 2024 05:45:07 +0000 Subject: [PATCH] =?UTF-8?q?Deploying=20to=20gh-pages=20from=20@=20webmachi?= =?UTF-8?q?nelearning/webnn-samples@229c4e2ff70bace06ce99b68a29b46aa12846d?= =?UTF-8?q?60=20=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/samples/matmul.js | 12 +++++++-- code/samples/mul_add.js | 2 +- code/samples/simple_graph.js | 2 +- common/utils.js | 15 +++++------ face_recognition/facenet_nchw.js | 5 ++-- face_recognition/facenet_nhwc.js | 5 ++-- face_recognition/main.js | 4 +-- .../face_landmark_nchw.js | 5 ++-- .../face_landmark_nhwc.js | 5 ++-- facial_landmark_detection/main.js | 4 +-- .../ssd_mobilenetv2_face_nchw.js | 5 ++-- .../ssd_mobilenetv2_face_nhwc.js | 5 ++-- .../efficientnet_fp16_nchw.js | 7 +++--- image_classification/main.js | 2 +- image_classification/mobilenet_nchw.js | 7 +++--- image_classification/mobilenet_nhwc.js | 7 +++--- image_classification/resnet50v1_fp16_nchw.js | 7 +++--- image_classification/resnet50v2_nchw.js | 7 +++--- image_classification/resnet50v2_nhwc.js | 7 +++--- image_classification/squeezenet_nchw.js | 7 +++--- image_classification/squeezenet_nhwc.js | 7 +++--- lenet/lenet.js | 25 +++++++++++++------ nnotepad/js/index.js | 1 + nnotepad/js/nnotepad.js | 18 +++++++------ nsnet2/nsnet2.js | 3 +++ object_detection/main.js | 2 +- object_detection/ssd_mobilenetv1_nchw.js | 5 ++-- object_detection/ssd_mobilenetv1_nhwc.js | 5 ++-- object_detection/tiny_yolov2_nchw.js | 9 ++++--- object_detection/tiny_yolov2_nhwc.js | 7 +++--- rnnoise/rnnoise.js | 4 +++ selfie_segmentation/main.js | 8 +++--- semantic_segmentation/deeplabv3_mnv2_nchw.js | 7 +++--- semantic_segmentation/deeplabv3_mnv2_nhwc.js | 7 +++--- semantic_segmentation/main.js | 6 ++--- style_transfer/fast_style_transfer_net.js | 15 +++++------ style_transfer/main.js | 4 +-- 37 files changed, 152 insertions(+), 101 deletions(-) diff --git a/code/samples/matmul.js b/code/samples/matmul.js index 4759c5d6..1b773705 100644 --- a/code/samples/matmul.js +++ b/code/samples/matmul.js @@ -2,8 +2,16 @@ const context = await navigator.ml.createContext({deviceType: 'gpu'}); const builder = new MLGraphBuilder(context); // Step 1: Create a computational graph calculating `c = a * b`. -const a = builder.input('a', {dataType: 'float32', dimensions: [3, 4]}); -const b = builder.input('b', {dataType: 'float32', dimensions: [4, 3]}); +const a = builder.input('a', { + dataType: 'float32', + dimensions: [3, 4], + shape: [3, 4], +}); +const b = builder.input('b', { + dataType: 'float32', + dimensions: [4, 3], + shape: [4, 3], +}); const c = builder.matmul(a, b); // Step 2: Compile it into an executable graph. const graph = await builder.build({c}); diff --git a/code/samples/mul_add.js b/code/samples/mul_add.js index b4a6c564..ddfdf512 100644 --- a/code/samples/mul_add.js +++ b/code/samples/mul_add.js @@ -1,4 +1,4 @@ -const operandType = {dataType: 'float32', dimensions: [2, 2]}; +const operandType = {dataType: 'float32', dimensions: [2, 2], shape: [2, 2]}; const context = await navigator.ml.createContext(); const builder = new MLGraphBuilder(context); // 1. Create a computational graph 'C = 0.2 * A + B'. diff --git a/code/samples/simple_graph.js b/code/samples/simple_graph.js index ff03401e..bd0fcb99 100644 --- a/code/samples/simple_graph.js +++ b/code/samples/simple_graph.js @@ -18,7 +18,7 @@ const TENSOR_SIZE = 8; const builder = new MLGraphBuilder(context); // Create MLOperandDescriptor object. -const desc = {dataType: 'float32', dimensions: TENSOR_DIMS}; +const desc = {dataType: 'float32', dimensions: TENSOR_DIMS, shape: TENSOR_DIMS}; // constant1 is a constant MLOperand with the value 0.5. const constantBuffer1 = new Float32Array(TENSOR_SIZE).fill(0.5); diff --git a/common/utils.js b/common/utils.js index 47787043..fb2f212b 100644 --- a/common/utils.js +++ b/common/utils.js @@ -104,7 +104,7 @@ export async function buildConstantByNpy(builder, url, targetType = 'float32') { if (!dataTypeMap.has(npArray.dataType)) { throw new Error(`Data type ${npArray.dataType} is not supported.`); } - const dimensions = npArray.shape; + const shape = npArray.shape; let type = dataTypeMap.get(npArray.dataType).type; const TypedArrayConstructor = dataTypeMap.get(npArray.dataType).array; const dataView = new Uint8Array(npArray.data.buffer); @@ -121,7 +121,8 @@ export async function buildConstantByNpy(builder, url, targetType = 'float32') { throw new Error(`Conversion from ${npArray.dataType} ` + `to ${targetType} is not supported.`); } - return builder.constant({dataType: type, dimensions}, typedArray); + return builder.constant( + {dataType: type, dimensions: shape, shape}, typedArray); } // Convert video frame to a canvas element @@ -162,7 +163,7 @@ export function stopCameraStream(id, stream) { * input element. * inputOptions = { * inputLayout {String}, // input layout of tensor. - * inputDimensions: {!Array}, // dimensions of input tensor. + * inputShape: {!Array}, // shape of input tensor. * mean: {Array}, // optional, mean values for processing the input * element. If not specified, it will be set to [0, 0, 0, 0]. * std: {Array}, // optional, std values for processing the input @@ -190,16 +191,16 @@ export function stopCameraStream(id, stream) { * @return {Object} tensor, an object of input tensor. */ export function getInputTensor(inputElement, inputOptions) { - const inputDimensions = inputOptions.inputDimensions; + const inputShape = inputOptions.inputShape; const tensor = new Float32Array( - inputDimensions.slice(1).reduce((a, b) => a * b)); + inputShape.slice(1).reduce((a, b) => a * b)); inputElement.width = inputElement.videoWidth || inputElement.naturalWidth; inputElement.height = inputElement.videoHeight || inputElement.naturalHeight; - let [channels, height, width] = inputDimensions.slice(1); + let [channels, height, width] = inputShape.slice(1); const mean = inputOptions.mean || [0, 0, 0, 0]; const std = inputOptions.std || [1, 1, 1, 1]; const normlizationFlag = inputOptions.norm || false; @@ -209,7 +210,7 @@ export function getInputTensor(inputElement, inputOptions) { const imageChannels = 4; // RGBA const drawOptions = inputOptions.drawOptions; if (inputLayout === 'nhwc') { - [height, width, channels] = inputDimensions.slice(1); + [height, width, channels] = inputShape.slice(1); } const canvasElement = document.createElement('canvas'); canvasElement.width = width; diff --git a/face_recognition/facenet_nchw.js b/face_recognition/facenet_nchw.js index e84440c6..91410492 100644 --- a/face_recognition/facenet_nchw.js +++ b/face_recognition/facenet_nchw.js @@ -19,7 +19,7 @@ export class FaceNetNchw { std: [127.5, 127.5, 127.5, 127.5], channelScheme: 'BGR', inputLayout: 'nchw', - inputDimensions: [1, 3, 160, 160], + inputShape: [1, 3, 160, 160], }; this.postOptions = { distanceMetric: 'euclidean', @@ -140,7 +140,8 @@ export class FaceNetNchw { this.builder_ = new MLGraphBuilder(this.context_); const input = this.builder_.input('input', { dataType: 'float32', - dimensions: this.inputOptions.inputDimensions, + dimensions: this.inputOptions.inputShape, + shape: this.inputOptions.inputShape, }); const poolOptions = {windowDimensions: [3, 3], strides}; diff --git a/face_recognition/facenet_nhwc.js b/face_recognition/facenet_nhwc.js index 98155b1a..29214a48 100644 --- a/face_recognition/facenet_nhwc.js +++ b/face_recognition/facenet_nhwc.js @@ -19,7 +19,7 @@ export class FaceNetNhwc { std: [127.5, 127.5, 127.5, 127.5], channelScheme: 'BGR', inputLayout: 'nhwc', - inputDimensions: [1, 160, 160, 3], + inputShape: [1, 160, 160, 3], }; this.postOptions = { distanceMetric: 'euclidean', @@ -141,7 +141,8 @@ export class FaceNetNhwc { this.builder_ = new MLGraphBuilder(this.context_); const input = this.builder_.input('input', { dataType: 'float32', - dimensions: this.inputOptions.inputDimensions, + dimensions: this.inputOptions.inputShape, + shape: this.inputOptions.inputShape, }); const poolOptions = {windowDimensions: [3, 3], strides, layout: 'nhwc'}; diff --git a/face_recognition/main.js b/face_recognition/main.js index 5c04a9f9..ae0c9bc8 100644 --- a/face_recognition/main.js +++ b/face_recognition/main.js @@ -375,9 +375,9 @@ async function main() { console.log('- Computing... '); // Do warm up const fdResults = await fdInstance.compute(new Float32Array( - utils.sizeOfShape(fdInputOptions.inputDimensions)), fdOutputs); + utils.sizeOfShape(fdInputOptions.inputShape)), fdOutputs); const frResults = await frInstance.compute(new Float32Array( - utils.sizeOfShape(frInputOptions.inputDimensions)), frOutputs); + utils.sizeOfShape(frInputOptions.inputShape)), frOutputs); fdOutputs = fdResults.outputs; frOutputs = frResults.outputs; for (let i = 0; i < numRuns; i++) { diff --git a/facial_landmark_detection/face_landmark_nchw.js b/facial_landmark_detection/face_landmark_nchw.js index e092ad12..6fc42ac1 100644 --- a/facial_landmark_detection/face_landmark_nchw.js +++ b/facial_landmark_detection/face_landmark_nchw.js @@ -12,7 +12,7 @@ export class FaceLandmarkNchw { '/test-data/models/face_landmark_nchw/weights'; this.inputOptions = { inputLayout: 'nchw', - inputDimensions: [1, 3, 128, 128], + inputShape: [1, 3, 128, 128], }; } @@ -71,7 +71,8 @@ export class FaceLandmarkNchw { this.builder_ = new MLGraphBuilder(this.context_); const input = this.builder_.input('input', { dataType: 'float32', - dimensions: this.inputOptions.inputDimensions, + dimensions: this.inputOptions.inputShape, + shape: this.inputOptions.inputShape, }); const poolOptions = diff --git a/facial_landmark_detection/face_landmark_nhwc.js b/facial_landmark_detection/face_landmark_nhwc.js index 5c992075..4ff29509 100644 --- a/facial_landmark_detection/face_landmark_nhwc.js +++ b/facial_landmark_detection/face_landmark_nhwc.js @@ -12,7 +12,7 @@ export class FaceLandmarkNhwc { '/test-data/models/face_landmark_nhwc/weights'; this.inputOptions = { inputLayout: 'nhwc', - inputDimensions: [1, 128, 128, 3], + inputShape: [1, 128, 128, 3], }; } @@ -72,7 +72,8 @@ export class FaceLandmarkNhwc { this.builder_ = new MLGraphBuilder(this.context_); const input = this.builder_.input('input', { dataType: 'float32', - dimensions: this.inputOptions.inputDimensions, + dimensions: this.inputOptions.inputShape, + shape: this.inputOptions.inputShape, }); const poolOptions = diff --git a/facial_landmark_detection/main.js b/facial_landmark_detection/main.js index 738f332e..ff32c81c 100644 --- a/facial_landmark_detection/main.js +++ b/facial_landmark_detection/main.js @@ -312,9 +312,9 @@ async function main() { console.log('- Computing... '); // Do warm up const fdResults = await fdInstance.compute(new Float32Array( - utils.sizeOfShape(fdInputOptions.inputDimensions)), fdOutputs); + utils.sizeOfShape(fdInputOptions.inputShape)), fdOutputs); const fldResults = await fldInstance.compute(new Float32Array( - utils.sizeOfShape(fldInputOptions.inputDimensions)), fldOutputs); + utils.sizeOfShape(fldInputOptions.inputShape)), fldOutputs); fdOutputs = fdResults.outputs; fldOutputs = fldResults.outputs; for (let i = 0; i < numRuns; i++) { diff --git a/facial_landmark_detection/ssd_mobilenetv2_face_nchw.js b/facial_landmark_detection/ssd_mobilenetv2_face_nchw.js index 7a4c3452..6d335e84 100644 --- a/facial_landmark_detection/ssd_mobilenetv2_face_nchw.js +++ b/facial_landmark_detection/ssd_mobilenetv2_face_nchw.js @@ -19,7 +19,7 @@ export class SsdMobilenetV2FaceNchw { boxSize: 4, numClasses: 2, numBoxes: [1083, 600, 150, 54, 24, 6], - inputDimensions: [1, 3, 300, 300], + inputShape: [1, 3, 300, 300], }; this.outputsInfo = { 'biasAdd0': [1, 12, 19, 19], @@ -115,7 +115,8 @@ ${nameArray[1]}`; this.builder_ = new MLGraphBuilder(this.context_); const input = this.builder_.input('input', { dataType: 'float32', - dimensions: this.inputOptions.inputDimensions, + dimensions: this.inputOptions.inputShape, + shape: this.inputOptions.inputShape, }); const bottleneck0 = this.buildLinearBottleneck_( diff --git a/facial_landmark_detection/ssd_mobilenetv2_face_nhwc.js b/facial_landmark_detection/ssd_mobilenetv2_face_nhwc.js index 8991b503..e02d01b9 100644 --- a/facial_landmark_detection/ssd_mobilenetv2_face_nhwc.js +++ b/facial_landmark_detection/ssd_mobilenetv2_face_nhwc.js @@ -19,7 +19,7 @@ export class SsdMobilenetV2FaceNhwc { boxSize: 4, numClasses: 2, numBoxes: [1083, 600, 150, 54, 24, 6], - inputDimensions: [1, 300, 300, 3], + inputShape: [1, 300, 300, 3], }; this.outputsInfo = { 'biasAdd0': [1, 19, 19, 12], @@ -127,7 +127,8 @@ ${nameArray[1]}`; this.builder_ = new MLGraphBuilder(this.context_); const input = this.builder_.input('input', { dataType: 'float32', - dimensions: this.inputOptions.inputDimensions, + dimensions: this.inputOptions.inputShape, + shape: this.inputOptions.inputShape, }); const bottleneck0 = this.buildLinearBottleneck_( diff --git a/image_classification/efficientnet_fp16_nchw.js b/image_classification/efficientnet_fp16_nchw.js index af9c3a52..cec1ccd1 100644 --- a/image_classification/efficientnet_fp16_nchw.js +++ b/image_classification/efficientnet_fp16_nchw.js @@ -16,9 +16,9 @@ export class EfficientNetFP16Nchw { norm: true, inputLayout: 'nchw', labelUrl: './labels/labels1000.txt', - inputDimensions: [1, 3, 224, 224], + inputShape: [1, 3, 224, 224], }; - this.outputDimensions = [1, 1000]; + this.outputShape = [1, 1000]; } async buildConv_(input, name, blockName, clip = false, options = {}) { @@ -77,7 +77,8 @@ export class EfficientNetFP16Nchw { this.builder_ = new MLGraphBuilder(this.context_); let data = this.builder_.input('input', { dataType: 'float32', - dimensions: this.inputOptions.inputDimensions, + dimensions: this.inputOptions.inputShape, + shape: this.inputOptions.inputShape, }); data = this.builder_.cast(data, 'float16'); // Block 0 diff --git a/image_classification/main.js b/image_classification/main.js index 99cd3e7f..ea3bfedd 100644 --- a/image_classification/main.js +++ b/image_classification/main.js @@ -335,7 +335,7 @@ async function main() { inputOptions = netInstance.inputOptions; labels = await fetchLabels(inputOptions.labelUrl); outputBuffer = - new Float32Array(utils.sizeOfShape(netInstance.outputDimensions)); + new Float32Array(utils.sizeOfShape(netInstance.outputShape)); isFirstTimeLoad = false; console.log(`- Model name: ${modelName}, Model layout: ${layout} -`); // UI shows model loading progress diff --git a/image_classification/mobilenet_nchw.js b/image_classification/mobilenet_nchw.js index d18bde98..014f3e7f 100644 --- a/image_classification/mobilenet_nchw.js +++ b/image_classification/mobilenet_nchw.js @@ -25,9 +25,9 @@ export class MobileNetV2Nchw { norm: true, inputLayout: 'nchw', labelUrl: './labels/labels1000.txt', - inputDimensions: [1, 3, 224, 224], + inputShape: [1, 3, 224, 224], }; - this.outputDimensions = [1, 1000]; + this.outputShape = [1, 1000]; } async buildConv_(input, name, relu6 = true, options = {}) { @@ -91,7 +91,8 @@ export class MobileNetV2Nchw { this.builder_ = new MLGraphBuilder(this.context_); let data = this.builder_.input('input', { dataType: 'float32', - dimensions: this.inputOptions.inputDimensions, + dimensions: this.inputOptions.inputShape, + shape: this.inputOptions.inputShape, }); if (this.dataType_ === 'float16') { data = this.builder_.cast(data, 'float16'); diff --git a/image_classification/mobilenet_nhwc.js b/image_classification/mobilenet_nhwc.js index a472eeca..441eab85 100644 --- a/image_classification/mobilenet_nhwc.js +++ b/image_classification/mobilenet_nhwc.js @@ -18,9 +18,9 @@ export class MobileNetV2Nhwc { std: [127.5, 127.5, 127.5], inputLayout: 'nhwc', labelUrl: './labels/labels1001.txt', - inputDimensions: [1, 224, 224, 3], + inputShape: [1, 224, 224, 3], }; - this.outputDimensions = [1, 1001]; + this.outputShape = [1, 1001]; } async buildConv_(input, weightsSubName, biasSubName, relu6, options) { @@ -89,7 +89,8 @@ export class MobileNetV2Nhwc { const filterLayout = 'ohwi'; const input = this.builder_.input('input', { dataType: 'float32', - dimensions: this.inputOptions.inputDimensions, + dimensions: this.inputOptions.inputShape, + shape: this.inputOptions.inputShape, }); const conv0 = this.buildConv_( input, '90', 'Conv_Conv2D', true, {strides, autoPad, filterLayout}); diff --git a/image_classification/resnet50v1_fp16_nchw.js b/image_classification/resnet50v1_fp16_nchw.js index 627e43ea..d9cdc843 100644 --- a/image_classification/resnet50v1_fp16_nchw.js +++ b/image_classification/resnet50v1_fp16_nchw.js @@ -16,9 +16,9 @@ export class ResNet50V1FP16Nchw { norm: true, inputLayout: 'nchw', labelUrl: './labels/labels1000.txt', - inputDimensions: [1, 3, 224, 224], + inputShape: [1, 3, 224, 224], }; - this.outputDimensions = [1, 1000]; + this.outputShape = [1, 1000]; } async buildConv_(input, name, stageName, relu, options = undefined) { @@ -78,7 +78,8 @@ export class ResNet50V1FP16Nchw { this.builder_ = new MLGraphBuilder(this.context_); let data = this.builder_.input('input', { dataType: 'float32', - dimensions: this.inputOptions.inputDimensions, + dimensions: this.inputOptions.inputShape, + shape: this.inputOptions.inputShape, }); data = this.builder_.cast(data, 'float16'); const conv1 = await this.buildConv_( diff --git a/image_classification/resnet50v2_nchw.js b/image_classification/resnet50v2_nchw.js index 03a3d256..56201dee 100644 --- a/image_classification/resnet50v2_nchw.js +++ b/image_classification/resnet50v2_nchw.js @@ -16,9 +16,9 @@ export class ResNet50V2Nchw { norm: true, inputLayout: 'nchw', labelUrl: './labels/labels1000.txt', - inputDimensions: [1, 3, 224, 224], + inputShape: [1, 3, 224, 224], }; - this.outputDimensions = [1, 1000]; + this.outputShape = [1, 1000]; } async buildConv_(input, name, stageName, options = undefined) { @@ -100,7 +100,8 @@ export class ResNet50V2Nchw { this.builder_ = new MLGraphBuilder(this.context_); const data = this.builder_.input('input', { dataType: 'float32', - dimensions: this.inputOptions.inputDimensions, + dimensions: this.inputOptions.inputShape, + shape: this.inputOptions.inputShape, }); const bn1 = this.buildBatchNorm_(data, '0', '', false); const conv0 = this.buildConv_( diff --git a/image_classification/resnet50v2_nhwc.js b/image_classification/resnet50v2_nhwc.js index 5f06b127..3babf6f3 100644 --- a/image_classification/resnet50v2_nhwc.js +++ b/image_classification/resnet50v2_nhwc.js @@ -19,9 +19,9 @@ export class ResNet50V2Nhwc { std: [127.5, 127.5, 127.5], inputLayout: layout, labelUrl: './labels/labels1001.txt', - inputDimensions: [1, 224, 224, 3], + inputShape: [1, 224, 224, 3], }; - this.outputDimensions = [1, 1001]; + this.outputShape = [1, 1001]; } async buildConv_(input, nameIndices, options = {}, relu = true) { @@ -122,7 +122,8 @@ export class ResNet50V2Nhwc { this.builder_ = new MLGraphBuilder(this.context_); const input = this.builder_.input('input', { dataType: 'float32', - dimensions: this.inputOptions.inputDimensions, + dimensions: this.inputOptions.inputShape, + shape: this.inputOptions.inputShape, }); const conv1 = await this.buildConv_( input, ['', '', '1'], {strides, padding: [3, 3, 3, 3]}, false); diff --git a/image_classification/squeezenet_nchw.js b/image_classification/squeezenet_nchw.js index 5f23808d..6fe75e5b 100644 --- a/image_classification/squeezenet_nchw.js +++ b/image_classification/squeezenet_nchw.js @@ -16,9 +16,9 @@ export class SqueezeNetNchw { norm: true, inputLayout: 'nchw', labelUrl: './labels/labels1000.txt', - inputDimensions: [1, 3, 224, 224], + inputShape: [1, 3, 224, 224], }; - this.outputDimensions = [1, 1000]; + this.outputShape = [1, 1000]; } async buildConv_(input, name, options = {}) { @@ -45,7 +45,8 @@ export class SqueezeNetNchw { this.builder_ = new MLGraphBuilder(this.context_); const data = this.builder_.input('input', { dataType: 'float32', - dimensions: this.inputOptions.inputDimensions, + dimensions: this.inputOptions.inputShape, + shape: this.inputOptions.inputShape, }); const conv0 = this.buildConv_(data, 'conv0', {strides: [2, 2]}); const pool0 = this.builder_.maxPool2d( diff --git a/image_classification/squeezenet_nhwc.js b/image_classification/squeezenet_nhwc.js index 05565710..c9d7d2d1 100644 --- a/image_classification/squeezenet_nhwc.js +++ b/image_classification/squeezenet_nhwc.js @@ -15,9 +15,9 @@ export class SqueezeNetNhwc { std: [127.5, 127.5, 127.5], inputLayout: 'nhwc', labelUrl: './labels/labels1001.txt', - inputDimensions: [1, 224, 224, 3], + inputShape: [1, 224, 224, 3], }; - this.outputDimensions = [1, 1001]; + this.outputShape = [1, 1001]; } async buildConv_(input, name, options = {}) { @@ -56,7 +56,8 @@ export class SqueezeNetNhwc { const layout = 'nhwc'; const placeholder = this.builder_.input('input', { dataType: 'float32', - dimensions: this.inputOptions.inputDimensions, + dimensions: this.inputOptions.inputShape, + shape: this.inputOptions.inputShape, }); const conv1 = this.buildConv_( placeholder, 'conv1', {strides, autoPad: 'same-upper'}); diff --git a/lenet/lenet.js b/lenet/lenet.js index 45d85f19..c3852509 100644 --- a/lenet/lenet.js +++ b/lenet/lenet.js @@ -28,6 +28,7 @@ export class LeNet { let input = this.builder_.input('input', { dataType: 'float32', dimensions: inputShape, + shape: inputShape, }); if (this.layout_ === 'nhwc') { @@ -50,7 +51,11 @@ export class LeNet { conv1FilterData, conv1FitlerShape, this.oihwToOhwiPermutation_); } const conv1Filter = this.builder_.constant( - {dataType: 'float32', dimensions: conv1FitlerShape}, + { + dataType: 'float32', + dimensions: conv1FitlerShape, + shape: conv1FitlerShape, + }, conv1FilterData); byteOffset += sizeOfShape(conv1FitlerShape) * Float32Array.BYTES_PER_ELEMENT; @@ -59,7 +64,7 @@ export class LeNet { const add1BiasData = new Float32Array(arrayBuffer, byteOffset, sizeOfShape(add1BiasShape)); const add1Bias = this.builder_.constant( - {dataType: 'float32', dimensions: add1BiasShape}, + {dataType: 'float32', dimensions: add1BiasShape, shape: add1BiasShape}, add1BiasData, ); byteOffset += sizeOfShape(add1BiasShape) * Float32Array.BYTES_PER_ELEMENT; @@ -87,14 +92,18 @@ export class LeNet { conv2FilterData, conv2FilterShape, this.oihwToOhwiPermutation_); } const conv2Filter = this.builder_.constant( - {dataType: 'float32', dimensions: conv2FilterShape}, + { + dataType: 'float32', + dimensions: conv2FilterShape, + shape: conv2FilterShape, + }, conv2FilterData); byteOffset += sizeOfShape(conv2FilterShape) * Float32Array.BYTES_PER_ELEMENT; const add2BiasShape = [50]; const add2Bias = this.builder_.constant( - {dataType: 'float32', dimensions: add2BiasShape}, + {dataType: 'float32', dimensions: add2BiasShape, shape: add2BiasShape}, new Float32Array(arrayBuffer, byteOffset, sizeOfShape(add2BiasShape))); byteOffset += sizeOfShape(add2BiasShape) * Float32Array.BYTES_PER_ELEMENT; conv2Options.bias = add2Bias; @@ -120,7 +129,7 @@ export class LeNet { const matmul1Shape = [500, 800]; const matmul1Weights = this.builder_.constant( - {dataType: 'float32', dimensions: matmul1Shape}, + {dataType: 'float32', dimensions: matmul1Shape, shape: matmul1Shape}, new Float32Array(arrayBuffer, byteOffset, sizeOfShape(matmul1Shape))); byteOffset += sizeOfShape(matmul1Shape) * Float32Array.BYTES_PER_ELEMENT; const matmul1WeightsTransposed = this.builder_.transpose(matmul1Weights); @@ -128,7 +137,7 @@ export class LeNet { const add3BiasShape = [1, 500]; const add3Bias = this.builder_.constant( - {dataType: 'float32', dimensions: add3BiasShape}, + {dataType: 'float32', dimensions: add3BiasShape, shape: add3BiasShape}, new Float32Array(arrayBuffer, byteOffset, sizeOfShape(add3BiasShape))); byteOffset += sizeOfShape(add3BiasShape) * Float32Array.BYTES_PER_ELEMENT; const add3 = this.builder_.add(matmul1, add3Bias); @@ -140,7 +149,7 @@ export class LeNet { const matmul2Shape = [10, 500]; const matmul2Weights = this.builder_.constant( - {dataType: 'float32', dimensions: matmul2Shape}, + {dataType: 'float32', dimensions: matmul2Shape, shape: matmul2Shape}, new Float32Array(arrayBuffer, byteOffset, sizeOfShape(matmul2Shape))); byteOffset += sizeOfShape(matmul2Shape) * Float32Array.BYTES_PER_ELEMENT; const matmul2WeightsTransposed = this.builder_.transpose(matmul2Weights); @@ -148,7 +157,7 @@ export class LeNet { const add4BiasShape = [1, 10]; const add4Bias = this.builder_.constant( - {dataType: 'float32', dimensions: add4BiasShape}, + {dataType: 'float32', dimensions: add4BiasShape, shape: add4BiasShape}, new Float32Array(arrayBuffer, byteOffset, sizeOfShape(add4BiasShape))); const add4 = this.builder_.add(matmul2, add4Bias); diff --git a/nnotepad/js/index.js b/nnotepad/js/index.js index fcb4fbb9..766c9bac 100644 --- a/nnotepad/js/index.js +++ b/nnotepad/js/index.js @@ -130,6 +130,7 @@ function explain(outputs) { .map((output) => [ 'dataType: ' + output.dataType, + 'dimensions: ' + Util.stringify(output.shape), 'shape: ' + Util.stringify(output.shape), 'tensor: ' + dumpTensor(output.shape, output.buffer, 8), ].join('\n'), diff --git a/nnotepad/js/nnotepad.js b/nnotepad/js/nnotepad.js index a3674353..08a9fde4 100644 --- a/nnotepad/js/nnotepad.js +++ b/nnotepad/js/nnotepad.js @@ -454,20 +454,20 @@ export class NNotepad { } function serializeTensor(tensor, dataType) { - const dimensions = []; + const shape = []; const elements = []; (function measure(t, d) { - if (d >= dimensions.length) { - dimensions[d] = t.length; - } else if (dimensions[d] !== t.length) { - throw new Error('Invalid tensor: inconsistent dimensions'); + if (d >= shape.length) { + shape[d] = t.length; + } else if (shape[d] !== t.length) { + throw new Error('Invalid tensor: inconsistent shape'); } t.forEach((e) => { if (e.type === 'array') { measure(e.value, d + 1); } else if (e.type !== 'number') { throw new Error(`Invalid tensor: saw ${e.type}`); - } else if (d + 1 !== dimensions.length) { + } else if (d + 1 !== shape.length) { throw new Error('Invalid tensor: saw scalar'); } else { elements.push(e.value); @@ -476,7 +476,8 @@ export class NNotepad { }(tensor, 0)); const ctor = WebNNUtil.dataTypeToBufferType(dataType); return `_.constant({dataType: "${dataType}", dimensions: ${ - Util.stringify(dimensions)}}, new ${ctor.name}([${ + Util.stringify(shape)}}, shape: ${ + Util.stringify(shape)}}, new ${ctor.name}([${ elements.map((n) => Util.stringifyNumber(n, dataType)).join(',')}]))`; } @@ -501,6 +502,7 @@ export class NNotepad { const dims = shape.value.map((expr) => expr.value); const ctor = WebNNUtil.dataTypeToBufferType(dataType.value); return `_.constant({dataType: "${dataType.value}", dimensions: ${ + Util.stringify(dims)}}, shape: ${ Util.stringify(dims)}}, new ${ ctor.name}(await Util.loadBuffer(${Util.stringify(url.value)})))`; } @@ -517,6 +519,7 @@ export class NNotepad { const ctor = WebNNUtil.dataTypeToBufferType(dataType.value); const len = dims.reduce((a, b) => a * b, 1); return `_.constant({dataType: "${dataType.value}", dimensions: ${ + Util.stringify(dims)}}, shape: ${ Util.stringify(dims)}}, new ${ ctor.name}(${len}))`; } @@ -595,6 +598,7 @@ export class NNotepad { return outputOperands.map( (op, index) => ({ dataType: op.dataType(), + dimensions: op.shape(), shape: op.shape(), buffer: maybeProxyForFloat16Array(result.outputs[`output-${index}`]), })); diff --git a/nsnet2/nsnet2.js b/nsnet2/nsnet2.js index 5ad2655f..e91a8608 100644 --- a/nsnet2/nsnet2.js +++ b/nsnet2/nsnet2.js @@ -39,12 +39,14 @@ export class NSNet2 { const input = this.builder_.input('input', { dataType: 'float32', dimensions: [batchSize, frames, this.frameSize], + shape: [batchSize, frames, this.frameSize], }); const relu20 = this.builder_.relu(this.builder_.add(this.builder_.matmul(input, weight172), biasFcIn0)); const transpose31 = this.builder_.transpose(relu20, {permutation: [1, 0, 2]}); const initialState92 = this.builder_.input('initialState92', { dataType: 'float32', dimensions: [1, batchSize, this.hiddenSize], + shape: [1, batchSize, this.hiddenSize], }); const [gru94, gru93] = this.builder_.gru(transpose31, weight192, recurrentWeight193, frames, this.hiddenSize, {bias: bias194, recurrentBias: recurrentBias194, initialHiddenState: initialState92, returnSequence: true}); @@ -55,6 +57,7 @@ export class NSNet2 { const initialState155 = this.builder_.input('initialState155', { dataType: 'float32', dimensions: [1, batchSize, this.hiddenSize], + shape: [1, batchSize, this.hiddenSize], }); const [gru157, gru156] = this.builder_.gru(squeeze95, weight212, recurrentWeight213, frames, this.hiddenSize, {bias: bias214, recurrentBias: recurrentBias214, initialHiddenState: initialState155, returnSequence: true}); diff --git a/object_detection/main.js b/object_detection/main.js index 504ad73e..f9f9745e 100644 --- a/object_detection/main.js +++ b/object_detection/main.js @@ -274,7 +274,7 @@ async function main() { if (modelName.includes('tinyyolov2')) { outputs = { 'output': new Float32Array( - utils.sizeOfShape(netInstance.outputDimensions)), + utils.sizeOfShape(netInstance.outputShape)), }; } else { outputs = { diff --git a/object_detection/ssd_mobilenetv1_nchw.js b/object_detection/ssd_mobilenetv1_nchw.js index 440634d4..067dab6f 100644 --- a/object_detection/ssd_mobilenetv1_nchw.js +++ b/object_detection/ssd_mobilenetv1_nchw.js @@ -22,7 +22,7 @@ export class SsdMobilenetV1Nchw { margin: [1, 1, 1, 1], mean: [127.5, 127.5, 127.5], std: [127.5, 127.5, 127.5], - inputDimensions: [1, 3, 300, 300], + inputShape: [1, 3, 300, 300], }; } @@ -81,7 +81,8 @@ ${nameArray[1]}_BatchNorm_batchnorm`; this.builder_ = new MLGraphBuilder(this.context_); let input = this.builder_.input('input', { dataType: 'float32', - dimensions: this.inputOptions.inputDimensions, + dimensions: this.inputOptions.inputShape, + shape: this.inputOptions.inputShape, }); if (this.targetDataType_ === 'float16') { input = this.builder_.cast(input, 'float16'); diff --git a/object_detection/ssd_mobilenetv1_nhwc.js b/object_detection/ssd_mobilenetv1_nhwc.js index 3ec267fd..9fe7d316 100644 --- a/object_detection/ssd_mobilenetv1_nhwc.js +++ b/object_detection/ssd_mobilenetv1_nhwc.js @@ -18,7 +18,7 @@ export class SsdMobilenetV1Nhwc { margin: [1, 1, 1, 1], mean: [127.5, 127.5, 127.5], std: [127.5, 127.5, 127.5], - inputDimensions: [1, 300, 300, 3], + inputShape: [1, 300, 300, 3], }; } @@ -87,7 +87,8 @@ ${nameArray[1]}_BatchNorm_batchnorm`; this.builder_ = new MLGraphBuilder(this.context_); const input = this.builder_.input('input', { dataType: 'float32', - dimensions: this.inputOptions.inputDimensions, + dimensions: this.inputOptions.inputShape, + shape: this.inputOptions.inputShape, }); const strides = [2, 2]; const conv0 = await this.buildConv_( diff --git a/object_detection/tiny_yolov2_nchw.js b/object_detection/tiny_yolov2_nchw.js index 32b35eb3..d6bd91dc 100644 --- a/object_detection/tiny_yolov2_nchw.js +++ b/object_detection/tiny_yolov2_nchw.js @@ -17,9 +17,9 @@ export class TinyYoloV2Nchw { labelUrl: './labels/pascal_classes.txt', margin: [1, 1, 1, 1], anchors: [1.08, 1.19, 3.42, 4.41, 6.63, 11.38, 9.42, 5.11, 16.62, 10.52], - inputDimensions: [1, 3, 416, 416], + inputShape: [1, 3, 416, 416], }; - this.outputDimensions = [1, 125, 13, 13]; + this.outputShape = [1, 125, 13, 13]; } async buildConv_(input, name) { @@ -63,10 +63,11 @@ export class TinyYoloV2Nchw { this.builder_ = new MLGraphBuilder(this.context_); let image = this.builder_.input('input', { dataType: 'float32', - dimensions: this.inputOptions.inputDimensions, + dimensions: this.inputOptions.inputShape, + shape: this.inputOptions.inputShape, }); let mulScale = this.builder_.constant( - {dataType: 'float32', dimensions: [1]}, + {dataType: 'float32', dimensions: [1], shape: [1]}, new Float32Array([0.003921568859368563]), ); const poolOptions = { diff --git a/object_detection/tiny_yolov2_nhwc.js b/object_detection/tiny_yolov2_nhwc.js index 933bba24..1be3cd95 100644 --- a/object_detection/tiny_yolov2_nhwc.js +++ b/object_detection/tiny_yolov2_nhwc.js @@ -15,10 +15,10 @@ export class TinyYoloV2Nhwc { labelUrl: './labels/pascal_classes.txt', margin: [1, 1, 1, 1], anchors: [1.08, 1.19, 3.42, 4.41, 6.63, 11.38, 9.42, 5.11, 16.62, 10.52], - inputDimensions: [1, 416, 416, 3], + inputShape: [1, 416, 416, 3], norm: true, }; - this.outputDimensions = [1, 13, 13, 125]; + this.outputShape = [1, 13, 13, 125]; } async buildConv_(input, name, leakyRelu = true) { @@ -57,7 +57,8 @@ export class TinyYoloV2Nhwc { this.builder_ = new MLGraphBuilder(this.context_); const input = this.builder_.input('input', { dataType: 'float32', - dimensions: this.inputOptions.inputDimensions, + dimensions: this.inputOptions.inputShape, + shape: this.inputOptions.inputShape, }); const poolOptions = { diff --git a/rnnoise/rnnoise.js b/rnnoise/rnnoise.js index 962b10ae..bde6e0d0 100644 --- a/rnnoise/rnnoise.js +++ b/rnnoise/rnnoise.js @@ -54,6 +54,7 @@ export class RNNoise { const input = this.builder_.input('input', { dataType: 'float32', dimensions: [this.batchSize_, this.frames_, this.featureSize], + shape: [this.batchSize_, this.frames_, this.featureSize], }); const inputDense0 = this.builder_.matmul(input, inputDenseKernel0); const biasedTensorName2 = this.builder_.add(inputDense0, inputDenseBias0); @@ -69,6 +70,7 @@ export class RNNoise { const vadGruInitialH = this.builder_.input('vadGruInitialH', { dataType: 'float32', dimensions: [1, this.batchSize_, this.vadGruHiddenSize], + shape: [1, this.batchSize_, this.vadGruHiddenSize], }); const [vadGruYH, vadGruY] = this.builder_.gru(vadGruX, vadGruW, vadGruR, this.frames_, this.vadGruHiddenSize, { @@ -96,6 +98,7 @@ export class RNNoise { const noiseGruInitialH = this.builder_.input('noiseGruInitialH', { dataType: 'float32', dimensions: [1, this.batchSize_, this.noiseGruHiddenSize], + shape: [1, this.batchSize_, this.noiseGruHiddenSize], }); const [noiseGruYH, noiseGruY] = this.builder_.gru(noiseGruX, noiseGruW, noiseGruR, this.frames_, this.noiseGruHiddenSize, { @@ -123,6 +126,7 @@ export class RNNoise { const denoiseGruInitialH = this.builder_.input('denoiseGruInitialH', { dataType: 'float32', dimensions: [1, this.batchSize_, this.denoiseGruHiddenSize], + shape: [1, this.batchSize_, this.denoiseGruHiddenSize], }); const [denoiseGruYH, denoiseGruY] = this.builder_.gru(denoiseGruX, denoiseGruW, denoiseGruR, this.frames_, this.denoiseGruHiddenSize, { diff --git a/selfie_segmentation/main.js b/selfie_segmentation/main.js index 1deb052a..de7d5be7 100644 --- a/selfie_segmentation/main.js +++ b/selfie_segmentation/main.js @@ -28,17 +28,17 @@ const inputOptions = { }; const modelConfigs = { 'selfie_segmentation': { - inputDimensions: [1, 256, 256, 3], + inputShape: [1, 256, 256, 3], inputResolution: [256, 256], modelPath: 'https://storage.googleapis.com/mediapipe-models/image_segmenter/selfie_segmenter/float16/latest/selfie_segmenter.tflite', }, 'selfie_segmentation_landscape': { - inputDimensions: [1, 144, 256, 3], + inputShape: [1, 144, 256, 3], inputResolution: [256, 144], modelPath: 'https://storage.googleapis.com/mediapipe-models/image_segmenter/selfie_segmenter_landscape/float16/latest/selfie_segmenter_landscape.tflite', }, 'deeplabv3': { - inputDimensions: [1, 257, 257, 3], + inputShape: [1, 257, 257, 3], inputResolution: [257, 257], modelPath: 'https://tfhub.dev/tensorflow/lite-model/deeplabv3/1/metadata/2?lite-format=tflite', }, @@ -60,7 +60,7 @@ $('input[name="model"]').on('change', async (e) => { } else { $('#ssModelsBtns .btn').removeClass('active'); } - inputOptions.inputDimensions = modelConfigs[modelName].inputDimensions; + inputOptions.inputShape = modelConfigs[modelName].inputShape; inputOptions.inputResolution = modelConfigs[modelName].inputResolution; if (inputType === 'camera') utils.stopCameraStream(rafReq, stream); await main(); diff --git a/semantic_segmentation/deeplabv3_mnv2_nchw.js b/semantic_segmentation/deeplabv3_mnv2_nchw.js index 608b514f..a0ce7e78 100644 --- a/semantic_segmentation/deeplabv3_mnv2_nchw.js +++ b/semantic_segmentation/deeplabv3_mnv2_nchw.js @@ -22,9 +22,9 @@ export class DeepLabV3MNV2Nchw { scaledFlag: true, inputLayout: 'nchw', labelUrl: './labels/labels.txt', - inputDimensions: [1, 3, 513, 513], + inputShape: [1, 3, 513, 513], }; - this.outputDimensions = [1, 21, 513, 513]; + this.outputShape = [1, 21, 513, 513]; } async buildConv_(input, nameArray, activation = 'relu6', options = {}) { @@ -90,7 +90,8 @@ export class DeepLabV3MNV2Nchw { const input = this.builder_.input('input', { dataType: 'float32', - dimensions: this.inputOptions.inputDimensions, + dimensions: this.inputOptions.inputShape, + shape: this.inputOptions.inputShape, }); const conv0 = this.buildConv_( input, ['MobilenetV2_Conv_Conv2D', '', '551'], 'relu6', {strides, padding: [1, 1, 1, 1]}); diff --git a/semantic_segmentation/deeplabv3_mnv2_nhwc.js b/semantic_segmentation/deeplabv3_mnv2_nhwc.js index 3656c366..69f10eef 100644 --- a/semantic_segmentation/deeplabv3_mnv2_nhwc.js +++ b/semantic_segmentation/deeplabv3_mnv2_nhwc.js @@ -17,9 +17,9 @@ export class DeepLabV3MNV2Nhwc { scaledFlag: true, inputLayout: 'nhwc', labelUrl: './labels/labels.txt', - inputDimensions: [1, 513, 513, 3], + inputShape: [1, 513, 513, 3], }; - this.outputDimensions = [1, 513, 513, 21]; + this.outputShape = [1, 513, 513, 21]; } async buildConv_( @@ -81,7 +81,8 @@ export class DeepLabV3MNV2Nhwc { const strides = [2, 2]; const input = this.builder_.input('input', { dataType: 'float32', - dimensions: this.inputOptions.inputDimensions, + dimensions: this.inputOptions.inputShape, + shape: this.inputOptions.inputShape, }); const conv0 = await this.buildConv_( input, 'MobilenetV2_Conv_Conv2D', '', true, {strides}); diff --git a/semantic_segmentation/main.js b/semantic_segmentation/main.js index e766a651..df54062f 100644 --- a/semantic_segmentation/main.js +++ b/semantic_segmentation/main.js @@ -276,7 +276,7 @@ async function drawOutput(srcElement) { // TODO: move 'argMax' operation to graph once it is supported in WebNN spec. // https://github.com/webmachinelearning/webnn/issues/184 const [argMaxBuffer, outputShape] = tf.tidy(() => { - const a = tf.tensor(outputBuffer, netInstance.outputDimensions, 'float32'); + const a = tf.tensor(outputBuffer, netInstance.outputShape, 'float32'); let axis = 3; if (layout === 'nchw') { axis = 1; @@ -285,7 +285,7 @@ async function drawOutput(srcElement) { return [b.dataSync(), b.shape]; }); - const width = inputOptions.inputDimensions[2]; + const width = inputOptions.inputShape[2]; const imWidth = srcElement.naturalWidth | srcElement.width; const imHeight = srcElement.naturalHeight | srcElement.height; const resizeRatio = Math.max(Math.max(imWidth, imHeight) / width, 1); @@ -354,7 +354,7 @@ export async function main() { inputOptions = netInstance.inputOptions; labels = await fetchLabels(inputOptions.labelUrl); outputBuffer = - new Float32Array(utils.sizeOfShape(netInstance.outputDimensions)); + new Float32Array(utils.sizeOfShape(netInstance.outputShape)); isFirstTimeLoad = false; console.log(`- Model name: ${modelName}, Model layout: ${layout} -`); // UI shows model loading progress diff --git a/style_transfer/fast_style_transfer_net.js b/style_transfer/fast_style_transfer_net.js index cfa72ce6..14c40f7c 100644 --- a/style_transfer/fast_style_transfer_net.js +++ b/style_transfer/fast_style_transfer_net.js @@ -15,10 +15,10 @@ export class FastStyleTransferNet { this.weightsUrl_ = weightsOrigin() + '/test-data/models/fast_style_transfer_nchw/weights/'; this.inputOptions = { - inputDimensions: [1, 3, 540, 540], + inputShape: [1, 3, 540, 540], inputLayout: 'nchw', }; - this.outputDimensions = [1, 3, 540, 540]; + this.outputShape = [1, 3, 540, 540]; } buildInstanceNormalization_(conv2D, variableMul, variableAdd) { @@ -96,25 +96,26 @@ export class FastStyleTransferNet { const padding1 = [0, 0, 1, 1]; const padding4 = [0, 0, 4, 4]; this.constAdd_ = this.builder_.constant( - {dataType: 'float32', dimensions: [1]}, + {dataType: 'float32', dimensions: [1], shape: [1]}, new Float32Array([9.999999717180685e-10]), ); this.constPow_ = this.builder_.constant( - {dataType: 'float32', dimensions: [1]}, + {dataType: 'float32', dimensions: [1], shape: [1]}, new Float32Array([0.5]), ); const constMul0 = this.builder_.constant( - {dataType: 'float32', dimensions: [1]}, + {dataType: 'float32', dimensions: [1], shape: [1]}, new Float32Array([150]), ); const constAdd0 = this.builder_.constant( - {dataType: 'float32', dimensions: [1]}, + {dataType: 'float32', dimensions: [1], shape: [1]}, new Float32Array([127.5]), ); // Build up the network. const input = this.builder_.input('input', { dataType: 'float32', - dimensions: this.inputOptions.inputDimensions, + dimensions: this.inputOptions.inputShape, + shape: this.inputOptions.inputShape, }); const conv2D0 = this.builder_.conv2d(this.builder_.pad(input, padding4, padding4, {mode: 'reflection'}), weightConv0); diff --git a/style_transfer/main.js b/style_transfer/main.js index 25dde460..a4e7c36c 100644 --- a/style_transfer/main.js +++ b/style_transfer/main.js @@ -139,7 +139,7 @@ function drawInput(srcElement, canvasId) { } function drawOutput(inCanvasId, outCanvasId) { - const outputSize = fastStyleTransferNet.outputDimensions; + const outputSize = fastStyleTransferNet.outputShape; const height = outputSize[2]; const width = outputSize[3]; const mean = [1, 1, 1, 1]; @@ -210,7 +210,7 @@ export async function main() { } fastStyleTransferNet = new FastStyleTransferNet(); outputBuffer = new Float32Array( - utils.sizeOfShape(fastStyleTransferNet.outputDimensions)); + utils.sizeOfShape(fastStyleTransferNet.outputShape)); isFirstTimeLoad = false; isModelChanged = false; console.log(`- Model ID: ${modelId} -`);