diff --git a/webnn/resources/test_data/softmax.json b/webnn/resources/test_data/softmax.json new file mode 100644 index 000000000000000..b19ce4059121bff --- /dev/null +++ b/webnn/resources/test_data/softmax.json @@ -0,0 +1,70 @@ +{ + "tests": [ + { + "name": "softmax float32 2D tensor", + "inputs": { + "x": { + "shape": [4, 6], + "data": [ + -9.602943250149636, + 5.353947088147631, + 4.982506021190005, + -1.8709681620943286, + 2.275207739606868, + -1.9403444022539098, + 1.8985638253724968, + 1.7877445512108103, + -7.243864108734894, + 7.827657028853274, + -2.4196847673132726, + -8.018804523844905, + -3.1493873901132474, + 7.674345195428224, + -5.183967275728079, + -7.301743057626533, + -7.121610082852072, + -8.29701166999875, + -5.77890866334104, + -9.76213424697228, + 7.332167409724249, + 3.9077721241449215, + -5.2970783047100545, + 5.0440509491607965 + ], + "type": "float32" + } + }, + "expected": { + "name": "output", + "shape": [4, 6], + "data": [ + 1.8385014755040174e-7, + 0.575650691986084, + 0.3970489799976349, + 0.0004191970219835639, + 0.026489850133657455, + 0.0003911005624104291, + 0.00264744833111763, + 0.00236973213031888, + 2.833488679243601e-7, + 0.9949471354484558, + 0.00003527247827150859, + 1.3054766156983533e-7, + 0.000019920609702239744, + 0.9999766945838928, + 0.0000026043292109534377, + 3.1329790317613515e-7, + 3.7513549955292547e-7, + 1.1580249292819644e-7, + 0.0000017836379129221314, + 3.322107744452296e-8, + 0.8818095922470093, + 0.028719622641801834, + 0.000002887773234760971, + 0.08946608752012253 + ], + "type": "float32" + } + } + ] +} \ No newline at end of file diff --git a/webnn/resources/utils.js b/webnn/resources/utils.js index 7dbea09096f3809..4eac139c8ad2fa8 100644 --- a/webnn/resources/utils.js +++ b/webnn/resources/utils.js @@ -60,10 +60,23 @@ const getExpectedData = (resources, outputName) => { return data; }; +/** + * Get ULP tolerance of softmax operation. + * @param {Object} resources - Resources used for building a graph + * @returns {Number} A tolerance number + */ +const getSoftmaxPrecisionTolerance = (resources) => { + // Compute the softmax values of the 2-D input tensor along axis 1. + const inputShape = resources.inputs[Object.keys(resources.inputs)[0]].shape; + const tolerance = inputShape[1] * 2 + 3; + return tolerance; +}; + // Refer to precision metrics on https://github.com/webmachinelearning/webnn/issues/265#issuecomment-1256242643 const PrecisionMetrics = { clamp: {ULP: {float32: 0, float16: 0}}, concat: {ULP: {float32: 0, float16: 0}}, + softmax: {ULP: {float32: getSoftmaxPrecisionTolerance, float16: getSoftmaxPrecisionTolerance}}, }; /** @@ -79,7 +92,7 @@ const getPrecisonTolerance = (operationName, metricType, resources) => { let tolerance = PrecisionMetrics[operationName][metricType][precisionType]; // If the tolerance is dynamic, then evaluate the function to get the value. if (tolerance instanceof Function) { - tolerance = tolerance(resources, operationName); + tolerance = tolerance(resources); } return tolerance; }; diff --git a/webnn/softmax.https.any.js b/webnn/softmax.https.any.js new file mode 100644 index 000000000000000..91afc2838516f9c --- /dev/null +++ b/webnn/softmax.https.any.js @@ -0,0 +1,10 @@ +// META: title=test WebNN API softmax operation +// META: global=window,dedicatedworker +// META: script=./resources/utils.js +// META: timeout=long + +'use strict'; + +// https://webmachinelearning.github.io/webnn/#api-mlgraphbuilder-softmax + +testWebNNOperation('softmax', '/webnn/resources/test_data/softmax.json', buildOperationWithSingleInput); \ No newline at end of file