From 8271f8025373a0861661033993d2cd09301d85d1 Mon Sep 17 00:00:00 2001 From: BruceDai Date: Wed, 4 Sep 2024 14:33:49 +0800 Subject: [PATCH 1/2] Implement dequantizeLinear fixes #93 --- src/dequantize_linear.js | 16 ++++ test/dequantize_linear_test.js | 147 +++++++++++++++++++++++++++++++++ 2 files changed, 163 insertions(+) create mode 100644 src/dequantize_linear.js create mode 100644 test/dequantize_linear_test.js diff --git a/src/dequantize_linear.js b/src/dequantize_linear.js new file mode 100644 index 0000000..888c7f7 --- /dev/null +++ b/src/dequantize_linear.js @@ -0,0 +1,16 @@ +'use strict'; + +import {mul, sub} from './binary.js'; + +/** + * Elementwise operator to scale a low precision integer (typically uint8 with a zero-point bias) + * to floating point. + * The calculation follows the expression (input - zeroPoint) * scale. + * @param {Tensor} input + * @param {Tensor} scale + * @param {Tensor} zeroPoint + * @return {Tensor} + */ +export function dequantizeLinear(input, scale, zeroPoint) { + return mul(sub(input, zeroPoint), scale); +} diff --git a/test/dequantize_linear_test.js b/test/dequantize_linear_test.js new file mode 100644 index 0000000..d842e0a --- /dev/null +++ b/test/dequantize_linear_test.js @@ -0,0 +1,147 @@ +'use strict'; + +import {dequantizeLinear} from '../src/dequantize_linear.js'; +import {Tensor} from '../src/lib/tensor.js'; +import * as utils from './utils.js'; + +describe('test dequantizeLinear', function() { + function testDequantizeLinear(input, scale, zeroPoint, expected) { + const inputTensor = new Tensor(input.shape, input.value); + const scaleTensor = new Tensor(scale.shape, scale.value); + const zeroPointTensor = new Tensor(zeroPoint.shape, zeroPoint.value); + const outputTensor = dequantizeLinear(inputTensor, scaleTensor, zeroPointTensor); + utils.checkShape(outputTensor, expected.shape); + utils.checkValue(outputTensor, expected.value); + } + + + it('dequantizeLinear 1D broadcasting scale and zeroPoint', function() { + testDequantizeLinear( + { // input + shape: [4], + value: [0, 3, 128, 255], + }, + { // scale + shape: [1], + value: [2], + }, + { // zeroPoint of uint8 + shape: [1], + value: [128], + }, + { // expected + shape: [4], + value: [-256, -250, 0, 254], + }, + ); + }); + + it('dequantizeLinear 2D', function() { + testDequantizeLinear( + { // input + shape: [3, 4], + value: [ + 0, 1, 2, 3, + 0, 1, 2, 3, + 0, 10, 20, 30, + ], + }, + { // scale + shape: [3, 4], + value: [ + 1, 1, 1, 1, + 2, 2, 2, 2, + 4, 4, 4, 4, + ], + }, + { // zeroPoint + shape: [3, 4], + value: [ + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + ], + }, + { // expected + shape: [3, 4], + value: [ + 0, 1, 2, 3, + 0, 2, 4, 6, + 0, 40, 80, 120, + ], + }, + ); + }); + + it('dequantizeLinear 2D broadcasting scale and zeroPoint', function() { + testDequantizeLinear( + { // input + shape: [3, 4], + value: [ + 0, 1, 2, 3, + 0, 1, 2, 3, + 0, 10, 20, 30, + ], + }, + { // scale + shape: [3, 1], + value: [ + 1, + 2, + 4, + ], + }, + { // zeroPoint + shape: [3, 1], + value: [ + 0, + 0, + 0, + ], + }, + { // expected + shape: [3, 4], + value: [ + 0, 1, 2, 3, + 0, 2, 4, 6, + 0, 40, 80, 120, + ], + }, + ); + }); + + it('dequantizeLinear 4D broadcasting scale and zeroPoint', function() { + testDequantizeLinear( + { // input + shape: [1, 1, 3, 4], + value: [ + 0, 1, 2, 3, + 0, 1, 2, 3, + 0, 10, 20, 30, + ], + }, + { // scale + shape: [3, 1], + value: [ + 1, + 2, + 4, + ], + }, + { // zeroPoint + shape: [1], + value: [ + 0, + ], + }, + { // expected + shape: [1, 1, 3, 4], + value: [ + 0, 1, 2, 3, + 0, 2, 4, 6, + 0, 40, 80, 120, + ], + }, + ); + }); +}); From 58aba22eb11a6b37d8ac09406e786d8e8bee6185 Mon Sep 17 00:00:00 2001 From: BruceDai Date: Thu, 5 Sep 2024 20:31:07 +0800 Subject: [PATCH 2/2] addressed comments --- test/dequantize_linear_test.js | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/test/dequantize_linear_test.js b/test/dequantize_linear_test.js index d842e0a..275f416 100644 --- a/test/dequantize_linear_test.js +++ b/test/dequantize_linear_test.js @@ -14,6 +14,26 @@ describe('test dequantizeLinear', function() { utils.checkValue(outputTensor, expected.value); } + it('dequantizeLinear 0D', function() { + testDequantizeLinear( + { // input + shape: [], + value: [255], + }, + { // scale + shape: [], + value: [2], + }, + { // zeroPoint of uint8 + shape: [], + value: [128], + }, + { // expected + shape: [], + value: [254], + }, + ); + }); it('dequantizeLinear 1D broadcasting scale and zeroPoint', function() { testDequantizeLinear( @@ -94,17 +114,17 @@ describe('test dequantizeLinear', function() { { // zeroPoint shape: [3, 1], value: [ - 0, - 0, - 0, + 1, + 2, + 3, ], }, { // expected shape: [3, 4], value: [ - 0, 1, 2, 3, - 0, 2, 4, 6, - 0, 40, 80, 120, + -1, 0, 1, 2, + -4, -2, 0, 2, + -12, 28, 68, 108, ], }, );