Skip to content

Commit 7f8f2f3

Browse files
authored
Merge pull request #245 from huningxin/fix_activation
Replace fused activations with standalone ones
2 parents fc9f030 + d874372 commit 7f8f2f3

16 files changed

+41
-114
lines changed

face_recognition/facenet_nhwc.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,6 @@ export class FaceNetNhwc {
4343
bias: bias,
4444
};
4545
}
46-
if (relu) {
47-
options.activation = this.builder_.relu();
48-
}
4946
// WebNN spec drops autoPad support, compute the explicit padding instead.
5047
if (options.autoPad == 'same-upper') {
5148
options.padding =
@@ -54,7 +51,8 @@ export class FaceNetNhwc {
5451
/* ohwi */[weights.shape()[1], weights.shape()[2]],
5552
options.strides, options.dilations, options.autoPad);
5653
}
57-
return this.builder_.conv2d(input, weights, options);
54+
const conv2d = this.builder_.conv2d(input, weights, options);
55+
return relu ? this.builder_.relu(conv2d) : conv2d;
5856
}
5957

6058
async buildBlock35_(input, indice) {

facial_landmark_detection/face_landmark_nchw.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ export class FaceLandmarkNchw {
3636
const bias = buildConstantByNpy(this.builder_, biasName);
3737
const options = {
3838
bias: await bias,
39-
activation: this.builder_.relu(),
4039
};
41-
return this.builder_.conv2d(await input, await weights, options);
40+
const conv2d = this.builder_.conv2d(await input, await weights, options);
41+
return this.builder_.relu(conv2d);
4242
}
4343

4444
async buildGemm_(input, namePrefix, relu = false, reshapeSize) {

facial_landmark_detection/face_landmark_nhwc.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ export class FaceLandmarkNhwc {
3838
inputLayout: 'nhwc',
3939
filterLayout: 'ohwi',
4040
bias: await bias,
41-
activation: this.builder_.relu(),
4241
};
43-
return this.builder_.conv2d(await input, await weights, options);
42+
const conv2d = this.builder_.conv2d(await input, await weights, options);
43+
return this.builder_.relu(conv2d);
4444
}
4545

4646
async buildFullyConnected_(input, namePrefix, relu = false, reshapeSize) {

facial_landmark_detection/ssd_mobilenetv2_face_nchw.js

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -74,19 +74,11 @@ ${nameArray[1]}`;
7474
/* oihw */[weightsShape[2], weightsShape[3]],
7575
options.strides, options.dilations, 'same-upper');
7676
options.bias = await bias;
77+
const conv2d = this.builder_.conv2d(await input, await weights, options);
7778
if (clip) {
78-
// TODO: Set clamp activation to options once it's supported in
79-
// WebNN DML backend.
80-
// Implement `clip` by `clamp` of WebNN API
81-
if (this.deviceType_ == 'gpu') {
82-
return this.builder_.clamp(
83-
this.builder_.conv2d(await input, await weights, options),
84-
{minValue: 0, maxValue: 6});
85-
} else {
86-
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
87-
}
79+
return this.builder_.clamp(conv2d, {minValue: 0, maxValue: 6});
8880
}
89-
return this.builder_.conv2d(await input, await weights, options);
81+
return conv2d;
9082
}
9183

9284
async buildLinearBottleneck_(

facial_landmark_detection/ssd_mobilenetv2_face_nhwc.js

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -86,19 +86,11 @@ ${nameArray[1]}`;
8686
/* nhwc */[inputShape[1], inputShape[2]],
8787
/* ohwi or ihwo */[weightsShape[1], weightsShape[2]],
8888
options.strides, options.dilations, 'same-upper');
89+
const conv2d = this.builder_.conv2d(await input, await weights, options);
8990
if (relu6) {
90-
// TODO: Set clamp activation to options once it's supported in
91-
// WebNN DML backend.
92-
// Implement `clip` by `clamp` of WebNN API
93-
if (this.deviceType_ == 'gpu') {
94-
return this.builder_.clamp(
95-
this.builder_.conv2d(await input, await weights, options),
96-
{minValue: 0, maxValue: 6});
97-
} else {
98-
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
99-
}
91+
return this.builder_.clamp(conv2d, {minValue: 0, maxValue: 6});
10092
}
101-
return this.builder_.conv2d(await input, await weights, options);
93+
return conv2d;
10294
}
10395

10496
async buildLinearBottleneck_(

image_classification/mobilenet_nchw.js

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,19 +47,11 @@ export class MobileNetV2Nchw {
4747
}
4848
}
4949

