UNPKG

@tensorflow/tfjs-node

Version:

This repository provides native TensorFlow execution in backend JavaScript applications under the Node.js runtime, accelerated by the TensorFlow C binary under the hood. It provides the same API as [TensorFlow.js](https://js.tensorflow.org/api/latest/).

1,023 lines (1,022 loc) 81.7 kB
"use strict"; /** * @license * Copyright 2018 Google Inc. 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. * ============================================================================= */ var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { 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]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __awaiter = (this && this.__awaiter) || function (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()); }); }; var __generator = (this && this.__generator) || function (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 }; } }; Object.defineProperty(exports, "__esModule", { value: true }); var tfc = require("@tensorflow/tfjs-core"); var tfjs_core_1 = require("@tensorflow/tfjs-core"); // tslint:disable-next-line: no-imports-from-dist var backend_1 = require("@tensorflow/tfjs-core/dist/backends/backend"); var util_1 = require("util"); var int64_tensors_1 = require("./int64_tensors"); var NodeJSKernelBackend = /** @class */ (function (_super) { __extends(NodeJSKernelBackend, _super); function NodeJSKernelBackend(binding, packageName) { var _this = _super.call(this) || this; _this.binding = binding; _this.isGPUPackage = packageName === '@tensorflow/tfjs-node-gpu'; _this.isUsingGpuDevice = _this.binding.isUsingGpuDevice(); _this.tensorMap = new tfc.DataStorage(_this, tfc.engine()); return _this; } NodeJSKernelBackend.prototype.getDTypeInteger = function (dtype) { switch (dtype) { case 'float32': return this.binding.TF_FLOAT; case 'int32': return this.binding.TF_INT32; case 'bool': return this.binding.TF_BOOL; case 'complex64': return this.binding.TF_COMPLEX64; case 'string': return this.binding.TF_STRING; default: throw new Error("Unsupported DType: " + dtype); } }; NodeJSKernelBackend.prototype.typeAttributeFromTensor = function (value) { return this.getDTypeInteger(value.dtype); }; // Creates a new Tensor and maps the dataId to the passed in ID. NodeJSKernelBackend.prototype.createOutputTensor = function (metadata) { var newId = {}; this.tensorMap.set(newId, { shape: metadata.shape, dtype: metadata.dtype, id: metadata.id, values: null }); var dtype; switch (metadata.dtype) { case this.binding.TF_FLOAT: dtype = 'float32'; break; case this.binding.TF_INT32: dtype = 'int32'; break; case this.binding.TF_BOOL: dtype = 'bool'; break; case this.binding.TF_COMPLEX64: dtype = 'complex64'; break; case this.binding.TF_STRING: dtype = 'string'; break; case this.binding.TF_RESOURCE: // NOTE(cais): We currently represent resource-type Tensors // as string of ubytes. dtype = 'string'; break; case this.binding.TF_UINT8: // TensorFlow uses UINT8 as dtype for image tensor. UINT8 is not // supported in TFJS yet, cast it to int32. dtype = 'int32'; break; default: throw new Error("Unknown dtype enum " + metadata.dtype); } return tfc.engine().makeTensorFromDataId(newId, metadata.shape, dtype); }; // Prepares Tensor instances for Op execution. NodeJSKernelBackend.prototype.getInputTensorIds = function (tensors) { var ids = []; for (var i = 0; i < tensors.length; i++) { if (tensors[i] instanceof int64_tensors_1.Int64Scalar) { // Then `tensors[i]` is a Int64Scalar, which we currently represent // using an `Int32Array`. var value = tensors[i].valueArray; var id = this.binding.createTensor([], this.binding.TF_INT64, value); ids.push(id); } else { var info = this.tensorMap.get(tensors[i].dataId); // TODO - what about ID in this case? Handle in write()?? if (info.values != null) { // Values were delayed to write into the TensorHandle. Do that before // Op execution and clear stored values. info.id = this.binding.createTensor(info.shape, info.dtype, info.values); info.values = null; } ids.push(info.id); } } return ids; }; NodeJSKernelBackend.prototype.createReductionOpAttrs = function (tensor) { return [ { name: 'keep_dims', type: this.binding.TF_ATTR_BOOL, value: false }, createTypeOpAttr('T', tensor.dtype), createTypeOpAttr('Tidx', 'int32') ]; }; NodeJSKernelBackend.prototype.executeSingleInput = function (name, input) { var opAttrs = [createTypeOpAttr('T', input.dtype)]; return this.executeSingleOutput(name, opAttrs, [input]); }; NodeJSKernelBackend.prototype.floatPrecision = function () { return 32; }; NodeJSKernelBackend.prototype.epsilon = function () { return backend_1.EPSILON_FLOAT32; }; /** * Executes a TensorFlow Eager Op that provides one output Tensor. * @param name The name of the Op to execute. * @param opAttrs The list of Op attributes required to execute. * @param inputs The list of input Tensors for the Op. * @return A resulting Tensor from Op execution. */ NodeJSKernelBackend.prototype.executeSingleOutput = function (name, opAttrs, inputs) { var outputMetadata = this.binding.executeOp(name, opAttrs, this.getInputTensorIds(inputs), 1); return this.createOutputTensor(outputMetadata[0]); }; /** * Executes a TensorFlow Eager Op that provides multiple output Tensors. * @param name The name of the Op to execute. * @param opAttrs The list of Op attributes required to execute. * @param inputs The list of input Tensors for the Op. * @param numOutputs The number of output Tensors for Op execution. * @return A resulting Tensor array from Op execution. */ NodeJSKernelBackend.prototype.executeMultipleOutputs = function (name, opAttrs, inputs, numOutputs) { var _this = this; var outputMetadata = this.binding.executeOp(name, opAttrs, this.getInputTensorIds(inputs), numOutputs); return outputMetadata.map(function (m) { return _this.createOutputTensor(m); }); }; NodeJSKernelBackend.prototype.numDataIds = function () { return this.tensorMap.numDataIds(); }; NodeJSKernelBackend.prototype.dispose = function () { }; NodeJSKernelBackend.prototype.read = function (dataId) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { return [2 /*return*/, this.readSync(dataId)]; }); }); }; NodeJSKernelBackend.prototype.readSync = function (dataId) { if (!this.tensorMap.has(dataId)) { throw new Error("Tensor " + dataId + " was not registered!"); } var info = this.tensorMap.get(dataId); if (info.values != null) { return info.values; } else { return this.binding.tensorDataSync(info.id); } }; NodeJSKernelBackend.prototype.disposeData = function (dataId) { // No-op if already disposed. if (!this.tensorMap.has(dataId)) { return; } var id = this.tensorMap.get(dataId).id; if (id != null && id >= 0) { this.binding.deleteTensor(id); } this.tensorMap.delete(dataId); }; NodeJSKernelBackend.prototype.move = function (dataId, values, shape, dtype) { this.tensorMap.set(dataId, { shape: shape, dtype: getTFDType(dtype), values: values, id: -1 }); }; NodeJSKernelBackend.prototype.write = function (values, shape, dtype) { var dataId = {}; this.move(dataId, values, shape, dtype); return dataId; }; NodeJSKernelBackend.prototype.fill = function (shape, value, dtype) { // TODO(cais, nkreeger): Investigate whether this can be made into // a dtype helper method. The underlying op kernel doesn't accept undefined // or null dtype. if (dtype == null) { if (typeof value === 'number') { dtype = 'float32'; } else { dtype = 'string'; } } var shapeTensor = tfjs_core_1.tensor1d(shape, 'int32'); var valueTensor = tfjs_core_1.scalar(value, dtype); var opAttrs = [ { name: 'T', type: this.binding.TF_ATTR_TYPE, value: this.getDTypeInteger(dtype) }, { name: 'index_type', type: this.binding.TF_ATTR_TYPE, value: this.binding.TF_INT32 } ]; return this.executeSingleOutput('Fill', opAttrs, [shapeTensor, valueTensor]); }; NodeJSKernelBackend.prototype.onesLike = function (x) { var opAttrs = [{ name: 'T', type: this.binding.TF_ATTR_TYPE, value: this.getDTypeInteger(x.dtype) }]; return this.executeSingleOutput('OnesLike', opAttrs, [x]); }; NodeJSKernelBackend.prototype.zerosLike = function (x) { var opAttrs = [{ name: 'T', type: this.binding.TF_ATTR_TYPE, value: this.getDTypeInteger(x.dtype) }]; return this.executeSingleOutput('ZerosLike', opAttrs, [x]); }; NodeJSKernelBackend.prototype.stridedSlice = function (x, begin, end, strides) { var beginTensor = tfjs_core_1.tensor1d(begin, 'int32'); for (var axis = 0; axis < end.length; axis++) { // Unlike Numpy, when the strides are negative, TF C uses -n-1 instead of // -1 as the "end" in order to include the first element. if (strides[axis] < 0 && end[axis] === -1) { end[axis] -= x.shape[axis]; } } var endTensor = tfjs_core_1.tensor1d(end, 'int32'); var stridesTensor = tfjs_core_1.tensor1d(strides, 'int32'); // All of the masks have already been accounted for in the high level op, // so the backend does NOT need to deal with masks. var opAttrs = [ createTypeOpAttr('T', x.dtype), createTypeOpAttr('Index', 'int32'), { name: 'begin_mask', type: this.binding.TF_ATTR_INT, value: 0 }, { name: 'end_mask', type: this.binding.TF_ATTR_INT, value: 0 }, { name: 'ellipsis_mask', type: this.binding.TF_ATTR_INT, value: 0 }, { name: 'new_axis_mask', type: this.binding.TF_ATTR_INT, value: 0 }, { name: 'shrink_axis_mask', type: this.binding.TF_ATTR_INT, value: 0 } ]; return this.executeSingleOutput('StridedSlice', opAttrs, [x, beginTensor, endTensor, stridesTensor]); }; NodeJSKernelBackend.prototype.unstack = function (x, axis) { if (axis >= x.shape.length) { throw new Error("Invalid axis supplied: " + axis + " shape length: " + x.shape.length); } var num = x.shape[axis]; var opAttrs = [ { name: 'num', type: this.binding.TF_ATTR_INT, value: num }, createTypeOpAttr('T', x.dtype), { name: 'axis', type: this.binding.TF_ATTR_INT, value: axis } ]; return this.executeMultipleOutputs('Unpack', opAttrs, [x], num); }; NodeJSKernelBackend.prototype.batchMatMul = function (a, b, transposeA, transposeB) { var opAttrs = [ createTypeOpAttr('T', a.dtype), { name: 'adj_x', type: this.binding.TF_ATTR_BOOL, value: transposeA }, { name: 'adj_y', type: this.binding.TF_ATTR_BOOL, value: transposeB } ]; return this.executeSingleOutput('BatchMatMul', opAttrs, [a, b]); }; NodeJSKernelBackend.prototype.applyActivation = function (input, activation, preluActivationWeights) { var result = input; if (activation != null) { if (activation === 'linear') { // No-op } else if (activation === 'relu') { result = this.relu(result); } else if (activation === 'prelu') { result = this.prelu(result, preluActivationWeights); } else if (activation === 'elu') { result = this.elu(result); } else if (activation === 'relu6') { result = this.relu6(result); } else { throw new Error("Activation: " + activation + " has not been implemented for the Node.js backend"); } } return result; }; NodeJSKernelBackend.prototype.fusedConv2d = function (_a) { var input = _a.input, filter = _a.filter, convInfo = _a.convInfo, bias = _a.bias, activation = _a.activation, preluActivationWeights = _a.preluActivationWeights; var result = this.conv2d(input, filter, convInfo); if (bias != null) { result = this.add(result, bias); } result = this.applyActivation(result, activation, preluActivationWeights); return result; }; NodeJSKernelBackend.prototype.fusedBatchMatMul = function (_a) { var a = _a.a, b = _a.b, transposeA = _a.transposeA, transposeB = _a.transposeB, bias = _a.bias, activation = _a.activation, preluActivationWeights = _a.preluActivationWeights; // Core TensorFlow does not have a fused BatchMatMul op. Combine calls to // achieve the same results: var result = this.batchMatMul(a, b, transposeA, transposeB); if (bias != null) { result = this.add(result, bias); } result = this.applyActivation(result, activation, preluActivationWeights); return result; }; NodeJSKernelBackend.prototype.slice = function (x, begin, size) { var opAttrs = [createTypeOpAttr('T', x.dtype), createTypeOpAttr('Index', 'int32')]; // Bind tensor values var beginTensor = tfjs_core_1.tensor1d(begin, 'int32'); var sizeTensor = tfjs_core_1.tensor1d(size, 'int32'); return this.executeSingleOutput('Slice', opAttrs, [x, beginTensor, sizeTensor]); }; NodeJSKernelBackend.prototype.reverse = function (a, axis) { var opAttrs = [createTypeOpAttr('Tidx', 'int32'), createTypeOpAttr('T', a.dtype)]; var axisTensor = tfjs_core_1.tensor1d(axis, 'int32'); return this.executeSingleOutput('ReverseV2', opAttrs, [a, axisTensor]); }; NodeJSKernelBackend.prototype.concat = function (tensors, axis) { var opAttrs = [ { name: 'N', type: this.binding.TF_ATTR_INT, value: tensors.length }, { name: 'Tidx', type: this.binding.TF_ATTR_TYPE, value: this.binding.TF_INT32 }, createTensorsTypeOpAttr('T', tensors) ]; var inputs = Array.from(tensors); inputs.push(tfjs_core_1.scalar(axis, 'int32')); return this.executeSingleOutput('ConcatV2', opAttrs, inputs); }; NodeJSKernelBackend.prototype.neg = function (a) { return this.executeSingleInput('Neg', a); }; NodeJSKernelBackend.prototype.diag = function (x) { return this.executeSingleInput('Diag', x); }; NodeJSKernelBackend.prototype.add = function (a, b) { var opAttrs = [createTypeOpAttr('T', tfjs_core_1.backend_util.upcastType(a.dtype, b.dtype))]; return this.executeSingleOutput('Add', opAttrs, [a, b]); }; NodeJSKernelBackend.prototype.select = function (condition, a, b) { var opAttrs = [createTypeOpAttr('T', tfjs_core_1.backend_util.upcastType(a.dtype, b.dtype))]; return this.executeSingleOutput('Select', opAttrs, [condition, a, b]); }; NodeJSKernelBackend.prototype.addN = function (tensors) { var opAttrs = [ createTypeOpAttr('T', tensors[0].dtype), { name: 'N', type: this.binding.TF_ATTR_INT, value: tensors.length } ]; return this.executeSingleOutput('AddN', opAttrs, tensors); }; NodeJSKernelBackend.prototype.subtract = function (a, b) { var opAttrs = [createTypeOpAttr('T', tfjs_core_1.backend_util.upcastType(a.dtype, b.dtype))]; return this.executeSingleOutput('Sub', opAttrs, [a, b]); }; NodeJSKernelBackend.prototype.multiply = function (a, b) { var opAttrs = [createTypeOpAttr('T', tfjs_core_1.backend_util.upcastType(a.dtype, b.dtype))]; return this.executeSingleOutput('Mul', opAttrs, [a, b]); }; NodeJSKernelBackend.prototype.realDivide = function (a, b) { var opAttrs = [createTypeOpAttr('T', tfjs_core_1.backend_util.upcastType(a.dtype, b.dtype))]; return this.executeSingleOutput('RealDiv', opAttrs, [a, b]); }; NodeJSKernelBackend.prototype.floorDiv = function (a, b) { var opAttrs = [createTypeOpAttr('T', tfjs_core_1.backend_util.upcastType(a.dtype, b.dtype))]; return this.executeSingleOutput('FloorDiv', opAttrs, [a, b]); }; NodeJSKernelBackend.prototype.divide = function (a, b) { var opAttrs = [createTypeOpAttr('T', tfjs_core_1.backend_util.upcastType(a.dtype, b.dtype))]; return this.executeSingleOutput('Div', opAttrs, [a, b]); }; NodeJSKernelBackend.prototype.divNoNan = function (a, b) { var opAttrs = [createTypeOpAttr('T', tfjs_core_1.backend_util.upcastType(a.dtype, b.dtype))]; return this.executeSingleOutput('DivNoNan', opAttrs, [a, b]); }; NodeJSKernelBackend.prototype.unsortedSegmentSum = function (x, segmentIds, numSegments) { var opAttrs = [ createTypeOpAttr('T', x.dtype), createTypeOpAttr('Tindices', 'int32'), createTypeOpAttr('Tnumsegments', 'int32') ]; return this.executeSingleOutput('UnsortedSegmentSum', opAttrs, [x, segmentIds, tfjs_core_1.scalar(numSegments, 'int32')]); }; NodeJSKernelBackend.prototype.sum = function (x, axes) { var axisTensor = tfjs_core_1.tensor1d(axes, 'int32'); return this.executeSingleOutput('Sum', this.createReductionOpAttrs(x), [x, axisTensor]); }; NodeJSKernelBackend.prototype.prod = function (x, axes) { var axesTensor = tfjs_core_1.tensor1d(axes, 'int32'); var opAttrs = [ { name: 'keep_dims', type: this.binding.TF_ATTR_BOOL, value: false }, createTypeOpAttr('T', x.dtype), createTypeOpAttr('Tidx', 'int32') ]; return this.executeSingleOutput('Prod', opAttrs, [x, axesTensor]); }; NodeJSKernelBackend.prototype.argMin = function (x, axis) { var xInput = x.dtype === 'bool' ? x.toInt() : x; var axisScalar = tfjs_core_1.scalar(axis, 'int32'); var opAttrs = [ createTypeOpAttr('T', xInput.dtype), createTypeOpAttr('Tidx', 'int32'), createTypeOpAttr('output_type', 'int32') ]; return this.executeSingleOutput('ArgMin', opAttrs, [xInput, axisScalar]); }; NodeJSKernelBackend.prototype.argMax = function (x, axis) { var xInput = x.dtype === 'bool' ? x.toInt() : x; var axisScalar = tfjs_core_1.scalar(axis, 'int32'); var opAttrs = [ createTypeOpAttr('T', xInput.dtype), createTypeOpAttr('Tidx', 'int32'), createTypeOpAttr('output_type', 'int32') ]; return this.executeSingleOutput('ArgMax', opAttrs, [xInput, axisScalar]); }; NodeJSKernelBackend.prototype.equal = function (a, b) { var opAttrs = [createTypeOpAttr('T', tfjs_core_1.backend_util.upcastType(a.dtype, b.dtype))]; return this.executeSingleOutput('Equal', opAttrs, [a, b]); }; NodeJSKernelBackend.prototype.notEqual = function (a, b) { var opAttrs = [createTypeOpAttr('T', tfjs_core_1.backend_util.upcastType(a.dtype, b.dtype))]; return this.executeSingleOutput('NotEqual', opAttrs, [a, b]); }; NodeJSKernelBackend.prototype.less = function (a, b) { var opAttrs = [createTypeOpAttr('T', tfjs_core_1.backend_util.upcastType(a.dtype, b.dtype))]; return this.executeSingleOutput('Less', opAttrs, [a, b]); }; NodeJSKernelBackend.prototype.lessEqual = function (a, b) { var opAttrs = [createTypeOpAttr('T', tfjs_core_1.backend_util.upcastType(a.dtype, b.dtype))]; return this.executeSingleOutput('LessEqual', opAttrs, [a, b]); }; NodeJSKernelBackend.prototype.greater = function (a, b) { var opAttrs = [createTypeOpAttr('T', tfjs_core_1.backend_util.upcastType(a.dtype, b.dtype))]; return this.executeSingleOutput('Greater', opAttrs, [a, b]); }; NodeJSKernelBackend.prototype.greaterEqual = function (a, b) { var opAttrs = [createTypeOpAttr('T', tfjs_core_1.backend_util.upcastType(a.dtype, b.dtype))]; return this.executeSingleOutput('GreaterEqual', opAttrs, [a, b]); }; NodeJSKernelBackend.prototype.logicalNot = function (a) { return this.executeSingleOutput('LogicalNot', [], [a]); }; NodeJSKernelBackend.prototype.logicalAnd = function (a, b) { return this.executeSingleOutput('LogicalAnd', [], [a, b]); }; NodeJSKernelBackend.prototype.logicalOr = function (a, b) { return this.executeSingleOutput('LogicalOr', [], [a, b]); }; NodeJSKernelBackend.prototype.where = function (condition) { return this.executeSingleOutput('Where', [], [condition]); }; NodeJSKernelBackend.prototype.topKValues = function (x, k) { throw new Error('Method not implemented.'); }; NodeJSKernelBackend.prototype.topKIndices = function (x, k) { throw new Error('Method not implemented.'); }; NodeJSKernelBackend.prototype.topk = function (x, k, sorted) { var kCount = util_1.isNullOrUndefined(k) ? 1 : k; var isSorted = util_1.isNullOrUndefined(sorted) ? true : sorted; var opAttrs = [ { name: 'sorted', type: this.binding.TF_ATTR_BOOL, value: isSorted }, createTypeOpAttr('T', x.dtype), ]; var kTensor = tfjs_core_1.scalar(kCount, 'int32'); // 'TopKV2' has two-hard coded output attributes: return this.executeMultipleOutputs('TopKV2', opAttrs, [x, kTensor], 2); }; NodeJSKernelBackend.prototype.min = function (x, axes) { var axesTensor = tfjs_core_1.tensor1d(axes, 'int32'); return this.executeSingleOutput('Min', this.createReductionOpAttrs(x), [x, axesTensor]); }; NodeJSKernelBackend.prototype.minimum = function (a, b) { var opAttrs = [createTypeOpAttr('T', tfjs_core_1.backend_util.upcastType(a.dtype, b.dtype))]; return this.executeSingleOutput('Minimum', opAttrs, [a, b]); }; NodeJSKernelBackend.prototype.max = function (x, axes) { var axesTensor = tfjs_core_1.tensor1d(axes, 'int32'); return this.executeSingleOutput('Max', this.createReductionOpAttrs(x), [x, axesTensor]); }; NodeJSKernelBackend.prototype.maximum = function (a, b) { var opAttrs = [createTypeOpAttr('T', tfjs_core_1.backend_util.upcastType(a.dtype, b.dtype))]; return this.executeSingleOutput('Maximum', opAttrs, [a, b]); }; NodeJSKernelBackend.prototype.all = function (x, axes) { var opAttrs = [ { name: 'keep_dims', type: this.binding.TF_ATTR_BOOL, value: false }, createTypeOpAttr('Tidx', 'int32') ]; var axesTensor = tfjs_core_1.tensor1d(axes, 'int32'); return this.executeSingleOutput('All', opAttrs, [x, axesTensor]); }; NodeJSKernelBackend.prototype.any = function (x, axes) { var opAttrs = [ { name: 'keep_dims', type: this.binding.TF_ATTR_BOOL, value: false }, createTypeOpAttr('Tidx', 'int32') ]; var axesTensor = tfjs_core_1.tensor1d(axes, 'int32'); return this.executeSingleOutput('Any', opAttrs, [x, axesTensor]); }; NodeJSKernelBackend.prototype.ceil = function (x) { return this.executeSingleInput('Ceil', x); }; NodeJSKernelBackend.prototype.floor = function (x) { return this.executeSingleInput('Floor', x); }; NodeJSKernelBackend.prototype.pow = function (a, b) { var dtype = tfjs_core_1.backend_util.upcastType(a.dtype, b.dtype); var opAttrs = [createTypeOpAttr('T', dtype)]; return this.executeSingleOutput('Pow', opAttrs, [a.cast(dtype), b.cast(dtype)]); }; NodeJSKernelBackend.prototype.exp = function (x) { var xTensor = x.dtype === 'int32' ? x.toFloat() : x; return this.executeSingleInput('Exp', xTensor); }; NodeJSKernelBackend.prototype.log = function (x) { return this.executeSingleInput('Log', x); }; NodeJSKernelBackend.prototype.log1p = function (x) { return this.executeSingleInput('Log1p', x); }; NodeJSKernelBackend.prototype.sqrt = function (x) { return this.executeSingleInput('Sqrt', x); }; NodeJSKernelBackend.prototype.square = function (x) { return this.executeSingleInput('Square', x); }; NodeJSKernelBackend.prototype.relu = function (x) { return this.executeSingleInput('Relu', x); }; NodeJSKernelBackend.prototype.relu6 = function (x) { return this.executeSingleInput('Relu6', x); }; NodeJSKernelBackend.prototype.prelu = function (x, a) { var pos = this.relu(x); var neg = a.mul(x.sub(this.abs(x))).mul(0.5); return pos.add(neg); }; NodeJSKernelBackend.prototype.elu = function (x) { return this.executeSingleInput('Elu', x); }; NodeJSKernelBackend.prototype.eluDer = function (dy, y) { var opAttrs = [createTypeOpAttr('T', y.dtype)]; return this.executeSingleOutput('EluGrad', opAttrs, [dy, y]); }; NodeJSKernelBackend.prototype.selu = function (x) { return this.executeSingleInput('Selu', x); }; NodeJSKernelBackend.prototype.int = function (x) { throw new Error('Method not implemented.'); }; NodeJSKernelBackend.prototype.clip = function (x, min, max) { var xMin = this.minimum(x, tfjs_core_1.scalar(max)); return this.maximum(xMin, tfjs_core_1.scalar(min)); }; NodeJSKernelBackend.prototype.abs = function (x) { return this.executeSingleInput('Abs', x); }; NodeJSKernelBackend.prototype.complexAbs = function (x) { var opAttrs = [createTypeOpAttr('T', x.dtype), createTypeOpAttr('Tout', 'float32')]; return this.executeSingleOutput('ComplexAbs', opAttrs, [x]); }; NodeJSKernelBackend.prototype.sigmoid = function (x) { return this.executeSingleInput('Sigmoid', x); }; NodeJSKernelBackend.prototype.sin = function (x) { return this.executeSingleInput('Sin', x); }; NodeJSKernelBackend.prototype.cos = function (x) { return this.executeSingleInput('Cos', x); }; NodeJSKernelBackend.prototype.tan = function (x) { return this.executeSingleInput('Tan', x); }; NodeJSKernelBackend.prototype.asin = function (x) { return this.executeSingleInput('Asin', x); }; NodeJSKernelBackend.prototype.acos = function (x) { return this.executeSingleInput('Acos', x); }; NodeJSKernelBackend.prototype.atan = function (x) { return this.executeSingleInput('Atan', x); }; NodeJSKernelBackend.prototype.sinh = function (x) { return this.executeSingleInput('Sinh', x); }; NodeJSKernelBackend.prototype.cosh = function (x) { return this.executeSingleInput('Cosh', x); }; NodeJSKernelBackend.prototype.tanh = function (x) { return this.executeSingleInput('Tanh', x); }; NodeJSKernelBackend.prototype.mod = function (a, b) { var opAttrs = [createTypeOpAttr('T', a.dtype)]; return this.executeSingleOutput('FloorMod', opAttrs, [a, b]); }; NodeJSKernelBackend.prototype.round = function (x) { return this.executeSingleInput('Round', x); }; NodeJSKernelBackend.prototype.sign = function (x) { return this.executeSingleInput('Sign', x); }; NodeJSKernelBackend.prototype.isNaN = function (x) { return this.executeSingleInput('IsNan', x); }; NodeJSKernelBackend.prototype.isInf = function (x) { return this.executeSingleInput('IsInf', x); }; NodeJSKernelBackend.prototype.isFinite = function (x) { return this.executeSingleInput('IsFinite', x); }; NodeJSKernelBackend.prototype.rsqrt = function (x) { return this.executeSingleInput('Rsqrt', x); }; NodeJSKernelBackend.prototype.reciprocal = function (x) { return this.executeSingleInput('Reciprocal', x); }; NodeJSKernelBackend.prototype.asinh = function (x) { return this.executeSingleInput('Asinh', x); }; NodeJSKernelBackend.prototype.acosh = function (x) { return this.executeSingleInput('Acosh', x); }; NodeJSKernelBackend.prototype.atanh = function (x) { return this.executeSingleInput('Atanh', x); }; NodeJSKernelBackend.prototype.erf = function (x) { return this.executeSingleInput('Erf', x); }; NodeJSKernelBackend.prototype.squaredDifference = function (a, b) { var opAttrs = [createTypeOpAttr('T', a.dtype)]; return this.executeSingleOutput('SquaredDifference', opAttrs, [a, b]); }; NodeJSKernelBackend.prototype.expm1 = function (x) { return this.executeSingleInput('Expm1', x); }; NodeJSKernelBackend.prototype.softplus = function (x) { return this.executeSingleInput('Softplus', x); }; NodeJSKernelBackend.prototype.atan2 = function (a, b) { var opAttrs = [createTypeOpAttr('T', a.dtype)]; return this.executeSingleOutput('Atan2', opAttrs, [a, b]); }; NodeJSKernelBackend.prototype.step = function (x, alpha) { var dtype = x.dtype; var nans = this.isNaN(x); var stepNoNans = this.select(this.greater(x, tfjs_core_1.scalar(0, dtype)), tfjs_core_1.ones(x.shape), tfjs_core_1.fill(x.shape, alpha, dtype)); return this.select(nans, x, stepNoNans); }; NodeJSKernelBackend.prototype.conv2d = function (x, filter, convInfo) { if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') { throw new Error("TF Backend supports only 'valid' and 'same' padding " + ("while padding was " + convInfo.padInfo.type)); } var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1]; var padding = convInfo.padInfo.type; var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW'; var dilations = [1, convInfo.dilationHeight, convInfo.dilationWidth, 1]; var opAttrs = [ createTypeOpAttr('T', x.dtype), { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides }, { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, { name: 'data_format', type: this.binding.TF_ATTR_STRING, value: dataFormat }, { name: 'use_cudnn_on_gpu', type: this.binding.TF_ATTR_BOOL, value: true }, { name: 'dilations', type: this.binding.TF_ATTR_INT, value: dilations }, ]; return this.executeSingleOutput('Conv2D', opAttrs, [x, filter]); }; NodeJSKernelBackend.prototype.conv2dDerInput = function (dy, filter, convInfo) { if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') { throw new Error("TF Backend supports only 'valid' and 'same' padding " + ("while padding was " + convInfo.padInfo.type)); } var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1]; var padding = convInfo.padInfo.type; var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW'; var dilations = [1, convInfo.dilationHeight, convInfo.dilationWidth, 1]; var opAttrs = [ createTypeOpAttr('T', 'float32'), { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides }, { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, { name: 'data_format', type: this.binding.TF_ATTR_STRING, value: dataFormat }, { name: 'use_cudnn_on_gpu', type: this.binding.TF_ATTR_BOOL, value: true }, { name: 'dilations', type: this.binding.TF_ATTR_INT, value: dilations } ]; var inputSizes = tfjs_core_1.tensor1d(convInfo.inShape, 'int32'); return this.executeSingleOutput('Conv2DBackpropInput', opAttrs, [inputSizes, filter, dy]); }; NodeJSKernelBackend.prototype.conv2dDerFilter = function (x, dy, convInfo) { if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') { throw new Error("TF Backend supports only 'valid' and 'same' padding " + ("while padding was " + convInfo.padInfo.type)); } var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1]; var padding = convInfo.padInfo.type; var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW'; var dilations = [1, convInfo.dilationHeight, convInfo.dilationWidth, 1]; var opAttrs = [ createTypeOpAttr('T', 'float32'), { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides }, { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, { name: 'data_format', type: this.binding.TF_ATTR_STRING, value: dataFormat }, { name: 'use_cudnn_on_gpu', type: this.binding.TF_ATTR_BOOL, value: true }, { name: 'dilations', type: this.binding.TF_ATTR_INT, value: dilations } ]; var filterSizes = tfjs_core_1.tensor1d(convInfo.filterShape, 'int32'); return this.executeSingleOutput('Conv2DBackpropFilter', opAttrs, [x, filterSizes, dy]); }; NodeJSKernelBackend.prototype.depthwiseConv2DDerInput = function (dy, filter, convInfo) { var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1]; var padding = convInfo.padInfo.type; var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW'; var dilations = [1, convInfo.dilationHeight, convInfo.dilationWidth, 1]; var opAttrs = [ createTypeOpAttr('T', 'float32'), { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides }, { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, { name: 'data_format', type: this.binding.TF_ATTR_STRING, value: dataFormat }, { name: 'dilations', type: this.binding.TF_ATTR_INT, value: dilations } ]; var inputSizes = tfjs_core_1.tensor1d(convInfo.inShape, 'int32'); return this.executeSingleOutput('DepthwiseConv2dNativeBackpropInput', opAttrs, [inputSizes, filter, dy]); }; NodeJSKernelBackend.prototype.depthwiseConv2DDerFilter = function (x, dY, convInfo) { var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1]; var padding = convInfo.padInfo.type; var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW'; var dilations = [1, convInfo.dilationHeight, convInfo.dilationWidth, 1]; var opAttrs = [ createTypeOpAttr('T', 'float32'), { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides }, { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, { name: 'data_format', type: this.binding.TF_ATTR_STRING, value: dataFormat }, { name: 'dilations', type: this.binding.TF_ATTR_INT, value: dilations } ]; var filterSizes = tfjs_core_1.tensor1d(convInfo.filterShape, 'int32'); return this.executeSingleOutput('DepthwiseConv2dNativeBackpropFilter', opAttrs, [x, filterSizes, dY]); }; NodeJSKernelBackend.prototype.fusedDepthwiseConv2D = function (_a) { var input = _a.input, filter = _a.filter, convInfo = _a.convInfo, bias = _a.bias, activation = _a.activation, preluActivationWeights = _a.preluActivationWeights; var result = this.depthwiseConv2D(input, filter, convInfo); if (bias != null) { result = this.add(result, bias); } result = this.applyActivation(result, activation, preluActivationWeights); return result; }; NodeJSKernelBackend.prototype.depthwiseConv2D = function (input, filter, convInfo) { if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') { throw new Error("TF Backend supports only 'valid' and 'same' padding " + ("while padding was " + convInfo.padInfo.type)); } var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1]; var padding = convInfo.padInfo.type; var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW'; var dilations = [1, convInfo.dilationHeight, convInfo.dilationWidth, 1]; var opAttrs = [ createTypeOpAttr('T', input.dtype), { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides }, { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, { name: 'data_format', type: this.binding.TF_ATTR_STRING, value: dataFormat }, { name: 'dilations', type: this.binding.TF_ATTR_INT, value: dilations } ]; return this.executeSingleOutput('DepthwiseConv2dNative', opAttrs, [input, filter]); }; NodeJSKernelBackend.prototype.conv3d = function (x, filter, convInfo) { var strides = [ 1, convInfo.strideDepth, convInfo.strideHeight, convInfo.strideWidth, 1 ]; var padding = convInfo.padInfo.type; var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NDHWC' : 'NCDHW'; if (!this.isGPUPackage && convInfo.dilationDepth > 1) { throw new Error('CPU Dilation depth must be 1'); } var dilations = [ 1, convInfo.dilationDepth, convInfo.dilationHeight, convInfo.dilationWidth, 1 ]; var opAttrs = [ createTypeOpAttr('T', x.dtype), { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides }, { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, { name: 'data_format', type: this.binding.TF_ATTR_STRING, value: dataFormat }, { name: 'dilations', type: this.binding.TF_ATTR_INT, value: dilations } ]; return this.executeSingleOutput('Conv3D', opAttrs, [x, filter]); }; NodeJSKernelBackend.prototype.conv3dDerInput = function (dy, filter, convInfo) { var strides = [ 1, convInfo.strideDepth, convInfo.strideHeight, convInfo.strideWidth, 1 ]; var padding = convInfo.padInfo.type; var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NDHWC' : 'NCDHW'; if (!this.isGPUPackage && convInfo.dilationDepth > 1) { throw new Error('CPU Dilation depth must be 1'); } var dilations = [ 1, convInfo.dilationDepth, convInfo.dilationHeight, convInfo.dilationWidth, 1 ]; var opAttrs = [ createTypeOpAttr('T', dy.dtype), { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides }, { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, { name: 'data_format', type: this.binding.TF_ATTR_STRING, value: dataFormat }, { name: 'dilations', type: this.binding.TF_ATTR_INT, value: dilations }, createTypeOpAttr('Tshape', 'int32') ]; var inputSizes = tfjs_core_1.tensor1d(convInfo.inShape, 'int32'); return this.executeSingleOutput('Conv3DBackpropInputV2', opAttrs, [inputSizes, filter, dy]); }; NodeJSKernelBackend.prototype.conv3dDerFilter = function (x, dY, convInfo) { var strides = [ 1, convInfo.strideDepth, convInfo.strideHeight, convInfo.strideWidth, 1 ]; var padding = convInfo.padInfo.type; var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NDHWC' : 'NCDHW'; if (!this.isGPUPackage && convInfo.dilationDepth > 1) { throw new Error('CPU Dilation depth must be 1'); } var dilations = [ 1, convInfo.dilationDepth, convInfo.dilationHeight, convInfo.dilationWidth, 1 ]; var opAttrs = [ createTypeOpAttr('T', x.dtype), { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides }, { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, { name: 'data_format', type: this.binding.TF_ATTR_STRING, value: dataFormat }, { name: 'dilations', type: this.binding.TF_ATTR_INT, value: dilations } ]; var filterSizes = tfjs_core_1.tensor1d(convInfo.filterShape, 'int32'); return this.executeSingleOutput('Conv3DBackpropFilterV2', opAttrs, [x, filterSizes, dY]); }; NodeJSKernelBackend.prototype.maxPool = function (x, convInfo) { if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') { throw new Error("TF Backend supports only 'valid' and 'same' padding " + ("while padding was " + convInfo.padInfo.type)); } var ksize = [1, convInfo.filterHeight, convInfo.filterWidth, 1]; var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1]; var padding = convInfo.padInfo.type; var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW'; var opAttrs = [ createTypeOpAttr('T', x.dtype), { name: 'ksize', type: this.binding.TF_ATTR_INT, value: ksize }, { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides }, { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, { name: 'data_format', type: this.binding.TF_ATTR_STRING, value: dataFormat } ]; return this.executeSingleOutput('MaxPool', opAttrs, [x]); }; NodeJSKernelBackend.prototype.maxPoolBackprop = function (dy, x, y, convInfo) { if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') { throw new Error("TF Backend supports only 'valid' and 'same' padding " + ("while padding type was " + convInfo.padInfo.type)); } var ksize = [1, convInfo.filterHeight, convInfo.filterWidth, 1]; var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1]; var padding = convInfo.padInfo.type; var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW'; var opAttrs = [ createTypeOpAttr('T', x.dtype), { name: 'ksize', type: this.binding.TF_ATTR_INT, value: ksize }, { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides }, { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, { name: 'data_format', type: this.binding.TF_ATTR_STRING, value: dataFormat }, ]; return this.executeSingleOutput('MaxPoolGrad', opAttrs, [x, y, dy]); }; NodeJSKernelBackend.prototype.avgPool = function (x, convInfo) { if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') { throw new Error("TF Backend supports only 'valid' and 'same' padding " + ("while padding was " + convInfo.padInfo.type)); } var ksize = [1, convInfo.filterHeight, convInfo.filterWidth, 1]; var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1]; var padding = convInfo.padInfo.type; var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW'; var opAttrs = [ createTypeOpAttr('T', x.dtype), { name: 'ksize', type: this.binding.TF_ATTR_INT, value: ksize }, { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides }, { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, { name: 'data_format', type: this.binding.TF_ATTR_STRING, value: dataFormat }, ]; return this.executeSingleOutput('AvgPool', opAttrs, [x]); }; NodeJSKernelBackend.prototype.avgPoolBackprop = function (dy, x, convInfo) { if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') { throw new Error("TF Backend supports only 'valid' and 'same' padding " + ("while padding type was " + convInfo.padInfo.type)); } var ksize = [1, convInfo.filterHeight, convInfo.filterWidth, 1]; var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1]; var padding = convInfo.padInfo.type; var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW'; var opAttrs = [ createTypeOpAttr('T', x.dtype), { name: 'ksize', type: this.binding.TF_ATTR_INT, value: ksize }, { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides }, { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, { name: 'data_format', type: this.binding.TF_ATTR_STRING, value: dataFormat }, ]; var origInputShape = tfjs_core_1.tensor1d(x.shape, 'int32'); return this.executeSingleOutput('AvgPoolGrad', opAttrs, [origInputShape, dy]);