Skip to content

Commit

Permalink
NNotepad: fix load(), add zeros(), improve tensor output display (web…
Browse files Browse the repository at this point in the history
…machinelearning#247)

- The load() helper was broken when the scripts were converted to modules, and also when array parsing was updated. Oops! Fix it.
- Add zeros() helper that creates a zero-initized tensor of the given shape. Useful for testing shape display.
- Ensure tensor output spaces n-dimensions tensors the same as numpy - more spaces between each layer.
- Ensure tensor output handles 0-sized dimensions.
  • Loading branch information
inexorabletash authored Jun 11, 2024
1 parent 1e0ad50 commit 919aa9f
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 9 deletions.
1 change: 1 addition & 0 deletions nnotepad/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ The default [data type](https://webmachinelearning.github.io/webnn/#enumdef-mlop
In addition to WebNN [`MLGraphBuilder`](https://webmachinelearning.github.io/webnn/#mlgraphbuilder) methods, you can use these helpers:

* **load(_url_, _shape_, _dataType_)** - fetch a tensor resource. Must be served with appropriate [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) headers. Example: `load('https://www.random.org/cgi-bin/randbyte?nbytes=256', [16, 16], 'uint8')`
* **zeros(_shape_, _dataType_)** - constant zero-filled tensor of the given shape. Example: `zeros([2,2,2,2], 'int8')`


# Details & Gotchas
Expand Down
7 changes: 2 additions & 5 deletions nnotepad/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ function explain(outputs) {

const width = [...buffer]
.map((n) => String(n).length)
.reduce((a, b) => Math.max(a, b));
.reduce((a, b) => Math.max(a, b), 0);

const out = [];
let bufferIndex = 0;
Expand All @@ -118,10 +118,7 @@ function explain(outputs) {
if (i !== shape[dim] - 1) {
out.push(', ');
if (dim + 1 !== shape.length) {
if (dim + 2 !== shape.length) {
out.push('\n');
}
out.push('\n');
out.push('\n'.repeat(shape.length - dim - 1));
out.push(' '.repeat(indent + dim + 1));
}
}
Expand Down
25 changes: 21 additions & 4 deletions nnotepad/js/nnotepad.js
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ export class NNotepad {
.join('');

const AsyncFunction = async function() {}.constructor;
return [new AsyncFunction(['_'], src), src];
return [new AsyncFunction(['_', 'Util'], src), src];

function serializeLine(line, last) {
const expr = serializeExpr(line.expr);
Expand Down Expand Up @@ -476,18 +476,35 @@ export class NNotepad {
if (url.type !== 'string') {
throw new TypeError('load(): expected string');
}
if (shape.type !== 'tensor') {
if (shape.type !== 'array') {
throw new TypeError('load(): expected array');
}
if (dataType.type !== 'string') {
throw new TypeError('load(): expected string');
}
const dims = shape.value.map((expr) => expr.value);
const ctor = WebNNUtil.dataTypeToBufferType(dataType.value);
return `_.constant({dataType: "${dataType.value}", dimensions: ${
Util.stringify(shape.value)}}, new ${
Util.stringify(dims)}}, new ${
ctor.name}(await Util.loadBuffer(${Util.stringify(url.value)})))`;
}

if (name === 'zeros') {
const [shape, dataType] = args;
if (shape.type !== 'array') {
throw new TypeError('zeros(): expected array');
}
if (dataType.type !== 'string') {
throw new TypeError('zeros(): expected string');
}
const dims = shape.value.map((expr) => expr.value);
const ctor = WebNNUtil.dataTypeToBufferType(dataType.value);
const len = dims.reduce((a, b) => a * b, 1);
return `_.constant({dataType: "${dataType.value}", dimensions: ${
Util.stringify(dims)}}, new ${
ctor.name}(${len}))`;
}

return `_.${name}(${
args.map(
(arg, index) => serializeExpr(
Expand All @@ -509,7 +526,7 @@ export class NNotepad {
const builder = new self.MLGraphBuilder(context);

const outputOperands = [];
let output = await builderFunc(builder);
let output = await builderFunc(builder, Util);
if (output instanceof self.MLOperand) {
// TODO: remove try/catch once all back-ends support `identity()`.
try {
Expand Down
1 change: 1 addition & 0 deletions nnotepad/res/docs.html
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ <h1>Helpers</h1>
<p>In addition to WebNN <a href="https://webmachinelearning.github.io/webnn/#mlgraphbuilder"><code>MLGraphBuilder</code></a> methods, you can use these helpers:</p>
<ul>
<li><strong>load(<em>url</em>, <em>shape</em>, <em>dataType</em>)</strong> - fetch a tensor resource. Must be served with appropriate <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS">CORS</a> headers. Example: <code>load('https://www.random.org/cgi-bin/randbyte?nbytes=256', [16, 16], 'uint8')</code></li>
<li><strong>zeros(<em>shape</em>, <em>dataType</em>)</strong> - constant zero-filled tensor of the given shape. Example: <code>zeros([2,2,2,2], 'int8')</code></li>
</ul>
<h1>Details &amp; Gotchas</h1>
<ul>
Expand Down

0 comments on commit 919aa9f

Please sign in to comment.