50+
const conv2d = this.builder_.conv2d(await input, await weights, options);
5051
if (relu6) {
51-
// TODO: Set clamp activation to options once it's supported in
52-
// WebNN DML backend.
53-
// Implement `clip` by `clamp` of WebNN API
54-
if (this.deviceType_ == 'gpu' || this.deviceType_ == 'npu') {
55-
return this.builder_.clamp(
56-
this.builder_.conv2d(await input, await weights, options),
57-
{minValue: 0, maxValue: 6});
58-
} else {
59-
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
60-
}
52+
return this.builder_.clamp(conv2d, {minValue: 0, maxValue: 6});
6153
}
62-
return this.builder_.conv2d(await input, await weights, options);
54+
return conv2d;
6355
}
6456

6557
async buildGemm_(input, name) {

image_classification/mobilenet_nhwc.js

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,19 +38,11 @@ export class MobileNetV2Nhwc {
3838
/* ohwi or ihwo */[weights.shape()[1], weights.shape()[2]],
3939
options.strides, options.dilations, options.autoPad);
4040
}
41+
const conv2d = this.builder_.conv2d(await input, weights, options);
4142
if (relu6) {
42-
// TODO: Set clamp activation to options once it's supported in
43-
// WebNN DML backend.
44-
// Implement `clip` by `clamp` of WebNN API
45-
if (this.deviceType_ == 'gpu') {
46-
return this.builder_.clamp(
47-
this.builder_.conv2d(await input, weights, options),
48-
{minValue: 0, maxValue: 6});
49-
} else {
50-
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
51-
}
43+
return this.builder_.clamp(conv2d, {minValue: 0, maxValue: 6});
5244
}
53-
return this.builder_.conv2d(input, weights, options);
45+
return conv2d;
5446
}
5547

5648
async buildLinearBottleneck_(input, weightsNameArray, biasName, dwiseOptions, shortcut = true) {

image_classification/resnet50v1_fp16_nchw.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,9 @@ export class ResNet50V1FP16Nchw {
3333
'float16');
3434
options.bias = await buildConstantByNpy(this.builder_, prefix + '_b.npy',
3535
'float16');
36-
if (relu) {
37-
options.activation = this.builder_.relu();
38-
}
3936

40-
return this.builder_.conv2d(await input, await weight, options);
37+
const conv2d = this.builder_.conv2d(await input, await weight, options);
38+
return relu ? this.builder_.relu(conv2d) : conv2d;
4139
}
4240

