Skip to content

Commit 229c4e2

Browse files
authored
Use both MLOperandDescriptor.dimensions and MLOperandDescriptor.shape (#274)
Fixed #273
1 parent c5e6539 commit 229c4e2

37 files changed

+152
-101
lines changed

code/samples/matmul.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,16 @@
22
const context = await navigator.ml.createContext({deviceType: 'gpu'});
33
const builder = new MLGraphBuilder(context);
44
// Step 1: Create a computational graph calculating `c = a * b`.
5-
const a = builder.input('a', {dataType: 'float32', dimensions: [3, 4]});
6-
const b = builder.input('b', {dataType: 'float32', dimensions: [4, 3]});
5+
const a = builder.input('a', {
6+
dataType: 'float32',
7+
dimensions: [3, 4],
8+
shape: [3, 4],
9+
});
10+
const b = builder.input('b', {
11+
dataType: 'float32',
12+
dimensions: [4, 3],
13+
shape: [4, 3],
14+
});
715
const c = builder.matmul(a, b);
816
// Step 2: Compile it into an executable graph.
917
const graph = await builder.build({c});

code/samples/mul_add.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const operandType = {dataType: 'float32', dimensions: [2, 2]};
1+
const operandType = {dataType: 'float32', dimensions: [2, 2], shape: [2, 2]};
22
const context = await navigator.ml.createContext();
33
const builder = new MLGraphBuilder(context);
44
// 1. Create a computational graph 'C = 0.2 * A + B'.

code/samples/simple_graph.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const TENSOR_SIZE = 8;
1818
const builder = new MLGraphBuilder(context);
1919

2020
// Create MLOperandDescriptor object.
21-
const desc = {dataType: 'float32', dimensions: TENSOR_DIMS};
21+
const desc = {dataType: 'float32', dimensions: TENSOR_DIMS, shape: TENSOR_DIMS};
2222

2323
// constant1 is a constant MLOperand with the value 0.5.
2424
const constantBuffer1 = new Float32Array(TENSOR_SIZE).fill(0.5);

common/utils.js

+8-7
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ export async function buildConstantByNpy(builder, url, targetType = 'float32') {
104104
if (!dataTypeMap.has(npArray.dataType)) {
105105
throw new Error(`Data type ${npArray.dataType} is not supported.`);
106106
}
107-
const dimensions = npArray.shape;
107+
const shape = npArray.shape;
108108
let type = dataTypeMap.get(npArray.dataType).type;
109109
const TypedArrayConstructor = dataTypeMap.get(npArray.dataType).array;
110110
const dataView = new Uint8Array(npArray.data.buffer);
@@ -121,7 +121,8 @@ export async function buildConstantByNpy(builder, url, targetType = 'float32') {
121121
throw new Error(`Conversion from ${npArray.dataType} ` +
122122
`to ${targetType} is not supported.`);
123123
}
124-
return builder.constant({dataType: type, dimensions}, typedArray);
124+
return builder.constant(
125+
{dataType: type, dimensions: shape, shape}, typedArray);
125126
}
126127

127128
// Convert video frame to a canvas element
@@ -162,7 +163,7 @@ export function stopCameraStream(id, stream) {
162163
* input element.
163164
* inputOptions = {
164165
* inputLayout {String}, // input layout of tensor.
165-
* inputDimensions: {!Array<number>}, // dimensions of input tensor.
166+
* inputShape: {!Array<number>}, // shape of input tensor.
166167
* mean: {Array<number>}, // optional, mean values for processing the input
167168
* element. If not specified, it will be set to [0, 0, 0, 0].
168169
* std: {Array<number>}, // optional, std values for processing the input
@@ -190,16 +191,16 @@ export function stopCameraStream(id, stream) {
190191
* @return {Object} tensor, an object of input tensor.
191192
*/
192193
export function getInputTensor(inputElement, inputOptions) {
193-
const inputDimensions = inputOptions.inputDimensions;
194+
const inputShape = inputOptions.inputShape;
194195
const tensor = new Float32Array(
195-
inputDimensions.slice(1).reduce((a, b) => a * b));
196+
inputShape.slice(1).reduce((a, b) => a * b));
196197

197198
inputElement.width = inputElement.videoWidth ||
198199
inputElement.naturalWidth;
199200
inputElement.height = inputElement.videoHeight ||
200201
inputElement.naturalHeight;
201202

202-
let [channels, height, width] = inputDimensions.slice(1);
203+
let [channels, height, width] = inputShape.slice(1);
203204
const mean = inputOptions.mean || [0, 0, 0, 0];
204205
const std = inputOptions.std || [1, 1, 1, 1];
205206
const normlizationFlag = inputOptions.norm || false;
@@ -209,7 +210,7 @@ export function getInputTensor(inputElement, inputOptions) {
209210
const imageChannels = 4; // RGBA
210211
const drawOptions = inputOptions.drawOptions;
211212
if (inputLayout === 'nhwc') {
212-
[height, width, channels] = inputDimensions.slice(1);
213+
[height, width, channels] = inputShape.slice(1);
213214
}
214215
const canvasElement = document.createElement('canvas');
215216
canvasElement.width = width;

face_recognition/facenet_nchw.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export class FaceNetNchw {
1919
std: [127.5, 127.5, 127.5, 127.5],
2020
channelScheme: 'BGR',
2121
inputLayout: 'nchw',
22-
inputDimensions: [1, 3, 160, 160],
22+
inputShape: [1, 3, 160, 160],
2323
};
2424
this.postOptions = {
2525
distanceMetric: 'euclidean',
@@ -140,7 +140,8 @@ export class FaceNetNchw {
140140
this.builder_ = new MLGraphBuilder(this.context_);
141141
const input = this.builder_.input('input', {
142142
dataType: 'float32',
143-
dimensions: this.inputOptions.inputDimensions,
143+
dimensions: this.inputOptions.inputShape,
144+
shape: this.inputOptions.inputShape,
144145
});
145146

146147
const poolOptions = {windowDimensions: [3, 3], strides};

face_recognition/facenet_nhwc.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export class FaceNetNhwc {
1919
std: [127.5, 127.5, 127.5, 127.5],
2020
channelScheme: 'BGR',
2121
inputLayout: 'nhwc',
22-
inputDimensions: [1, 160, 160, 3],
22+
inputShape: [1, 160, 160, 3],
2323
};
2424
this.postOptions = {
2525
distanceMetric: 'euclidean',
@@ -141,7 +141,8 @@ export class FaceNetNhwc {
141141
this.builder_ = new MLGraphBuilder(this.context_);
142142
const input = this.builder_.input('input', {
143143
dataType: 'float32',
144-
dimensions: this.inputOptions.inputDimensions,
144+
dimensions: this.inputOptions.inputShape,
145+
shape: this.inputOptions.inputShape,
145146
});
146147

147148
const poolOptions = {windowDimensions: [3, 3], strides, layout: 'nhwc'};

face_recognition/main.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -375,9 +375,9 @@ async function main() {
375375
console.log('- Computing... ');
376376
// Do warm up
377377
const fdResults = await fdInstance.compute(new Float32Array(
378-
utils.sizeOfShape(fdInputOptions.inputDimensions)), fdOutputs);
378+
utils.sizeOfShape(fdInputOptions.inputShape)), fdOutputs);
379379
const frResults = await frInstance.compute(new Float32Array(
380-
utils.sizeOfShape(frInputOptions.inputDimensions)), frOutputs);
380+
utils.sizeOfShape(frInputOptions.inputShape)), frOutputs);
381381
fdOutputs = fdResults.outputs;
382382
frOutputs = frResults.outputs;
383383
for (let i = 0; i < numRuns; i++) {

facial_landmark_detection/face_landmark_nchw.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export class FaceLandmarkNchw {
1212
'/test-data/models/face_landmark_nchw/weights';
1313
this.inputOptions = {
1414
inputLayout: 'nchw',
15-
inputDimensions: [1, 3, 128, 128],
15+
inputShape: [1, 3, 128, 128],
1616
};
1717
}
1818

@@ -71,7 +71,8 @@ export class FaceLandmarkNchw {
7171
this.builder_ = new MLGraphBuilder(this.context_);
7272
const input = this.builder_.input('input', {
7373
dataType: 'float32',
74-
dimensions: this.inputOptions.inputDimensions,
74+
dimensions: this.inputOptions.inputShape,
75+
shape: this.inputOptions.inputShape,
7576
});
7677

7778
const poolOptions =

facial_landmark_detection/face_landmark_nhwc.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export class FaceLandmarkNhwc {
1212
'/test-data/models/face_landmark_nhwc/weights';
1313
this.inputOptions = {
1414
inputLayout: 'nhwc',
15-
inputDimensions: [1, 128, 128, 3],
15+
inputShape: [1, 128, 128, 3],
1616
};
1717
}
1818

@@ -72,7 +72,8 @@ export class FaceLandmarkNhwc {
7272
this.builder_ = new MLGraphBuilder(this.context_);
7373
const input = this.builder_.input('input', {
7474
dataType: 'float32',
75-
dimensions: this.inputOptions.inputDimensions,
75+
dimensions: this.inputOptions.inputShape,
76+
shape: this.inputOptions.inputShape,
7677
});
7778

7879
const poolOptions =

facial_landmark_detection/main.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -312,9 +312,9 @@ async function main() {
312312
console.log('- Computing... ');
313313
// Do warm up
314314
const fdResults = await fdInstance.compute(new Float32Array(
315-
utils.sizeOfShape(fdInputOptions.inputDimensions)), fdOutputs);
315+
utils.sizeOfShape(fdInputOptions.inputShape)), fdOutputs);
316316
const fldResults = await fldInstance.compute(new Float32Array(
317-
utils.sizeOfShape(fldInputOptions.inputDimensions)), fldOutputs);
317+
utils.sizeOfShape(fldInputOptions.inputShape)), fldOutputs);
318318
fdOutputs = fdResults.outputs;
319319
fldOutputs = fldResults.outputs;
320320
for (let i = 0; i < numRuns; i++) {

facial_landmark_detection/ssd_mobilenetv2_face_nchw.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export class SsdMobilenetV2FaceNchw {
1919
boxSize: 4,
2020
numClasses: 2,
2121
numBoxes: [1083, 600, 150, 54, 24, 6],
22-
inputDimensions: [1, 3, 300, 300],
22+
inputShape: [1, 3, 300, 300],
2323
};
2424
this.outputsInfo = {
2525
'biasAdd0': [1, 12, 19, 19],
@@ -115,7 +115,8 @@ ${nameArray[1]}`;
115115
this.builder_ = new MLGraphBuilder(this.context_);
116116
const input = this.builder_.input('input', {
117117
dataType: 'float32',
118-
dimensions: this.inputOptions.inputDimensions,
118+
dimensions: this.inputOptions.inputShape,
119+
shape: this.inputOptions.inputShape,
119120
});
120121

121122
const bottleneck0 = this.buildLinearBottleneck_(

facial_landmark_detection/ssd_mobilenetv2_face_nhwc.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export class SsdMobilenetV2FaceNhwc {
1919
boxSize: 4,
2020
numClasses: 2,
2121
numBoxes: [1083, 600, 150, 54, 24, 6],
22-
inputDimensions: [1, 300, 300, 3],
22+
inputShape: [1, 300, 300, 3],
2323
};
2424
this.outputsInfo = {
2525
'biasAdd0': [1, 19, 19, 12],
@@ -127,7 +127,8 @@ ${nameArray[1]}`;
127127
this.builder_ = new MLGraphBuilder(this.context_);
128128
const input = this.builder_.input('input', {
129129
dataType: 'float32',
130-
dimensions: this.inputOptions.inputDimensions,
130+
dimensions: this.inputOptions.inputShape,
131+
shape: this.inputOptions.inputShape,
131132
});
132133

133134
const bottleneck0 = this.buildLinearBottleneck_(

image_classification/efficientnet_fp16_nchw.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ export class EfficientNetFP16Nchw {
1616
norm: true,
1717
inputLayout: 'nchw',
1818
labelUrl: './labels/labels1000.txt',
19-
inputDimensions: [1, 3, 224, 224],
19+
inputShape: [1, 3, 224, 224],
2020
};
21-
this.outputDimensions = [1, 1000];
21+
this.outputShape = [1, 1000];
2222
}
2323

2424
async buildConv_(input, name, blockName, clip = false, options = {}) {
@@ -77,7 +77,8 @@ export class EfficientNetFP16Nchw {
7777
this.builder_ = new MLGraphBuilder(this.context_);
7878
let data = this.builder_.input('input', {
7979
dataType: 'float32',
80-
dimensions: this.inputOptions.inputDimensions,
80+
dimensions: this.inputOptions.inputShape,
81+
shape: this.inputOptions.inputShape,
8182
});
8283
data = this.builder_.cast(data, 'float16');
8384
// Block 0

image_classification/main.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ async function main() {
335335
inputOptions = netInstance.inputOptions;
336336
labels = await fetchLabels(inputOptions.labelUrl);
337337
outputBuffer =
338-
new Float32Array(utils.sizeOfShape(netInstance.outputDimensions));
338+
new Float32Array(utils.sizeOfShape(netInstance.outputShape));
339339
isFirstTimeLoad = false;
340340
console.log(`- Model name: ${modelName}, Model layout: ${layout} -`);
341341
// UI shows model loading progress

image_classification/mobilenet_nchw.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ export class MobileNetV2Nchw {
2525
norm: true,
2626
inputLayout: 'nchw',
2727
labelUrl: './labels/labels1000.txt',
28-
inputDimensions: [1, 3, 224, 224],
28+
inputShape: [1, 3, 224, 224],
2929
};
30-
this.outputDimensions = [1, 1000];
30+
this.outputShape = [1, 1000];
3131
}
3232

3333
async buildConv_(input, name, relu6 = true, options = {}) {
@@ -91,7 +91,8 @@ export class MobileNetV2Nchw {
9191
this.builder_ = new MLGraphBuilder(this.context_);
9292
let data = this.builder_.input('input', {
9393
dataType: 'float32',
94-
dimensions: this.inputOptions.inputDimensions,
94+
dimensions: this.inputOptions.inputShape,
95+
shape: this.inputOptions.inputShape,
9596
});
9697
if (this.dataType_ === 'float16') {
9798
data = this.builder_.cast(data, 'float16');

image_classification/mobilenet_nhwc.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ export class MobileNetV2Nhwc {
1818
std: [127.5, 127.5, 127.5],
1919
inputLayout: 'nhwc',
2020
labelUrl: './labels/labels1001.txt',
21-
inputDimensions: [1, 224, 224, 3],
21+
inputShape: [1, 224, 224, 3],
2222
};
23-
this.outputDimensions = [1, 1001];
23+
this.outputShape = [1, 1001];
2424
}
2525

2626
async buildConv_(input, weightsSubName, biasSubName, relu6, options) {
@@ -89,7 +89,8 @@ export class MobileNetV2Nhwc {
8989
const filterLayout = 'ohwi';
9090
const input = this.builder_.input('input', {
9191
dataType: 'float32',
92-
dimensions: this.inputOptions.inputDimensions,
92+
dimensions: this.inputOptions.inputShape,
93+
shape: this.inputOptions.inputShape,
9394
});
9495
const conv0 = this.buildConv_(
9596
input, '90', 'Conv_Conv2D', true, {strides, autoPad, filterLayout});

image_classification/resnet50v1_fp16_nchw.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ export class ResNet50V1FP16Nchw {
1616
norm: true,
1717
inputLayout: 'nchw',
1818
labelUrl: './labels/labels1000.txt',
19-
inputDimensions: [1, 3, 224, 224],
19+
inputShape: [1, 3, 224, 224],
2020
};
21-
this.outputDimensions = [1, 1000];
21+
this.outputShape = [1, 1000];
2222
}
2323

2424
async buildConv_(input, name, stageName, relu, options = undefined) {
@@ -78,7 +78,8 @@ export class ResNet50V1FP16Nchw {
7878
this.builder_ = new MLGraphBuilder(this.context_);
7979
let data = this.builder_.input('input', {
8080
dataType: 'float32',
81-
dimensions: this.inputOptions.inputDimensions,
81+
dimensions: this.inputOptions.inputShape,
82+
shape: this.inputOptions.inputShape,
8283
});
8384
data = this.builder_.cast(data, 'float16');
8485
const conv1 = await this.buildConv_(

image_classification/resnet50v2_nchw.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ export class ResNet50V2Nchw {
1616
norm: true,
1717
inputLayout: 'nchw',
1818
labelUrl: './labels/labels1000.txt',
19-
inputDimensions: [1, 3, 224, 224],
19+
inputShape: [1, 3, 224, 224],
2020
};
21-
this.outputDimensions = [1, 1000];
21+
this.outputShape = [1, 1000];
2222
}
2323

2424
async buildConv_(input, name, stageName, options = undefined) {
@@ -100,7 +100,8 @@ export class ResNet50V2Nchw {
100100
this.builder_ = new MLGraphBuilder(this.context_);
101101
const data = this.builder_.input('input', {
102102
dataType: 'float32',
103-
dimensions: this.inputOptions.inputDimensions,
103+
dimensions: this.inputOptions.inputShape,
104+
shape: this.inputOptions.inputShape,
104105
});
105106
const bn1 = this.buildBatchNorm_(data, '0', '', false);
106107
const conv0 = this.buildConv_(

image_classification/resnet50v2_nhwc.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ export class ResNet50V2Nhwc {
1919
std: [127.5, 127.5, 127.5],
2020
inputLayout: layout,
2121
labelUrl: './labels/labels1001.txt',
22-
inputDimensions: [1, 224, 224, 3],
22+
inputShape: [1, 224, 224, 3],
2323
};
24-
this.outputDimensions = [1, 1001];
24+
this.outputShape = [1, 1001];
2525
}
2626

2727
async buildConv_(input, nameIndices, options = {}, relu = true) {
@@ -122,7 +122,8 @@ export class ResNet50V2Nhwc {
122122
this.builder_ = new MLGraphBuilder(this.context_);
123123
const input = this.builder_.input('input', {
124124
dataType: 'float32',
125-
dimensions: this.inputOptions.inputDimensions,
125+
dimensions: this.inputOptions.inputShape,
126+
shape: this.inputOptions.inputShape,
126127
});
127128
const conv1 = await this.buildConv_(
128129
input, ['', '', '1'], {strides, padding: [3, 3, 3, 3]}, false);

image_classification/squeezenet_nchw.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ export class SqueezeNetNchw {
1616
norm: true,
1717
inputLayout: 'nchw',
1818
labelUrl: './labels/labels1000.txt',
19-
inputDimensions: [1, 3, 224, 224],
19+
inputShape: [1, 3, 224, 224],
2020
};
21-
this.outputDimensions = [1, 1000];
21+
this.outputShape = [1, 1000];
2222
}
2323

2424
async buildConv_(input, name, options = {}) {
@@ -45,7 +45,8 @@ export class SqueezeNetNchw {
4545
this.builder_ = new MLGraphBuilder(this.context_);
4646
const data = this.builder_.input('input', {
4747
dataType: 'float32',
48-
dimensions: this.inputOptions.inputDimensions,
48+
dimensions: this.inputOptions.inputShape,
49+
shape: this.inputOptions.inputShape,
4950
});
5051
const conv0 = this.buildConv_(data, 'conv0', {strides: [2, 2]});
5152
const pool0 = this.builder_.maxPool2d(

0 commit comments

Comments
 (0)