UNPKG

@tensorflow/tfjs-core

Version:

Hardware-accelerated JavaScript library for machine intelligence

1,219 lines (1,204 loc) 781 kB
/** * @license * Copyright 2018 Google LLC. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============================================================================= */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.tf = global.tf || {}))); }(this, (function (exports) { 'use strict'; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ /* global Reflect, Promise */ var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; function __extends(d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } var __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; function __awaiter(thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); } function __generator(thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } } function isMobile() { var a = navigator.userAgent || navigator.vendor || window.opera; return /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i .test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i .test(a.substr(0, 4)); } function shuffle(array) { var counter = array.length; var temp = 0; var index = 0; while (counter > 0) { index = (Math.random() * counter) | 0; counter--; temp = array[counter]; array[counter] = array[index]; array[index] = temp; } } function clamp(min, x, max) { return Math.max(min, Math.min(x, max)); } function randUniform(a, b) { return Math.random() * (b - a) + a; } function distSquared(a, b) { var result = 0; for (var i = 0; i < a.length; i++) { var diff = Number(a[i]) - Number(b[i]); result += diff * diff; } return result; } function assert(expr, msg) { if (!expr) { throw new Error(typeof msg === 'string' ? msg : msg()); } } function assertShapesMatch(shapeA, shapeB, errorMessagePrefix) { if (errorMessagePrefix === void 0) { errorMessagePrefix = ''; } assert(arraysEqual(shapeA, shapeB), errorMessagePrefix + (" Shapes " + shapeA + " and " + shapeB + " must match")); } function assertNonNull(a) { assert(a != null, "The input to the tensor constructor must be a non-null value."); } function flatten(arr, ret) { if (ret === void 0) { ret = []; } if (Array.isArray(arr)) { for (var i = 0; i < arr.length; ++i) { flatten(arr[i], ret); } } else { ret.push(arr); } return ret; } function inferShape(val) { var firstElem = val; if (isTypedArray(val)) { return [val.length]; } if (!Array.isArray(val)) { return []; } var shape = []; while (firstElem instanceof Array) { shape.push(firstElem.length); firstElem = firstElem[0]; } if (val instanceof Array) { deepAssertShapeConsistency(val, shape, []); } return shape; } function deepAssertShapeConsistency(val, shape, indices) { indices = indices || []; if (!(val instanceof Array)) { assert(shape.length === 0, function () { return "Element arr[" + indices.join('][') + "] is a primitive, " + ("but should be an array of " + shape[0] + " elements"); }); return; } assert(shape.length > 0, function () { return "Element arr[" + indices.join('][') + "] should be a primitive, " + ("but is an array of " + val.length + " elements"); }); assert(val.length === shape[0], function () { return "Element arr[" + indices.join('][') + "] should have " + shape[0] + " " + ("elements, but has " + val.length + " elements"); }); var subShape = shape.slice(1); for (var i = 0; i < val.length; ++i) { deepAssertShapeConsistency(val[i], subShape, indices.concat(i)); } } function sizeFromShape(shape) { if (shape.length === 0) { return 1; } var size = shape[0]; for (var i = 1; i < shape.length; i++) { size *= shape[i]; } return size; } function isScalarShape(shape) { return shape.length === 0; } function arraysEqual(n1, n2) { if (n1.length !== n2.length) { return false; } for (var i = 0; i < n1.length; i++) { if (n1[i] !== n2[i]) { return false; } } return true; } function isInt(a) { return a % 1 === 0; } function tanh(x) { if (Math.tanh != null) { return Math.tanh(x); } if (x === Infinity) { return 1; } else if (x === -Infinity) { return -1; } else { var e2x = Math.exp(2 * x); return (e2x - 1) / (e2x + 1); } } function sizeToSquarishShape(size) { for (var a = Math.floor(Math.sqrt(size)); a > 1; --a) { if (size % a === 0) { return [a, size / a]; } } return [1, size]; } function createShuffledIndices(n) { var shuffledIndices = new Uint32Array(n); for (var i = 0; i < n; ++i) { shuffledIndices[i] = i; } shuffle(shuffledIndices); return shuffledIndices; } function rightPad(a, size) { if (size <= a.length) { return a; } return a + ' '.repeat(size - a.length); } function repeatedTry(checkFn, delayFn, maxCounter) { if (delayFn === void 0) { delayFn = function (counter) { return 0; }; } return new Promise(function (resolve, reject) { var tryCount = 0; var tryFn = function () { if (checkFn()) { resolve(); return; } tryCount++; var nextBackoff = delayFn(tryCount); if (maxCounter != null && tryCount >= maxCounter) { reject(); return; } setTimeout(tryFn, nextBackoff); }; tryFn(); }); } function inferFromImplicitShape(shape, size) { var shapeProd = 1; var implicitIdx = -1; for (var i = 0; i < shape.length; ++i) { if (shape[i] >= 0) { shapeProd *= shape[i]; } else if (shape[i] === -1) { if (implicitIdx !== -1) { throw Error("Shapes can only have 1 implicit size. " + ("Found -1 at dim " + implicitIdx + " and dim " + i)); } implicitIdx = i; } else if (shape[i] < 0) { throw Error("Shapes can not be < 0. Found " + shape[i] + " at dim " + i); } } if (implicitIdx === -1) { if (size > 0 && size !== shapeProd) { throw Error("Size(" + size + ") must match the product of shape " + shape); } return shape; } if (shapeProd === 0) { throw Error("Cannot infer the missing size in [" + shape + "] when " + "there are 0 elements"); } if (size % shapeProd !== 0) { throw Error("The implicit shape can't be a fractional number. " + ("Got " + size + " / " + shapeProd)); } var newShape = shape.slice(); newShape[implicitIdx] = size / shapeProd; return newShape; } function squeezeShape(shape, axis) { var newShape = []; var keptDims = []; var j = 0; for (var i = 0; i < shape.length; ++i) { if (axis != null) { if (axis[j] === i && shape[i] !== 1) { throw new Error("Can't squeeze axis " + i + " since its dim '" + shape[i] + "' is not 1"); } if ((axis[j] == null || axis[j] > i) && shape[i] === 1) { newShape.push(shape[i]); keptDims.push(i); } if (axis[j] <= i) { j++; } } if (shape[i] !== 1) { newShape.push(shape[i]); keptDims.push(i); } } return { newShape: newShape, keptDims: keptDims }; } function getTypedArrayFromDType(dtype, size) { var values = null; if (dtype == null || dtype === 'float32') { values = new Float32Array(size); } else if (dtype === 'int32') { values = new Int32Array(size); } else if (dtype === 'bool') { values = new Uint8Array(size); } else { throw new Error("Unknown data type " + dtype); } return values; } function checkComputationForNaN(vals, dtype, name) { if (dtype !== 'float32') { return; } for (var i = 0; i < vals.length; i++) { if (isNaN(vals[i])) { throw Error("The result of the '" + name + "' has NaNs."); } } } function checkConversionForNaN(vals, dtype) { if (dtype === 'float32') { return; } for (var i = 0; i < vals.length; i++) { if (isNaN(vals[i])) { throw Error("NaN is not a valid value for dtype: '" + dtype + "'."); } } } function hasEncodingLoss(oldType, newType) { if (newType === 'float32') { return false; } if (newType === 'int32' && oldType !== 'float32') { return false; } if (newType === 'bool' && oldType === 'bool') { return false; } return true; } function copyTypedArray(array, dtype, debugMode) { if (dtype == null || dtype === 'float32') { return new Float32Array(array); } else if (dtype === 'int32') { if (debugMode) { checkConversionForNaN(array, dtype); } return new Int32Array(array); } else if (dtype === 'bool') { var bool = new Uint8Array(array.length); for (var i = 0; i < bool.length; ++i) { if (Math.round(array[i]) !== 0) { bool[i] = 1; } } return bool; } else { throw new Error("Unknown data type " + dtype); } } function isTypedArray(a) { return a instanceof Float32Array || a instanceof Int32Array || a instanceof Uint8Array; } function bytesPerElement(dtype) { if (dtype === 'float32' || dtype === 'int32') { return 4; } else if (dtype === 'bool') { return 1; } else { throw new Error("Unknown dtype " + dtype); } } function isFunction(f) { return !!(f && f.constructor && f.call && f.apply); } function nearestDivisor(size, start) { for (var i = start; i < size; ++i) { if (size % i === 0) { return i; } } return size; } function computeStrides(shape) { var rank = shape.length; if (rank < 2) { return []; } var strides = new Array(rank - 1); strides[rank - 2] = shape[rank - 1]; for (var i = rank - 3; i >= 0; --i) { strides[i] = strides[i + 1] * shape[i + 1]; } return strides; } function toTypedArray(a, dtype, debugMode) { if (noConversionNeeded(a, dtype)) { return a; } if (Array.isArray(a)) { a = flatten(a); } return copyTypedArray(a, dtype, debugMode); } function noConversionNeeded(a, dtype) { return (a instanceof Float32Array && dtype === 'float32') || (a instanceof Int32Array && dtype === 'int32') || (a instanceof Uint8Array && dtype === 'bool'); } function makeOnesTypedArray(size, dtype) { var array = makeZerosTypedArray(size, dtype); for (var i = 0; i < array.length; i++) { array[i] = 1; } return array; } function makeZerosTypedArray(size, dtype) { if (dtype == null || dtype === 'float32') { return new Float32Array(size); } else if (dtype === 'int32') { return new Int32Array(size); } else if (dtype === 'bool') { return new Uint8Array(size); } else { throw new Error("Unknown data type " + dtype); } } function now() { if (typeof performance !== 'undefined') { return performance.now(); } else if (typeof process !== 'undefined') { var time = process.hrtime(); return time[0] * 1000 + time[1] / 1000000; } else { throw new Error('Can not measure time in this environment. You should run tf.js ' + 'in the browser or in Node.js'); } } var util = /*#__PURE__*/Object.freeze({ shuffle: shuffle, clamp: clamp, randUniform: randUniform, distSquared: distSquared, assert: assert, assertShapesMatch: assertShapesMatch, assertNonNull: assertNonNull, flatten: flatten, inferShape: inferShape, sizeFromShape: sizeFromShape, isScalarShape: isScalarShape, arraysEqual: arraysEqual, isInt: isInt, tanh: tanh, sizeToSquarishShape: sizeToSquarishShape, createShuffledIndices: createShuffledIndices, rightPad: rightPad, repeatedTry: repeatedTry, inferFromImplicitShape: inferFromImplicitShape, squeezeShape: squeezeShape, getTypedArrayFromDType: getTypedArrayFromDType, checkComputationForNaN: checkComputationForNaN, checkConversionForNaN: checkConversionForNaN, hasEncodingLoss: hasEncodingLoss, isTypedArray: isTypedArray, bytesPerElement: bytesPerElement, isFunction: isFunction, nearestDivisor: nearestDivisor, computeStrides: computeStrides, toTypedArray: toTypedArray, makeOnesTypedArray: makeOnesTypedArray, makeZerosTypedArray: makeZerosTypedArray, now: now }); var Profiler = (function () { function Profiler(backendTimer, logger) { this.backendTimer = backendTimer; this.logger = logger; if (logger == null) { this.logger = new Logger(); } } Profiler.prototype.profileKernel = function (name, f) { var _this = this; var result; var holdResultWrapperFn = function () { result = f(); }; var timer = this.backendTimer.time(holdResultWrapperFn); var results = Array.isArray(result) ? result : [result]; results.forEach(function (r) { var vals = r.dataSync(); checkComputationForNaN(vals, r.dtype, name); timer.then(function (timing) { _this.logger.logKernelProfile(name, r, vals, timing.kernelMs); }); }); return result; }; return Profiler; }()); var Logger = (function () { function Logger() { } Logger.prototype.logKernelProfile = function (name, result, vals, timeMs) { var time = rightPad(timeMs + "ms", 9); var paddedName = rightPad(name, 25); var rank = result.rank; var size = result.size; var shape = rightPad(result.shape.toString(), 14); console.log("%c" + paddedName + "\t%c" + time + "\t%c" + rank + "D " + shape + "\t%c" + size, 'font-weight:bold', 'color:red', 'color:blue', 'color: orange'); }; return Logger; }()); function getFilteredNodesXToY(tape, xs, y) { var tensorsFromX = {}; var nodesFromX = {}; for (var i = 0; i < xs.length; i++) { tensorsFromX[xs[i].id] = true; } for (var i = 0; i < tape.length; i++) { var node = tape[i]; var nodeInputs = node.inputs; for (var inputName in nodeInputs) { var input = nodeInputs[inputName]; var anyInputFromX = false; for (var j = 0; j < xs.length; j++) { if (tensorsFromX[input.id]) { tensorsFromX[node.output.id] = true; anyInputFromX = true; nodesFromX[node.id] = true; break; } } if (anyInputFromX) { break; } } } var tensorsLeadToY = {}; tensorsLeadToY[y.id] = true; var nodesToY = {}; for (var i = tape.length - 1; i >= 0; i--) { var node = tape[i]; var nodeInputs = node.inputs; var outputs = []; outputs.push(node.output); for (var j = 0; j < outputs.length; j++) { if (tensorsLeadToY[outputs[j].id]) { for (var inputName in nodeInputs) { tensorsLeadToY[nodeInputs[inputName].id] = true; nodesToY[node.id] = true; } break; } } } var filteredTape = []; for (var i = 0; i < tape.length; i++) { var node = tape[i]; if (nodesFromX[node.id] && nodesToY[node.id]) { var prunedInputs = {}; for (var inputName in node.inputs) { var nodeInput = node.inputs[inputName]; if (tensorsFromX[nodeInput.id]) { prunedInputs[inputName] = nodeInput; } } var prunedNode = Object.assign({}, node); prunedNode.inputs = prunedInputs; prunedNode.output = node.output; filteredTape.push(prunedNode); } } return filteredTape; } function backpropagateGradients(tensorAccumulatedGradientMap, filteredTape) { for (var i = filteredTape.length - 1; i >= 0; i--) { var node = filteredTape[i]; var dy = tensorAccumulatedGradientMap[node.output.id]; if (node.gradient == null) { throw new Error("Cannot compute gradient: gradient function not found " + ("for " + node.name + ".")); } var inputGradients = node.gradient(dy); for (var inputName in node.inputs) { if (!(inputName in inputGradients)) { throw new Error("Cannot backprop through input " + inputName + ". " + ("Available gradients found: " + Object.keys(inputGradients) + ".")); } var dx = inputGradients[inputName](); var x = node.inputs[inputName]; if (!arraysEqual(dx.shape, x.shape)) { throw new Error("Error in gradient for op " + node.name + ". The gradient of input " + ("'" + inputName + "' has shape '" + dx.shape + "', which does not match ") + ("the shape of the input '" + x.shape + "'")); } if (tensorAccumulatedGradientMap[x.id] == null) { tensorAccumulatedGradientMap[x.id] = dx; } else { var curGradient = tensorAccumulatedGradientMap[x.id]; tensorAccumulatedGradientMap[x.id] = curGradient.add(dx); curGradient.dispose(); } } } } var FORMAT_LIMIT_NUM_VALS = 20; var FORMAT_NUM_FIRST_LAST_VALS = 3; var FORMAT_NUM_SIG_DIGITS = 7; function tensorToString(vals, shape, dtype, verbose) { var strides = computeStrides(shape); var padPerCol = computeMaxSizePerColumn(vals, shape, strides); var rank = shape.length; var valsLines = subTensorToString(vals, shape, strides, padPerCol); var lines = ['Tensor']; if (verbose) { lines.push(" dtype: " + dtype); lines.push(" rank: " + rank); lines.push(" shape: [" + shape + "]"); lines.push(" values:"); } lines.push(valsLines.map(function (l) { return ' ' + l; }).join('\n')); return lines.join('\n'); } function computeMaxSizePerColumn(vals, shape, strides) { var n = sizeFromShape(shape); var numCols = strides[strides.length - 1]; var padPerCol = new Array(numCols).fill(0); var rank = shape.length; if (rank > 1) { for (var row = 0; row < n / numCols; row++) { var offset = row * numCols; for (var j = 0; j < numCols; j++) { padPerCol[j] = Math.max(padPerCol[j], valToString(vals[offset + j], 0).length); } } } return padPerCol; } function valToString(val, pad) { return rightPad(parseFloat(val.toFixed(FORMAT_NUM_SIG_DIGITS)).toString(), pad); } function subTensorToString(vals, shape, strides, padPerCol, isLast) { if (isLast === void 0) { isLast = true; } var size = shape[0]; var rank = shape.length; if (rank === 0) { return [vals[0].toString()]; } if (rank === 1) { if (size > FORMAT_LIMIT_NUM_VALS) { var firstVals = Array.from(vals.subarray(0, FORMAT_NUM_FIRST_LAST_VALS)); var lastVals = Array.from(vals.subarray(size - FORMAT_NUM_FIRST_LAST_VALS, size)); return [ '[' + firstVals.map(function (x, i) { return valToString(x, padPerCol[i]); }).join(', ') + ', ..., ' + lastVals .map(function (x, i) { return valToString(x, padPerCol[size - FORMAT_NUM_FIRST_LAST_VALS + i]); }) .join(', ') + ']' ]; } return [ '[' + Array.from(vals).map(function (x, i) { return valToString(x, padPerCol[i]); }).join(', ') + ']' ]; } var subshape = shape.slice(1); var substrides = strides.slice(1); var stride = strides[0]; var lines = []; if (size > FORMAT_LIMIT_NUM_VALS) { for (var i = 0; i < FORMAT_NUM_FIRST_LAST_VALS; i++) { var start = i * stride; var end = start + stride; lines.push.apply(lines, subTensorToString(vals.subarray(start, end), subshape, substrides, padPerCol, false)); } lines.push('...'); for (var i = size - FORMAT_NUM_FIRST_LAST_VALS; i < size; i++) { var start = i * stride; var end = start + stride; lines.push.apply(lines, subTensorToString(vals.subarray(start, end), subshape, substrides, padPerCol, i === size - 1)); } } else { for (var i = 0; i < size; i++) { var start = i * stride; var end = start + stride; lines.push.apply(lines, subTensorToString(vals.subarray(start, end), subshape, substrides, padPerCol, i === size - 1)); } } var sep = rank === 2 ? ',' : ''; lines[0] = '[' + lines[0] + sep; for (var i = 1; i < lines.length - 1; i++) { lines[i] = ' ' + lines[i] + sep; } var newLineSep = ',\n'; for (var i = 2; i < rank; i++) { newLineSep += '\n'; } lines[lines.length - 1] = ' ' + lines[lines.length - 1] + ']' + (isLast ? '' : newLineSep); return lines; } var TensorBuffer = (function () { function TensorBuffer(shape, dtype, values) { this.dtype = dtype; if (values != null) { var n = values.length; var size = sizeFromShape(shape); assert(n === size, "Length of values '" + n + "' does not match the size " + ("inferred by the shape '" + size + "'")); } this.shape = shape.slice(); this.values = values || getTypedArrayFromDType(dtype, sizeFromShape(shape)); this.strides = computeStrides(shape); this.size = sizeFromShape(shape); } TensorBuffer.prototype.set = function (value) { var locs = []; for (var _i = 1; _i < arguments.length; _i++) { locs[_i - 1] = arguments[_i]; } if (locs.length === 0) { locs = [0]; } assert(locs.length === this.rank, "The number of provided coordinates (" + locs.length + ") must " + ("match the rank (" + this.rank + ")")); var index = this.locToIndex(locs); this.values[index] = value; }; TensorBuffer.prototype.get = function () { var locs = []; for (var _i = 0; _i < arguments.length; _i++) { locs[_i] = arguments[_i]; } if (locs.length === 0) { locs = [0]; } var index = locs[locs.length - 1]; for (var i = 0; i < locs.length - 1; ++i) { index += this.strides[i] * locs[i]; } return this.values[index]; }; TensorBuffer.prototype.locToIndex = function (locs) { if (this.rank === 0) { return 0; } else if (this.rank === 1) { return locs[0]; } var index = locs[locs.length - 1]; for (var i = 0; i < locs.length - 1; ++i) { index += this.strides[i] * locs[i]; } return index; }; TensorBuffer.prototype.indexToLoc = function (index) { if (this.rank === 0) { return []; } else if (this.rank === 1) { return [index]; } var locs = new Array(this.shape.length); for (var i = 0; i < locs.length - 1; ++i) { locs[i] = Math.floor(index / this.strides[i]); index -= locs[i] * this.strides[i]; } locs[locs.length - 1] = index; return locs; }; Object.defineProperty(TensorBuffer.prototype, "rank", { get: function () { return this.shape.length; }, enumerable: true, configurable: true }); TensorBuffer.prototype.toTensor = function () { return Tensor.make(this.shape, { values: this.values }, this.dtype); }; return TensorBuffer; }()); var trackerFn = null; var opHandler = null; function setTensorTracker(fn) { trackerFn = fn; } function setOpHandler(handler) { opHandler = handler; } var Tensor = (function () { function Tensor(shape, dtype, values, dataId) { this.isDisposedInternal = false; this.size = sizeFromShape(shape); if (values != null) { assert(this.size === values.length, "Based on the provided shape, [" + shape + "], the tensor should have " + (this.size + " values but has " + values.length)); } this.shape = shape.slice(); this.dtype = dtype || 'float32'; this.strides = computeStrides(shape); this.dataId = dataId != null ? dataId : {}; this.id = Tensor.nextId++; this.rankType = (this.rank < 5 ? this.rank.toString() : 'higher'); trackerFn().registerTensor(this); if (values != null) { trackerFn().write(this.dataId, values); } } Tensor.make = function (shape, data, dtype) { return new Tensor(shape, dtype, data.values, data.dataId); }; Tensor.prototype.flatten = function () { this.throwIfDisposed(); return this.as1D(); }; Tensor.prototype.asScalar = function () { this.throwIfDisposed(); assert(this.size === 1, 'The array must have only 1 element.'); return this.reshape([]); }; Tensor.prototype.as1D = function () { this.throwIfDisposed(); return this.reshape([this.size]); }; Tensor.prototype.as2D = function (rows, columns) { this.throwIfDisposed(); return this.reshape([rows, columns]); }; Tensor.prototype.as3D = function (rows, columns, depth) { this.throwIfDisposed(); return this.reshape([rows, columns, depth]); }; Tensor.prototype.as4D = function (rows, columns, depth, depth2) { this.throwIfDisposed(); return this.reshape([rows, columns, depth, depth2]); }; Tensor.prototype.asType = function (dtype) { this.throwIfDisposed(); return opHandler.cast(this, dtype); }; Object.defineProperty(Tensor.prototype, "rank", { get: function () { return this.shape.length; }, enumerable: true, configurable: true }); Tensor.prototype.get = function () { var locs = []; for (var _i = 0; _i < arguments.length; _i++) { locs[_i] = arguments[_i]; } assert(locs.length === this.rank, 'Number of coordinates in get() must match the rank of the tensor'); this.throwIfDisposed(); if (locs.length === 0) { locs = [0]; } var index = locs[locs.length - 1]; for (var i = 0; i < locs.length - 1; ++i) { index += this.strides[i] * locs[i]; } return this.dataSync()[index]; }; Tensor.prototype.buffer = function () { return opHandler.buffer(this.shape, this.dtype, this.dataSync()); }; Tensor.prototype.data = function () { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { this.throwIfDisposed(); return [2, trackerFn().read(this.dataId)]; }); }); }; Tensor.prototype.dataSync = function () { this.throwIfDisposed(); return trackerFn().readSync(this.dataId); }; Tensor.prototype.dispose = function () { if (this.isDisposed) { return; } trackerFn().disposeTensor(this); this.isDisposedInternal = true; }; Object.defineProperty(Tensor.prototype, "isDisposed", { get: function () { return this.isDisposedInternal; }, enumerable: true, configurable: true }); Tensor.prototype.throwIfDisposed = function () { if (this.isDisposed) { throw new Error("Tensor is disposed."); } }; Tensor.prototype.toFloat = function () { return this.asType('float32'); }; Tensor.prototype.toInt = function () { return this.asType('int32'); }; Tensor.prototype.toBool = function () { return this.asType('bool'); }; Tensor.prototype.print = function (verbose) { if (verbose === void 0) { verbose = false; } return opHandler.print(this, verbose); }; Tensor.prototype.reshape = function (newShape) { this.throwIfDisposed(); return opHandler.reshape(this, newShape); }; Tensor.prototype.reshapeAs = function (x) { this.throwIfDisposed(); return this.reshape(x.shape); }; Tensor.prototype.expandDims = function (axis) { if (axis === void 0) { axis = 0; } return opHandler.expandDims(this, axis); }; Tensor.prototype.cumsum = function (axis, exclusive, reverse) { if (axis === void 0) { axis = 0; } if (exclusive === void 0) { exclusive = false; } if (reverse === void 0) { reverse = false; } return opHandler.cumsum(this, axis, exclusive, reverse); }; Tensor.prototype.squeeze = function (axis) { this.throwIfDisposed(); return opHandler.squeeze(this, axis); }; Tensor.prototype.clone = function () { this.throwIfDisposed(); return opHandler.clone(this); }; Tensor.prototype.toString = function (verbose) { if (verbose === void 0) { verbose = false; } var vals = this.dataSync(); return tensorToString(vals, this.shape, this.dtype, verbose); }; Tensor.prototype.tile = function (reps) { this.throwIfDisposed(); return opHandler.tile(this, reps); }; Tensor.prototype.gather = function (indices, axis) { if (axis === void 0) { axis = 0; } this.throwIfDisposed(); return opHandler.gather(this, indices, axis); }; Tensor.prototype.matMul = function (b, transposeA, transposeB) { if (transposeA === void 0) { transposeA = false; } if (transposeB === void 0) { transposeB = false; } this.throwIfDisposed(); return opHandler.matMul(this, b, transposeA, transposeB); }; Tensor.prototype.dot = function (b) { this.throwIfDisposed(); return opHandler.dot(this, b); }; Tensor.prototype.norm = function (ord, axis, keepDims) { if (ord === void 0) { ord = 'euclidean'; } if (axis === void 0) { axis = null; } if (keepDims === void 0) { keepDims = false; } this.throwIfDisposed(); return opHandler.norm(this, ord, axis, keepDims); }; Tensor.prototype.slice = function (begin, size) { this.throwIfDisposed(); return opHandler.slice(this, begin, size); }; Tensor.prototype.reverse = function (axis) { this.throwIfDisposed(); return opHandler.reverse(this, axis); }; Tensor.prototype.concat = function (x, axis) { if (axis === void 0) { axis = 0; } this.throwIfDisposed(); return opHandler.concat([this, x], axis); }; Tensor.prototype.stack = function (x, axis) { if (axis === void 0) { axis = 0; } return opHandler.stack([this, x], axis); }; Tensor.prototype.unstack = function (x, axis) { if (axis === void 0) { axis = 0; } return opHandler.unstack(this, axis); }; Tensor.prototype.pad = function (paddings, constantValue) { if (constantValue === void 0) { constantValue = 0; } return opHandler.pad(this, paddings, constantValue); }; Tensor.prototype.batchNormalization = function (mean, variance, varianceEpsilon, scale, offset) { if (varianceEpsilon === void 0) { varianceEpsilon = .001; } this.throwIfDisposed(); return opHandler.batchNormalization(this, mean, variance, varianceEpsilon, scale, offset); }; Tensor.prototype.all = function (axis, keepDims) { if (axis === void 0) { axis = null; } if (keepDims === void 0) { keepDims = false; } this.throwIfDisposed(); return opHandler.all(this, axis, keepDims); }; Tensor.prototype.any = function (axis, keepDims) { if (axis === void 0) { axis = null; } if (keepDims === void 0) { keepDims = false; } this.throwIfDisposed(); return opHandler.any(this, axis, keepDims); }; Tensor.prototype.logSumExp = function (axis, keepDims) { if (axis === void 0) { axis = null; } if (keepDims === void 0) { keepDims = false; } this.throwIfDisposed(); return opHandler.logSumExp(this, axis, keepDims); }; Tensor.prototype.sum = function (axis, keepDims) { if (axis === void 0) { axis = null; } if (keepDims === void 0) { keepDims = false; } this.throwIfDisposed(); return opHandler.sum(this, axis, keepDims); }; Tensor.prototype.mean = function (axis, keepDims) { if (axis === void 0) { axis = null; } if (keepDims === void 0) { keepDims = false; } this.throwIfDisposed(); return opHandler.mean(this, axis, keepDims); }; Tensor.prototype.min = function (axis, keepDims) { if (axis === void 0) { axis = null; } if (keepDims === void 0) { keepDims = false; } this.throwIfDisposed(); return opHandler.min(this, axis, keepDims); }; Tensor.prototype.max = function (axis, keepDims) { if (axis === void 0) { axis = null; } if (keepDims === void 0) { keepDims = false; } this.throwIfDisposed(); return opHandler.max(this, axis, keepDims); }; Tensor.prototype.argMin = function (axis) { if (axis === void 0) { axis = null; } this.throwIfDisposed(); return opHandler.argMin(this, axis); }; Tensor.prototype.argMax = function (axis) { if (axis === void 0) { axis = null; } this.throwIfDisposed(); return opHandler.argMax(this, axis); }; Tensor.prototype.cast = function (dtype) { this.throwIfDisposed(); return opHandler.cast(this, dtype); }; Tensor.prototype.add = function (x) { this.throwIfDisposed(); return opHandler.add(this, x); }; Tensor.prototype.addStrict = function (x) { this.throwIfDisposed(); return opHandler.addStrict(this, x); }; Tensor.prototype.sub = function (x) { this.throwIfDisposed(); return opHandler.sub(this, x); }; Tensor.prototype.subStrict = function (x) { this.throwIfDisposed(); return opHandler.subStrict(this, x); }; Tensor.prototype.pow = function (exp) { this.throwIfDisposed(); return opHandler.pow(this, exp); }; Tensor.prototype.powStrict = function (exp) { this.throwIfDisposed(); return opHandler.powStrict(this, exp); }; Tensor.prototype.mul = function (x) { this.throwIfDisposed(); return opHandler.mul(this, x); }; Tensor.prototype.mulStrict = function (x) { this.throwIfDisposed(); return opHandler.mulStrict(this, x); }; Tensor.prototype.div = function (x) { this.throwIfDisposed(); return opHandler.div(this, x); }; Tensor.prototype.floorDiv = function (x) { this.throwIfDisposed(); return opHandler.floorDiv(this, x); }; Tensor.prototype.divStrict = function (x) { this.throwIfDisposed(); return opHandler.divStrict(this, x); }; Tensor.prototype.minimum = function (x) { this.throwIfDisposed(); return opHandler.minimum(this, x); }; Tensor.prototype.minimumStrict = function (x) { this.throwIfDisposed(); return opHandler.minimumStrict(this, x); }; Tensor.prototype.maximum = function (x) { this.throwIfDisposed(); return opHandler.maximum(this, x); }; Tensor.prototype.maximumStrict = function (x) { this.throwIfDisposed(); return opHandler.maximumStrict(this, x); }; Tensor.prototype.mod = function (x) { this.throwIfDisposed(); return opHandler.mod(this, x); }; Tensor.prototype.modStrict = function (x) { this.throwIfDisposed(); return opHandler.modStrict(this, x); }; Tensor.prototype.squaredDifference = function (x) { this.throwIfDisposed(); return opHandler.squaredDifference(this, x); }; Tensor.prototype.squaredDifferenceStrict = function (x) { this.throwIfDisposed(); return opHandler.squaredDifferenceStrict(this, x); }; Tensor.prototype.transpose = function (perm) { this.throwIfDisposed(); return opHandler.transpose(this, perm); }; Tensor.prototype.notEqual = function (x) { this.throwIfDisposed(); return opHandler.notEqual(this, x); }; Tensor.prototype.notEqualStrict = function (x) { this.throwIfDisposed(); return opHandler.notEqualStrict(this, x); }; Tensor.prototype.less = function (x) { this.throwIfDisposed(); return opHandler.less(this, x); }; Tensor.prototype.lessStrict = function (x) { this.throwIfDisposed(); return opHandler.lessStrict(this, x); }; Tensor.prototype.equal = function (x) { this.throwIfDisposed(); return opHandler.equal(this, x); }; Tensor.prototype.equalStrict = function (x) { this.throwIfDisposed(); return opHandler.equalStrict(this, x); }; Tensor.protot