4341
async buildGemm_(input, name) {

image_classification/resnet50v2_nchw.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,13 @@ export class ResNet50V2Nchw {
5151
const mean = buildConstantByNpy(this.builder_, meanName);
5252
const variance = buildConstantByNpy(this.builder_, varName);
5353
const options = {scale: await scale, bias: await bias};
54-
if (relu) {
55-
options.activation = this.builder_.relu();
56-
}
57-
return this.builder_.batchNormalization(
54+
const batchnorm = this.builder_.batchNormalization(
5855
await input,
5956
await mean,
6057
await variance,
6158
options,
6259
);
60+
return relu ? this.builder_.relu(batchnorm) : batchnorm;
6361
}
6462

6563
async buildGemm_(input, name) {

image_classification/resnet50v2_nhwc.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,6 @@ export class ResNet50V2Nhwc {
4848
options.inputLayout = layout;
4949
options.filterLayout = 'ohwi';
5050
options.bias = await bias;
51-
if (relu) {
52-
options.activation = this.builder_.relu();
53-
}
5451
// WebNN spec drops autoPad support, compute the explicit padding instead.
5552
if (options.autoPad == 'same-upper') {
5653
options.padding =
@@ -59,7 +56,8 @@ export class ResNet50V2Nhwc {
5956
/* ohwi */[weights.shape()[1], weights.shape()[2]],
6057
options.strides, options.dilations, options.autoPad);
6158
}
62-
return this.builder_.conv2d(await input, weights, options);
59+
const conv2d = this.builder_.conv2d(await input, weights, options);
60+
return relu ? this.builder_.relu(conv2d) : conv2d;
6361
}
6462

6563
async buildFusedBatchNorm_(input, nameIndices) {

image_classification/squeezenet_nchw.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ export class SqueezeNetNchw {
2828
const biasName = prefix + '_bias.npy';
2929
const bias = buildConstantByNpy(this.builder_, biasName);
3030
options.bias = await bias;
31-
options.activation = this.builder_.relu();
32-
return this.builder_.conv2d(await input, await weights, options);
31+
const conv2d = this.builder_.conv2d(await input, await weights, options);
32+
return this.builder_.relu(conv2d);
3333
}
3434

3535
async buildFire_(input, convName, conv1x1Name, conv3x3Name) {

image_classification/squeezenet_nhwc.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ export class SqueezeNetNhwc {
2929
options.inputLayout = 'nhwc';
3030
options.filterLayout = 'ohwi';
3131
options.bias = await bias;
32-
options.activation = this.builder_.relu();
3332
// WebNN spec drops autoPad support, compute the explicit padding instead.
3433
if (options.autoPad == 'same-upper') {
3534
options.padding =
@@ -38,7 +37,8 @@ export class SqueezeNetNhwc {
3837
/* ohwi */[weights.shape()[1], weights.shape()[2]],
3938
options.strides, options.dilations, options.autoPad);
4039
}
41-
return this.builder_.conv2d(await input, weights, options);
40+
const conv2d = this.builder_.conv2d(await input, weights, options);
41+
return this.builder_.relu(conv2d);
4242
}
4343

4444
async buildFire_(input, name) {

object_detection/ssd_mobilenetv1_nchw.js

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -68,19 +68,11 @@ ${nameArray[1]}_BatchNorm_batchnorm`;
6868
/* oihw */[weights.shape()[2], weights.shape()[3]],
6969
options.strides, options.dilations, 'same-upper');
7070
options.bias = bias;
71+
const conv2d = this.builder_.conv2d(input, weights, options);
7172
if (relu6) {
72-
// TODO: Set clamp activation to options once it's supported in
73-
// WebNN DML backend.
74-
// Implement `clip` by `clamp` of WebNN API
75-
if (this.deviceType_ == 'gpu' || this.deviceType_ == 'npu') {
76-
return this.builder_.clamp(
77-
this.builder_.conv2d(input, weights, options),
78-
{minValue: 0, maxValue: 6});
79-
} else {
80-
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
81-
}
73+
return this.builder_.clamp(conv2d, {minValue: 0, maxValue: 6});
8274
}
83-
return this.builder_.conv2d(input, weights, options);
75+
return conv2d;
8476
}
8577

8678
async load(contextOptions) {

object_detection/ssd_mobilenetv1_nhwc.js

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -74,19 +74,11 @@ ${nameArray[1]}_BatchNorm_batchnorm`;
7474
/* nhwc */[input.shape()[1], input.shape()[2]],
7575
/* ohwi or ihwo */[weights.shape()[1], weights.shape()[2]],
7676
options.strides, options.dilations, 'same-upper');
77+
const conv2d = this.builder_.conv2d(input, weights, options);
7778
if (relu6) {
78-
// TODO: Set clamp activation to options once it's supported in
79-
// WebNN DML backend.
80-
// Implement `clip` by `clamp` of WebNN API
81-
if (this.deviceType_ == 'gpu') {
82-
return this.builder_.clamp(
83-
this.builder_.conv2d(input, weights, options),
84-
{minValue: 0, maxValue: 6});
85-
} else {
86-
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
87-
}
79+
return this.builder_.clamp(conv2d, {minValue: 0, maxValue: 6});
8880
}
89-
return this.builder_.conv2d(input, weights, options);
81+
return conv2d;
9082
}
9183

9284
async load(contextOptions) {

semantic_segmentation/deeplabv3_mnv2_nchw.js

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -45,23 +45,14 @@ export class DeepLabV3MNV2Nchw {
4545
const bias = buildConstantByNpy(this.builder_, biasName);
4646

4747
options.bias = await bias;
48+
const conv2d = this.builder_.conv2d(await input, await weights, options);
4849
if (activation === 'relu6') {
49-
// TODO: Set clamp activation to options once it's supported in
50-
// WebNN DML backend.
51-
// Implement `clip` by `clamp` of WebNN API
52-
if (this.deviceType_ == 'gpu') {
53-
return this.builder_.clamp(
54-
this.builder_.conv2d(await input, await weights, options),
55-
{minValue: 0, maxValue: 6});
56-
} else {
57-
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
58-
}
50+
return this.builder_.clamp(conv2d, {minValue: 0, maxValue: 6});
5951
} else if (activation === 'relu') {
60-
options.activation = this.builder_.relu();
52+
return this.builder_.relu(conv2d);
6153
} else {
62-
options.activation = undefined;
54+
return conv2d;
6355
}
64-
return this.builder_.conv2d(await input, await weights, options);
6556
}
6657

6758
async buildLinearBottleneck_(input, nameArray, dwiseOptions, shortcut = true) {

semantic_segmentation/deeplabv3_mnv2_nhwc.js

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,19 +47,11 @@ export class DeepLabV3MNV2Nhwc {
4747
/* ohwi or ihwo */[weights.shape()[1], weights.shape()[2]],
4848
options.strides, options.dilations, 'same-upper');
4949
options.bias = bias;
50+
const conv2d = this.builder_.conv2d(input, weights, options);
5051
if (relu6) {
51-
// TODO: Set clamp activation to options once it's supported in
52-
// WebNN DML backend.
53-
// Implement `clip` by `clamp` of WebNN API
54-
if (this.deviceType_ == 'gpu') {
55-
return this.builder_.clamp(
56-
this.builder_.conv2d(input, weights, options),
57-
{minValue: 0, maxValue: 6});
58-
} else {
59-
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
60-
}
52+
return this.builder_.clamp(conv2d, {minValue: 0, maxValue: 6});
6153
}
62-
return this.builder_.conv2d(input, weights, options);
54+
return conv2d;
6355
}
6456

6557
async buildLinearBottleneck_(

0 commit comments

Comments
 (0)