UNPKG

82.1 kBJavaScriptView Raw
1"use strict";
2/**
3 * @license
4 * Copyright 2018 Google Inc. All Rights Reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 * =============================================================================
17 */
18var __extends = (this && this.__extends) || (function () {
19 var extendStatics = function (d, b) {
20 extendStatics = Object.setPrototypeOf ||
21 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
22 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
23 return extendStatics(d, b);
24 };
25 return function (d, b) {
26 extendStatics(d, b);
27 function __() { this.constructor = d; }
28 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
29 };
30})();
31var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
32 return new (P || (P = Promise))(function (resolve, reject) {
33 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
34 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
35 function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
36 step((generator = generator.apply(thisArg, _arguments || [])).next());
37 });
38};
39var __generator = (this && this.__generator) || function (thisArg, body) {
40 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
41 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
42 function verb(n) { return function (v) { return step([n, v]); }; }
43 function step(op) {
44 if (f) throw new TypeError("Generator is already executing.");
45 while (_) try {
46 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;
47 if (y = 0, t) op = [op[0] & 2, t.value];
48 switch (op[0]) {
49 case 0: case 1: t = op; break;
50 case 4: _.label++; return { value: op[1], done: false };
51 case 5: _.label++; y = op[1]; op = [0]; continue;
52 case 7: op = _.ops.pop(); _.trys.pop(); continue;
53 default:
54 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
55 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
56 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
57 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
58 if (t[2]) _.ops.pop();
59 _.trys.pop(); continue;
60 }
61 op = body.call(thisArg, _);
62 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
63 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
64 }
65};
66Object.defineProperty(exports, "__esModule", { value: true });
67var tf = require("@tensorflow/tfjs");
68var tfjs_1 = require("@tensorflow/tfjs");
69var util_1 = require("util");
70var int64_tensors_1 = require("./int64_tensors");
71var NodeJSKernelBackend = /** @class */ (function (_super) {
72 __extends(NodeJSKernelBackend, _super);
73 function NodeJSKernelBackend(binding, packageName) {
74 var _this = _super.call(this) || this;
75 _this.binding = binding;
76 _this.isGPUPackage = packageName === '@tensorflow/tfjs-node-gpu';
77 _this.isUsingGpuDevice = _this.binding.isUsingGpuDevice();
78 _this.tensorMap = new tf.DataStorage(_this, tf.engine());
79 return _this;
80 }
81 NodeJSKernelBackend.prototype.getDTypeInteger = function (dtype) {
82 switch (dtype) {
83 case 'float32':
84 return this.binding.TF_FLOAT;
85 case 'int32':
86 return this.binding.TF_INT32;
87 case 'bool':
88 return this.binding.TF_BOOL;
89 case 'complex64':
90 return this.binding.TF_COMPLEX64;
91 case 'string':
92 return this.binding.TF_STRING;
93 default:
94 throw new Error("Unsupported DType: " + dtype);
95 }
96 };
97 NodeJSKernelBackend.prototype.typeAttributeFromTensor = function (value) {
98 return this.getDTypeInteger(value.dtype);
99 };
100 // Creates a new Tensor and maps the dataId to the passed in ID.
101 NodeJSKernelBackend.prototype.createOutputTensor = function (metadata) {
102 var newId = {};
103 this.tensorMap.set(newId, {
104 shape: metadata.shape,
105 dtype: metadata.dtype,
106 id: metadata.id,
107 values: null
108 });
109 var dtype;
110 switch (metadata.dtype) {
111 case this.binding.TF_FLOAT:
112 dtype = 'float32';
113 break;
114 case this.binding.TF_INT32:
115 dtype = 'int32';
116 break;
117 case this.binding.TF_BOOL:
118 dtype = 'bool';
119 break;
120 case this.binding.TF_COMPLEX64:
121 dtype = 'complex64';
122 break;
123 case this.binding.TF_STRING:
124 dtype = 'string';
125 break;
126 case this.binding.TF_RESOURCE:
127 // NOTE(cais): We currently represent resource-type Tensors
128 // as string of ubytes.
129 dtype = 'string';
130 break;
131 case this.binding.TF_UINT8:
132 // TensorFlow uses UINT8 as dtype for image tensor. UINT8 is not
133 // supported in TFJS yet, cast it to int32.
134 dtype = 'int32';
135 break;
136 default:
137 throw new Error("Unknown dtype enum " + metadata.dtype);
138 }
139 return tf.engine().makeTensorFromDataId(newId, metadata.shape, dtype);
140 };
141 // Prepares Tensor instances for Op execution.
142 NodeJSKernelBackend.prototype.getInputTensorIds = function (tensors) {
143 var ids = [];
144 for (var i = 0; i < tensors.length; i++) {
145 if (tensors[i] instanceof int64_tensors_1.Int64Scalar) {
146 // Then `tensors[i]` is a Int64Scalar, which we currently represent
147 // using an `Int32Array`.
148 var value = tensors[i].valueArray;
149 var id = this.binding.createTensor([], this.binding.TF_INT64, value);
150 ids.push(id);
151 }
152 else {
153 var info = this.tensorMap.get(tensors[i].dataId);
154 // TODO - what about ID in this case? Handle in write()??
155 if (info.values != null) {
156 // Values were delayed to write into the TensorHandle. Do that before
157 // Op execution and clear stored values.
158 info.id =
159 this.binding.createTensor(info.shape, info.dtype, info.values);
160 info.values = null;
161 }
162 ids.push(info.id);
163 }
164 }
165 return ids;
166 };
167 NodeJSKernelBackend.prototype.createReductionOpAttrs = function (tensor) {
168 return [
169 { name: 'keep_dims', type: this.binding.TF_ATTR_BOOL, value: false },
170 createTensorsTypeOpAttr('T', tensor.dtype),
171 createTensorsTypeOpAttr('Tidx', 'int32')
172 ];
173 };
174 NodeJSKernelBackend.prototype.executeSingleInput = function (name, input) {
175 var opAttrs = [createTensorsTypeOpAttr('T', input.dtype)];
176 return this.executeSingleOutput(name, opAttrs, [input]);
177 };
178 NodeJSKernelBackend.prototype.floatPrecision = function () {
179 return 32;
180 };
181 NodeJSKernelBackend.prototype.epsilon = function () {
182 return _super.prototype.epsilon.call(this);
183 };
184 /**
185 * Executes a TensorFlow Eager Op that provides one output Tensor.
186 * @param name The name of the Op to execute.
187 * @param opAttrs The list of Op attributes required to execute.
188 * @param inputs The list of input Tensors for the Op.
189 * @return A resulting Tensor from Op execution.
190 */
191 NodeJSKernelBackend.prototype.executeSingleOutput = function (name, opAttrs, inputs) {
192 var outputMetadata = this.binding.executeOp(name, opAttrs, this.getInputTensorIds(inputs), 1);
193 return this.createOutputTensor(outputMetadata[0]);
194 };
195 /**
196 * Executes a TensorFlow Eager Op that provides multiple output Tensors.
197 * @param name The name of the Op to execute.
198 * @param opAttrs The list of Op attributes required to execute.
199 * @param inputs The list of input Tensors for the Op.
200 * @param numOutputs The number of output Tensors for Op execution.
201 * @return A resulting Tensor array from Op execution.
202 */
203 NodeJSKernelBackend.prototype.executeMultipleOutputs = function (name, opAttrs, inputs, numOutputs) {
204 var _this = this;
205 var outputMetadata = this.binding.executeOp(name, opAttrs, this.getInputTensorIds(inputs), numOutputs);
206 return outputMetadata.map(function (m) { return _this.createOutputTensor(m); });
207 };
208 NodeJSKernelBackend.prototype.numDataIds = function () {
209 return this.tensorMap.numDataIds();
210 };
211 NodeJSKernelBackend.prototype.dispose = function () { };
212 NodeJSKernelBackend.prototype.read = function (dataId) {
213 return __awaiter(this, void 0, void 0, function () {
214 return __generator(this, function (_a) {
215 return [2 /*return*/, this.readSync(dataId)];
216 });
217 });
218 };
219 NodeJSKernelBackend.prototype.readSync = function (dataId) {
220 if (!this.tensorMap.has(dataId)) {
221 throw new Error("Tensor " + dataId + " was not registered!");
222 }
223 var info = this.tensorMap.get(dataId);
224 if (info.values != null) {
225 return info.values;
226 }
227 else {
228 return this.binding.tensorDataSync(info.id);
229 }
230 };
231 NodeJSKernelBackend.prototype.disposeData = function (dataId) {
232 // No-op if already disposed.
233 if (!this.tensorMap.has(dataId)) {
234 return;
235 }
236 var id = this.tensorMap.get(dataId).id;
237 if (id != null && id >= 0) {
238 this.binding.deleteTensor(id);
239 }
240 this.tensorMap.delete(dataId);
241 };
242 NodeJSKernelBackend.prototype.move = function (dataId, values, shape, dtype) {
243 this.tensorMap.set(dataId, { shape: shape, dtype: getTFDType(dtype), values: values, id: -1 });
244 };
245 NodeJSKernelBackend.prototype.write = function (values, shape, dtype) {
246 var dataId = {};
247 this.move(dataId, values, shape, dtype);
248 return dataId;
249 };
250 NodeJSKernelBackend.prototype.fill = function (shape, value, dtype) {
251 // TODO(cais, nkreeger): Investigate whether this can be made into
252 // a dtype helper method. The underlying op kernel doesn't accept undefined
253 // or null dtype.
254 if (dtype == null) {
255 if (typeof value === 'number') {
256 dtype = 'float32';
257 }
258 else {
259 dtype = 'string';
260 }
261 }
262 var shapeTensor = tfjs_1.tensor1d(shape, 'int32');
263 var valueTensor = tfjs_1.scalar(value, dtype);
264 var opAttrs = [
265 {
266 name: 'T',
267 type: this.binding.TF_ATTR_TYPE,
268 value: this.getDTypeInteger(dtype)
269 },
270 {
271 name: 'index_type',
272 type: this.binding.TF_ATTR_TYPE,
273 value: this.binding.TF_INT32
274 }
275 ];
276 return this.executeSingleOutput('Fill', opAttrs, [shapeTensor, valueTensor]);
277 };
278 NodeJSKernelBackend.prototype.onesLike = function (x) {
279 var opAttrs = [{
280 name: 'T',
281 type: this.binding.TF_ATTR_TYPE,
282 value: this.getDTypeInteger(x.dtype)
283 }];
284 return this.executeSingleOutput('OnesLike', opAttrs, [x]);
285 };
286 NodeJSKernelBackend.prototype.zerosLike = function (x) {
287 var opAttrs = [{
288 name: 'T',
289 type: this.binding.TF_ATTR_TYPE,
290 value: this.getDTypeInteger(x.dtype)
291 }];
292 return this.executeSingleOutput('ZerosLike', opAttrs, [x]);
293 };
294 NodeJSKernelBackend.prototype.stridedSlice = function (x, begin, end, strides) {
295 var beginTensor = tfjs_1.tensor1d(begin, 'int32');
296 for (var axis = 0; axis < end.length; axis++) {
297 // Unlike Numpy, when the strides are negative, TF C uses -n-1 instead of
298 // -1 as the "end" in order to include the first element.
299 if (strides[axis] < 0 && end[axis] === -1) {
300 end[axis] -= x.shape[axis];
301 }
302 }
303 var endTensor = tfjs_1.tensor1d(end, 'int32');
304 var stridesTensor = tfjs_1.tensor1d(strides, 'int32');
305 // All of the masks have already been accounted for in the high level op,
306 // so the backend does NOT need to deal with masks.
307 var opAttrs = [
308 createTensorsTypeOpAttr('T', x.dtype),
309 createTensorsTypeOpAttr('Index', 'int32'),
310 { name: 'begin_mask', type: this.binding.TF_ATTR_INT, value: 0 },
311 { name: 'end_mask', type: this.binding.TF_ATTR_INT, value: 0 },
312 { name: 'ellipsis_mask', type: this.binding.TF_ATTR_INT, value: 0 },
313 { name: 'new_axis_mask', type: this.binding.TF_ATTR_INT, value: 0 },
314 { name: 'shrink_axis_mask', type: this.binding.TF_ATTR_INT, value: 0 }
315 ];
316 return this.executeSingleOutput('StridedSlice', opAttrs, [x, beginTensor, endTensor, stridesTensor]);
317 };
318 NodeJSKernelBackend.prototype.unstack = function (x, axis) {
319 if (axis >= x.shape.length) {
320 throw new Error("Invalid axis supplied: " + axis + " shape length: " + x.shape.length);
321 }
322 var num = x.shape[axis];
323 var opAttrs = [
324 { name: 'num', type: this.binding.TF_ATTR_INT, value: num },
325 createTensorsTypeOpAttr('T', x.dtype),
326 { name: 'axis', type: this.binding.TF_ATTR_INT, value: axis }
327 ];
328 return this.executeMultipleOutputs('Unpack', opAttrs, [x], num);
329 };
330 NodeJSKernelBackend.prototype.batchMatMul = function (a, b, transposeA, transposeB) {
331 var opAttrs = [
332 createTensorsTypeOpAttr('T', a.dtype),
333 { name: 'adj_x', type: this.binding.TF_ATTR_BOOL, value: transposeA },
334 { name: 'adj_y', type: this.binding.TF_ATTR_BOOL, value: transposeB }
335 ];
336 return this.executeSingleOutput('BatchMatMul', opAttrs, [a, b]);
337 };
338 NodeJSKernelBackend.prototype.applyActivation = function (input, activation, preluActivationWeights) {
339 var result = input;
340 if (activation != null) {
341 if (activation === 'linear') {
342 // No-op
343 }
344 else if (activation === 'relu') {
345 result = this.relu(result);
346 }
347 else if (activation === 'prelu') {
348 result = this.prelu(result, preluActivationWeights);
349 }
350 else if (activation === 'elu') {
351 result = this.elu(result);
352 }
353 else if (activation === 'relu6') {
354 result = this.relu6(result);
355 }
356 else {
357 throw new Error("Activation: " + activation + " has not been implemented for the Node.js backend");
358 }
359 }
360 return result;
361 };
362 NodeJSKernelBackend.prototype.fusedConv2d = function (_a) {
363 var input = _a.input, filter = _a.filter, convInfo = _a.convInfo, bias = _a.bias, activation = _a.activation, preluActivationWeights = _a.preluActivationWeights;
364 var result = this.conv2d(input, filter, convInfo);
365 if (bias != null) {
366 result = this.add(result, bias);
367 }
368 result = this.applyActivation(result, activation, preluActivationWeights);
369 return result;
370 };
371 NodeJSKernelBackend.prototype.fusedBatchMatMul = function (_a) {
372 var a = _a.a, b = _a.b, transposeA = _a.transposeA, transposeB = _a.transposeB, bias = _a.bias, activation = _a.activation, preluActivationWeights = _a.preluActivationWeights;
373 // Core TensorFlow does not have a fused BatchMatMul op. Combine calls to
374 // achieve the same results:
375 var result = this.batchMatMul(a, b, transposeA, transposeB);
376 if (bias != null) {
377 result = this.add(result, bias);
378 }
379 result = this.applyActivation(result, activation, preluActivationWeights);
380 return result;
381 };
382 NodeJSKernelBackend.prototype.slice = function (x, begin, size) {
383 var opAttrs = [
384 createTensorsTypeOpAttr('T', x.dtype),
385 createTensorsTypeOpAttr('Index', 'int32')
386 ];
387 // Bind tensor values
388 var beginTensor = tfjs_1.tensor1d(begin, 'int32');
389 var sizeTensor = tfjs_1.tensor1d(size, 'int32');
390 return this.executeSingleOutput('Slice', opAttrs, [x, beginTensor, sizeTensor]);
391 };
392 NodeJSKernelBackend.prototype.reverse = function (a, axis) {
393 var opAttrs = [
394 createTensorsTypeOpAttr('Tidx', 'int32'),
395 createTensorsTypeOpAttr('T', a.dtype)
396 ];
397 var axisTensor = tfjs_1.tensor1d(axis, 'int32');
398 return this.executeSingleOutput('ReverseV2', opAttrs, [a, axisTensor]);
399 };
400 NodeJSKernelBackend.prototype.concat = function (tensors, axis) {
401 var opAttrs = [
402 { name: 'N', type: this.binding.TF_ATTR_INT, value: tensors.length }, {
403 name: 'Tidx',
404 type: this.binding.TF_ATTR_TYPE,
405 value: this.binding.TF_INT32
406 },
407 createTensorsTypeOpAttr('T', tensors)
408 ];
409 var inputs = Array.from(tensors);
410 inputs.push(tfjs_1.scalar(axis, 'int32'));
411 return this.executeSingleOutput('ConcatV2', opAttrs, inputs);
412 };
413 NodeJSKernelBackend.prototype.neg = function (a) {
414 return this.executeSingleInput('Neg', a);
415 };
416 NodeJSKernelBackend.prototype.diag = function (x) {
417 return this.executeSingleInput('Diag', x);
418 };
419 NodeJSKernelBackend.prototype.add = function (a, b) {
420 var opAttrs = [createTensorsTypeOpAttr('T', tfjs_1.backend_util.upcastType(a.dtype, b.dtype))];
421 return this.executeSingleOutput('Add', opAttrs, [a, b]);
422 };
423 NodeJSKernelBackend.prototype.select = function (condition, a, b) {
424 var opAttrs = [createTensorsTypeOpAttr('T', tfjs_1.backend_util.upcastType(a.dtype, b.dtype))];
425 return this.executeSingleOutput('Select', opAttrs, [condition, a, b]);
426 };
427 NodeJSKernelBackend.prototype.addN = function (tensors) {
428 var opAttrs = [
429 createTensorsTypeOpAttr('T', tensors[0].dtype),
430 { name: 'N', type: this.binding.TF_ATTR_INT, value: tensors.length }
431 ];
432 return this.executeSingleOutput('AddN', opAttrs, tensors);
433 };
434 NodeJSKernelBackend.prototype.subtract = function (a, b) {
435 var opAttrs = [createTensorsTypeOpAttr('T', tfjs_1.backend_util.upcastType(a.dtype, b.dtype))];
436 return this.executeSingleOutput('Sub', opAttrs, [a, b]);
437 };
438 NodeJSKernelBackend.prototype.multiply = function (a, b) {
439 var opAttrs = [createTensorsTypeOpAttr('T', tfjs_1.backend_util.upcastType(a.dtype, b.dtype))];
440 return this.executeSingleOutput('Mul', opAttrs, [a, b]);
441 };
442 NodeJSKernelBackend.prototype.realDivide = function (a, b) {
443 var opAttrs = [createTensorsTypeOpAttr('T', tfjs_1.backend_util.upcastType(a.dtype, b.dtype))];
444 return this.executeSingleOutput('RealDiv', opAttrs, [a, b]);
445 };
446 NodeJSKernelBackend.prototype.floorDiv = function (a, b) {
447 var opAttrs = [createTensorsTypeOpAttr('T', tfjs_1.backend_util.upcastType(a.dtype, b.dtype))];
448 return this.executeSingleOutput('FloorDiv', opAttrs, [a, b]);
449 };
450 NodeJSKernelBackend.prototype.divide = function (a, b) {
451 var opAttrs = [createTensorsTypeOpAttr('T', tfjs_1.backend_util.upcastType(a.dtype, b.dtype))];
452 return this.executeSingleOutput('Div', opAttrs, [a, b]);
453 };
454 NodeJSKernelBackend.prototype.divNoNan = function (a, b) {
455 var opAttrs = [createTensorsTypeOpAttr('T', tfjs_1.backend_util.upcastType(a.dtype, b.dtype))];
456 return this.executeSingleOutput('DivNoNan', opAttrs, [a, b]);
457 };
458 NodeJSKernelBackend.prototype.unsortedSegmentSum = function (x, segmentIds, numSegments) {
459 var opAttrs = [
460 createTensorsTypeOpAttr('T', x.dtype),
461 createTensorsTypeOpAttr('Tindices', 'int32'),
462 createTensorsTypeOpAttr('Tnumsegments', 'int32')
463 ];
464 return this.executeSingleOutput('UnsortedSegmentSum', opAttrs, [x, segmentIds, tfjs_1.scalar(numSegments, 'int32')]);
465 };
466 NodeJSKernelBackend.prototype.sum = function (x, axes) {
467 var axisTensor = tfjs_1.tensor1d(axes, 'int32');
468 return this.executeSingleOutput('Sum', this.createReductionOpAttrs(x), [x, axisTensor]);
469 };
470 NodeJSKernelBackend.prototype.prod = function (x, axes) {
471 var axesTensor = tfjs_1.tensor1d(axes, 'int32');
472 var opAttrs = [
473 { name: 'keep_dims', type: this.binding.TF_ATTR_BOOL, value: false },
474 createTensorsTypeOpAttr('T', x.dtype),
475 createTensorsTypeOpAttr('Tidx', 'int32')
476 ];
477 return this.executeSingleOutput('Prod', opAttrs, [x, axesTensor]);
478 };
479 NodeJSKernelBackend.prototype.argMin = function (x, axis) {
480 var xInput = x.dtype === 'bool' ? x.toInt() : x;
481 var axisScalar = tfjs_1.scalar(axis, 'int32');
482 var opAttrs = [
483 createTensorsTypeOpAttr('T', xInput.dtype),
484 createTensorsTypeOpAttr('Tidx', 'int32'),
485 createTensorsTypeOpAttr('output_type', 'int32')
486 ];
487 return this.executeSingleOutput('ArgMin', opAttrs, [xInput, axisScalar]);
488 };
489 NodeJSKernelBackend.prototype.argMax = function (x, axis) {
490 var xInput = x.dtype === 'bool' ? x.toInt() : x;
491 var axisScalar = tfjs_1.scalar(axis, 'int32');
492 var opAttrs = [
493 createTensorsTypeOpAttr('T', xInput.dtype),
494 createTensorsTypeOpAttr('Tidx', 'int32'),
495 createTensorsTypeOpAttr('output_type', 'int32')
496 ];
497 return this.executeSingleOutput('ArgMax', opAttrs, [xInput, axisScalar]);
498 };
499 NodeJSKernelBackend.prototype.equal = function (a, b) {
500 var opAttrs = [createTensorsTypeOpAttr('T', tfjs_1.backend_util.upcastType(a.dtype, b.dtype))];
501 return this.executeSingleOutput('Equal', opAttrs, [a, b]);
502 };
503 NodeJSKernelBackend.prototype.notEqual = function (a, b) {
504 var opAttrs = [createTensorsTypeOpAttr('T', tfjs_1.backend_util.upcastType(a.dtype, b.dtype))];
505 return this.executeSingleOutput('NotEqual', opAttrs, [a, b]);
506 };
507 NodeJSKernelBackend.prototype.less = function (a, b) {
508 var opAttrs = [createTensorsTypeOpAttr('T', tfjs_1.backend_util.upcastType(a.dtype, b.dtype))];
509 return this.executeSingleOutput('Less', opAttrs, [a, b]);
510 };
511 NodeJSKernelBackend.prototype.lessEqual = function (a, b) {
512 var opAttrs = [createTensorsTypeOpAttr('T', tfjs_1.backend_util.upcastType(a.dtype, b.dtype))];
513 return this.executeSingleOutput('LessEqual', opAttrs, [a, b]);
514 };
515 NodeJSKernelBackend.prototype.greater = function (a, b) {
516 var opAttrs = [createTensorsTypeOpAttr('T', tfjs_1.backend_util.upcastType(a.dtype, b.dtype))];
517 return this.executeSingleOutput('Greater', opAttrs, [a, b]);
518 };
519 NodeJSKernelBackend.prototype.greaterEqual = function (a, b) {
520 var opAttrs = [createTensorsTypeOpAttr('T', tfjs_1.backend_util.upcastType(a.dtype, b.dtype))];
521 return this.executeSingleOutput('GreaterEqual', opAttrs, [a, b]);
522 };
523 NodeJSKernelBackend.prototype.logicalNot = function (a) {
524 return this.executeSingleOutput('LogicalNot', [], [a]);
525 };
526 NodeJSKernelBackend.prototype.logicalAnd = function (a, b) {
527 return this.executeSingleOutput('LogicalAnd', [], [a, b]);
528 };
529 NodeJSKernelBackend.prototype.logicalOr = function (a, b) {
530 return this.executeSingleOutput('LogicalOr', [], [a, b]);
531 };
532 NodeJSKernelBackend.prototype.where = function (condition) {
533 return this.executeSingleOutput('Where', [], [condition]);
534 };
535 NodeJSKernelBackend.prototype.topKValues = function (x, k) {
536 throw new Error('Method not implemented.');
537 };
538 NodeJSKernelBackend.prototype.topKIndices = function (x, k) {
539 throw new Error('Method not implemented.');
540 };
541 NodeJSKernelBackend.prototype.topk = function (x, k, sorted) {
542 var kCount = util_1.isNullOrUndefined(k) ? 1 : k;
543 var isSorted = util_1.isNullOrUndefined(sorted) ? true : sorted;
544 var opAttrs = [
545 { name: 'sorted', type: this.binding.TF_ATTR_BOOL, value: isSorted },
546 createTensorsTypeOpAttr('T', x.dtype),
547 ];
548 var kTensor = tfjs_1.scalar(kCount, 'int32');
549 // 'TopKV2' has two-hard coded output attributes:
550 return this.executeMultipleOutputs('TopKV2', opAttrs, [x, kTensor], 2);
551 };
552 NodeJSKernelBackend.prototype.min = function (x, axes) {
553 var axesTensor = tfjs_1.tensor1d(axes, 'int32');
554 return this.executeSingleOutput('Min', this.createReductionOpAttrs(x), [x, axesTensor]);
555 };
556 NodeJSKernelBackend.prototype.minimum = function (a, b) {
557 var opAttrs = [createTensorsTypeOpAttr('T', tfjs_1.backend_util.upcastType(a.dtype, b.dtype))];
558 return this.executeSingleOutput('Minimum', opAttrs, [a, b]);
559 };
560 NodeJSKernelBackend.prototype.max = function (x, axes) {
561 var axesTensor = tfjs_1.tensor1d(axes, 'int32');
562 return this.executeSingleOutput('Max', this.createReductionOpAttrs(x), [x, axesTensor]);
563 };
564 NodeJSKernelBackend.prototype.maximum = function (a, b) {
565 var opAttrs = [createTensorsTypeOpAttr('T', tfjs_1.backend_util.upcastType(a.dtype, b.dtype))];
566 return this.executeSingleOutput('Maximum', opAttrs, [a, b]);
567 };
568 NodeJSKernelBackend.prototype.all = function (x, axes) {
569 var opAttrs = [
570 { name: 'keep_dims', type: this.binding.TF_ATTR_BOOL, value: false },
571 createTensorsTypeOpAttr('Tidx', 'int32')
572 ];
573 var axesTensor = tfjs_1.tensor1d(axes, 'int32');
574 return this.executeSingleOutput('All', opAttrs, [x, axesTensor]);
575 };
576 NodeJSKernelBackend.prototype.any = function (x, axes) {
577 var opAttrs = [
578 { name: 'keep_dims', type: this.binding.TF_ATTR_BOOL, value: false },
579 createTensorsTypeOpAttr('Tidx', 'int32')
580 ];
581 var axesTensor = tfjs_1.tensor1d(axes, 'int32');
582 return this.executeSingleOutput('Any', opAttrs, [x, axesTensor]);
583 };
584 NodeJSKernelBackend.prototype.ceil = function (x) {
585 return this.executeSingleInput('Ceil', x);
586 };
587 NodeJSKernelBackend.prototype.floor = function (x) {
588 return this.executeSingleInput('Floor', x);
589 };
590 NodeJSKernelBackend.prototype.pow = function (a, b) {
591 var dtype = tfjs_1.backend_util.upcastType(a.dtype, b.dtype);
592 var opAttrs = [createTensorsTypeOpAttr('T', dtype)];
593 return this.executeSingleOutput('Pow', opAttrs, [a.cast(dtype), b.cast(dtype)]);
594 };
595 NodeJSKernelBackend.prototype.exp = function (x) {
596 var xTensor = x.dtype === 'int32' ? x.toFloat() : x;
597 return this.executeSingleInput('Exp', xTensor);
598 };
599 NodeJSKernelBackend.prototype.log = function (x) {
600 return this.executeSingleInput('Log', x);
601 };
602 NodeJSKernelBackend.prototype.log1p = function (x) {
603 return this.executeSingleInput('Log1p', x);
604 };
605 NodeJSKernelBackend.prototype.sqrt = function (x) {
606 return this.executeSingleInput('Sqrt', x);
607 };
608 NodeJSKernelBackend.prototype.square = function (x) {
609 return this.executeSingleInput('Square', x);
610 };
611 NodeJSKernelBackend.prototype.relu = function (x) {
612 return this.executeSingleInput('Relu', x);
613 };
614 NodeJSKernelBackend.prototype.relu6 = function (x) {
615 return this.executeSingleInput('Relu6', x);
616 };
617 NodeJSKernelBackend.prototype.prelu = function (x, a) {
618 var pos = this.relu(x);
619 var neg = a.mul(x.sub(this.abs(x))).mul(0.5);
620 return pos.add(neg);
621 };
622 NodeJSKernelBackend.prototype.elu = function (x) {
623 return this.executeSingleInput('Elu', x);
624 };
625 NodeJSKernelBackend.prototype.eluDer = function (dy, y) {
626 var opAttrs = [createTensorsTypeOpAttr('T', y.dtype)];
627 return this.executeSingleOutput('EluGrad', opAttrs, [dy, y]);
628 };
629 NodeJSKernelBackend.prototype.selu = function (x) {
630 return this.executeSingleInput('Selu', x);
631 };
632 NodeJSKernelBackend.prototype.int = function (x) {
633 throw new Error('Method not implemented.');
634 };
635 NodeJSKernelBackend.prototype.clip = function (x, min, max) {
636 var xMin = this.minimum(x, tfjs_1.scalar(max));
637 return this.maximum(xMin, tfjs_1.scalar(min));
638 };
639 NodeJSKernelBackend.prototype.abs = function (x) {
640 return this.executeSingleInput('Abs', x);
641 };
642 NodeJSKernelBackend.prototype.complexAbs = function (x) {
643 var opAttrs = [
644 createTensorsTypeOpAttr('T', x.dtype),
645 createTensorsTypeOpAttr('Tout', 'float32')
646 ];
647 return this.executeSingleOutput('ComplexAbs', opAttrs, [x]);
648 };
649 NodeJSKernelBackend.prototype.sigmoid = function (x) {
650 return this.executeSingleInput('Sigmoid', x);
651 };
652 NodeJSKernelBackend.prototype.sin = function (x) {
653 return this.executeSingleInput('Sin', x);
654 };
655 NodeJSKernelBackend.prototype.cos = function (x) {
656 return this.executeSingleInput('Cos', x);
657 };
658 NodeJSKernelBackend.prototype.tan = function (x) {
659 return this.executeSingleInput('Tan', x);
660 };
661 NodeJSKernelBackend.prototype.asin = function (x) {
662 return this.executeSingleInput('Asin', x);
663 };
664 NodeJSKernelBackend.prototype.acos = function (x) {
665 return this.executeSingleInput('Acos', x);
666 };
667 NodeJSKernelBackend.prototype.atan = function (x) {
668 return this.executeSingleInput('Atan', x);
669 };
670 NodeJSKernelBackend.prototype.sinh = function (x) {
671 return this.executeSingleInput('Sinh', x);
672 };
673 NodeJSKernelBackend.prototype.cosh = function (x) {
674 return this.executeSingleInput('Cosh', x);
675 };
676 NodeJSKernelBackend.prototype.tanh = function (x) {
677 return this.executeSingleInput('Tanh', x);
678 };
679 NodeJSKernelBackend.prototype.mod = function (a, b) {
680 var opAttrs = [createTensorsTypeOpAttr('T', a.dtype)];
681 return this.executeSingleOutput('FloorMod', opAttrs, [a, b]);
682 };
683 NodeJSKernelBackend.prototype.round = function (x) {
684 return this.executeSingleInput('Round', x);
685 };
686 NodeJSKernelBackend.prototype.sign = function (x) {
687 return this.executeSingleInput('Sign', x);
688 };
689 NodeJSKernelBackend.prototype.isNaN = function (x) {
690 return this.executeSingleInput('IsNan', x);
691 };
692 NodeJSKernelBackend.prototype.isInf = function (x) {
693 return this.executeSingleInput('IsInf', x);
694 };
695 NodeJSKernelBackend.prototype.isFinite = function (x) {
696 return this.executeSingleInput('IsFinite', x);
697 };
698 NodeJSKernelBackend.prototype.rsqrt = function (x) {
699 return this.executeSingleInput('Rsqrt', x);
700 };
701 NodeJSKernelBackend.prototype.reciprocal = function (x) {
702 return this.executeSingleInput('Reciprocal', x);
703 };
704 NodeJSKernelBackend.prototype.asinh = function (x) {
705 return this.executeSingleInput('Asinh', x);
706 };
707 NodeJSKernelBackend.prototype.acosh = function (x) {
708 return this.executeSingleInput('Acosh', x);
709 };
710 NodeJSKernelBackend.prototype.atanh = function (x) {
711 return this.executeSingleInput('Atanh', x);
712 };
713 NodeJSKernelBackend.prototype.erf = function (x) {
714 return this.executeSingleInput('Erf', x);
715 };
716 NodeJSKernelBackend.prototype.squaredDifference = function (a, b) {
717 var opAttrs = [createTensorsTypeOpAttr('T', a.dtype)];
718 return this.executeSingleOutput('SquaredDifference', opAttrs, [a, b]);
719 };
720 NodeJSKernelBackend.prototype.expm1 = function (x) {
721 return this.executeSingleInput('Expm1', x);
722 };
723 NodeJSKernelBackend.prototype.softplus = function (x) {
724 return this.executeSingleInput('Softplus', x);
725 };
726 NodeJSKernelBackend.prototype.atan2 = function (a, b) {
727 var opAttrs = [createTensorsTypeOpAttr('T', a.dtype)];
728 return this.executeSingleOutput('Atan2', opAttrs, [a, b]);
729 };
730 NodeJSKernelBackend.prototype.step = function (x, alpha) {
731 var dtype = x.dtype;
732 var nans = this.isNaN(x);
733 var stepNoNans = this.select(this.greater(x, tfjs_1.scalar(0, dtype)), tfjs_1.ones(x.shape), tfjs_1.fill(x.shape, alpha, dtype));
734 return this.select(nans, x, stepNoNans);
735 };
736 NodeJSKernelBackend.prototype.conv2d = function (x, filter, convInfo) {
737 if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') {
738 throw new Error("TF Backend supports only 'valid' and 'same' padding " +
739 ("while padding was " + convInfo.padInfo.type));
740 }
741 var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1];
742 var padding = convInfo.padInfo.type;
743 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW';
744 var dilations = [1, convInfo.dilationHeight, convInfo.dilationWidth, 1];
745 var opAttrs = [
746 createTensorsTypeOpAttr('T', x.dtype),
747 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
748 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding },
749 {
750 name: 'data_format',
751 type: this.binding.TF_ATTR_STRING,
752 value: dataFormat
753 },
754 { name: 'use_cudnn_on_gpu', type: this.binding.TF_ATTR_BOOL, value: true },
755 { name: 'dilations', type: this.binding.TF_ATTR_INT, value: dilations },
756 ];
757 return this.executeSingleOutput('Conv2D', opAttrs, [x, filter]);
758 };
759 NodeJSKernelBackend.prototype.conv2dDerInput = function (dy, filter, convInfo) {
760 if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') {
761 throw new Error("TF Backend supports only 'valid' and 'same' padding " +
762 ("while padding was " + convInfo.padInfo.type));
763 }
764 var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1];
765 var padding = convInfo.padInfo.type;
766 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW';
767 var dilations = [1, convInfo.dilationHeight, convInfo.dilationWidth, 1];
768 var opAttrs = [
769 createTensorsTypeOpAttr('T', 'float32'),
770 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
771 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, {
772 name: 'data_format',
773 type: this.binding.TF_ATTR_STRING,
774 value: dataFormat
775 },
776 { name: 'use_cudnn_on_gpu', type: this.binding.TF_ATTR_BOOL, value: true },
777 { name: 'dilations', type: this.binding.TF_ATTR_INT, value: dilations }
778 ];
779 var inputSizes = tfjs_1.tensor1d(convInfo.inShape, 'int32');
780 return this.executeSingleOutput('Conv2DBackpropInput', opAttrs, [inputSizes, filter, dy]);
781 };
782 NodeJSKernelBackend.prototype.conv2dDerFilter = function (x, dy, convInfo) {
783 if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') {
784 throw new Error("TF Backend supports only 'valid' and 'same' padding " +
785 ("while padding was " + convInfo.padInfo.type));
786 }
787 var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1];
788 var padding = convInfo.padInfo.type;
789 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW';
790 var dilations = [1, convInfo.dilationHeight, convInfo.dilationWidth, 1];
791 var opAttrs = [
792 createTensorsTypeOpAttr('T', 'float32'),
793 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
794 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, {
795 name: 'data_format',
796 type: this.binding.TF_ATTR_STRING,
797 value: dataFormat
798 },
799 { name: 'use_cudnn_on_gpu', type: this.binding.TF_ATTR_BOOL, value: true },
800 { name: 'dilations', type: this.binding.TF_ATTR_INT, value: dilations }
801 ];
802 var filterSizes = tfjs_1.tensor1d(convInfo.filterShape, 'int32');
803 return this.executeSingleOutput('Conv2DBackpropFilter', opAttrs, [x, filterSizes, dy]);
804 };
805 NodeJSKernelBackend.prototype.depthwiseConv2DDerInput = function (dy, filter, convInfo) {
806 var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1];
807 var padding = convInfo.padInfo.type;
808 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW';
809 var dilations = [1, convInfo.dilationHeight, convInfo.dilationWidth, 1];
810 var opAttrs = [
811 createTensorsTypeOpAttr('T', 'float32'),
812 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
813 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, {
814 name: 'data_format',
815 type: this.binding.TF_ATTR_STRING,
816 value: dataFormat
817 },
818 { name: 'dilations', type: this.binding.TF_ATTR_INT, value: dilations }
819 ];
820 var inputSizes = tfjs_1.tensor1d(convInfo.inShape, 'int32');
821 return this.executeSingleOutput('DepthwiseConv2dNativeBackpropInput', opAttrs, [inputSizes, filter, dy]);
822 };
823 NodeJSKernelBackend.prototype.depthwiseConv2DDerFilter = function (x, dY, convInfo) {
824 var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1];
825 var padding = convInfo.padInfo.type;
826 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW';
827 var dilations = [1, convInfo.dilationHeight, convInfo.dilationWidth, 1];
828 var opAttrs = [
829 createTensorsTypeOpAttr('T', 'float32'),
830 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
831 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, {
832 name: 'data_format',
833 type: this.binding.TF_ATTR_STRING,
834 value: dataFormat
835 },
836 { name: 'dilations', type: this.binding.TF_ATTR_INT, value: dilations }
837 ];
838 var filterSizes = tfjs_1.tensor1d(convInfo.filterShape, 'int32');
839 return this.executeSingleOutput('DepthwiseConv2dNativeBackpropFilter', opAttrs, [x, filterSizes, dY]);
840 };
841 NodeJSKernelBackend.prototype.fusedDepthwiseConv2D = function (_a) {
842 var input = _a.input, filter = _a.filter, convInfo = _a.convInfo, bias = _a.bias, activation = _a.activation, preluActivationWeights = _a.preluActivationWeights;
843 var result = this.depthwiseConv2D(input, filter, convInfo);
844 if (bias != null) {
845 result = this.add(result, bias);
846 }
847 result = this.applyActivation(result, activation, preluActivationWeights);
848 return result;
849 };
850 NodeJSKernelBackend.prototype.depthwiseConv2D = function (input, filter, convInfo) {
851 if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') {
852 throw new Error("TF Backend supports only 'valid' and 'same' padding " +
853 ("while padding was " + convInfo.padInfo.type));
854 }
855 var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1];
856 var padding = convInfo.padInfo.type;
857 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW';
858 var dilations = [1, convInfo.dilationHeight, convInfo.dilationWidth, 1];
859 var opAttrs = [
860 createTensorsTypeOpAttr('T', input.dtype),
861 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
862 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, {
863 name: 'data_format',
864 type: this.binding.TF_ATTR_STRING,
865 value: dataFormat
866 },
867 { name: 'dilations', type: this.binding.TF_ATTR_INT, value: dilations }
868 ];
869 return this.executeSingleOutput('DepthwiseConv2dNative', opAttrs, [input, filter]);
870 };
871 NodeJSKernelBackend.prototype.conv3d = function (x, filter, convInfo) {
872 var strides = [
873 1, convInfo.strideDepth, convInfo.strideHeight, convInfo.strideWidth, 1
874 ];
875 var padding = convInfo.padInfo.type;
876 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NDHWC' : 'NCDHW';
877 if (!this.isGPUPackage && convInfo.dilationDepth > 1) {
878 throw new Error('CPU Dilation depth must be 1');
879 }
880 var dilations = [
881 1, convInfo.dilationDepth, convInfo.dilationHeight,
882 convInfo.dilationWidth, 1
883 ];
884 var opAttrs = [
885 createTensorsTypeOpAttr('T', x.dtype),
886 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
887 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, {
888 name: 'data_format',
889 type: this.binding.TF_ATTR_STRING,
890 value: dataFormat
891 },
892 { name: 'dilations', type: this.binding.TF_ATTR_INT, value: dilations }
893 ];
894 return this.executeSingleOutput('Conv3D', opAttrs, [x, filter]);
895 };
896 NodeJSKernelBackend.prototype.conv3dDerInput = function (dy, filter, convInfo) {
897 var strides = [
898 1, convInfo.strideDepth, convInfo.strideHeight, convInfo.strideWidth, 1
899 ];
900 var padding = convInfo.padInfo.type;
901 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NDHWC' : 'NCDHW';
902 if (!this.isGPUPackage && convInfo.dilationDepth > 1) {
903 throw new Error('CPU Dilation depth must be 1');
904 }
905 var dilations = [
906 1, convInfo.dilationDepth, convInfo.dilationHeight,
907 convInfo.dilationWidth, 1
908 ];
909 var opAttrs = [
910 createTensorsTypeOpAttr('T', dy.dtype),
911 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
912 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, {
913 name: 'data_format',
914 type: this.binding.TF_ATTR_STRING,
915 value: dataFormat
916 },
917 { name: 'dilations', type: this.binding.TF_ATTR_INT, value: dilations },
918 createTensorsTypeOpAttr('Tshape', 'int32')
919 ];
920 var inputSizes = tfjs_1.tensor1d(convInfo.inShape, 'int32');
921 return this.executeSingleOutput('Conv3DBackpropInputV2', opAttrs, [inputSizes, filter, dy]);
922 };
923 NodeJSKernelBackend.prototype.conv3dDerFilter = function (x, dY, convInfo) {
924 var strides = [
925 1, convInfo.strideDepth, convInfo.strideHeight, convInfo.strideWidth, 1
926 ];
927 var padding = convInfo.padInfo.type;
928 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NDHWC' : 'NCDHW';
929 if (!this.isGPUPackage && convInfo.dilationDepth > 1) {
930 throw new Error('CPU Dilation depth must be 1');
931 }
932 var dilations = [
933 1, convInfo.dilationDepth, convInfo.dilationHeight,
934 convInfo.dilationWidth, 1
935 ];
936 var opAttrs = [
937 createTensorsTypeOpAttr('T', x.dtype),
938 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
939 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, {
940 name: 'data_format',
941 type: this.binding.TF_ATTR_STRING,
942 value: dataFormat
943 },
944 { name: 'dilations', type: this.binding.TF_ATTR_INT, value: dilations }
945 ];
946 var filterSizes = tfjs_1.tensor1d(convInfo.filterShape, 'int32');
947 return this.executeSingleOutput('Conv3DBackpropFilterV2', opAttrs, [x, filterSizes, dY]);
948 };
949 NodeJSKernelBackend.prototype.maxPool = function (x, convInfo) {
950 if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') {
951 throw new Error("TF Backend supports only 'valid' and 'same' padding " +
952 ("while padding was " + convInfo.padInfo.type));
953 }
954 var ksize = [1, convInfo.filterHeight, convInfo.filterWidth, 1];
955 var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1];
956 var padding = convInfo.padInfo.type;
957 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW';
958 var opAttrs = [
959 createTensorsTypeOpAttr('T', x.dtype),
960 { name: 'ksize', type: this.binding.TF_ATTR_INT, value: ksize },
961 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
962 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, {
963 name: 'data_format',
964 type: this.binding.TF_ATTR_STRING,
965 value: dataFormat
966 }
967 ];
968 return this.executeSingleOutput('MaxPool', opAttrs, [x]);
969 };
970 NodeJSKernelBackend.prototype.maxPoolBackprop = function (dy, x, y, convInfo) {
971 if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') {
972 throw new Error("TF Backend supports only 'valid' and 'same' padding " +
973 ("while padding type was " + convInfo.padInfo.type));
974 }
975 var ksize = [1, convInfo.filterHeight, convInfo.filterWidth, 1];
976 var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1];
977 var padding = convInfo.padInfo.type;
978 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW';
979 var opAttrs = [
980 createTensorsTypeOpAttr('T', x.dtype),
981 { name: 'ksize', type: this.binding.TF_ATTR_INT, value: ksize },
982 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
983 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding },
984 {
985 name: 'data_format',
986 type: this.binding.TF_ATTR_STRING,
987 value: dataFormat
988 },
989 ];
990 return this.executeSingleOutput('MaxPoolGrad', opAttrs, [x, y, dy]);
991 };
992 NodeJSKernelBackend.prototype.avgPool = function (x, convInfo) {
993 if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') {
994 throw new Error("TF Backend supports only 'valid' and 'same' padding " +
995 ("while padding was " + convInfo.padInfo.type));
996 }
997 var ksize = [1, convInfo.filterHeight, convInfo.filterWidth, 1];
998 var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1];
999 var padding = convInfo.padInfo.type;
1000 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW';
1001 var opAttrs = [
1002 createTensorsTypeOpAttr('T', x.dtype),
1003 { name: 'ksize', type: this.binding.TF_ATTR_INT, value: ksize },
1004 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
1005 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding },
1006 {
1007 name: 'data_format',
1008 type: this.binding.TF_ATTR_STRING,
1009 value: dataFormat
1010 },
1011 ];
1012 return this.executeSingleOutput('AvgPool', opAttrs, [x]);
1013 };
1014 NodeJSKernelBackend.prototype.avgPoolBackprop = function (dy, x, convInfo) {
1015 if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') {
1016 throw new Error("TF Backend supports only 'valid' and 'same' padding " +
1017 ("while padding type was " + convInfo.padInfo.type));
1018 }
1019 var ksize = [1, convInfo.filterHeight, convInfo.filterWidth, 1];
1020 var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1];
1021 var padding = convInfo.padInfo.type;
1022 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW';
1023 var opAttrs = [
1024 createTensorsTypeOpAttr('T', x.dtype),
1025 { name: 'ksize', type: this.binding.TF_ATTR_INT, value: ksize },
1026 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
1027 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding },
1028 {
1029 name: 'data_format',
1030 type: this.binding.TF_ATTR_STRING,
1031 value: dataFormat
1032 },
1033 ];
1034 var origInputShape = tfjs_1.tensor1d(x.shape, 'int32');
1035 return this.executeSingleOutput('AvgPoolGrad', opAttrs, [origInputShape, dy]);
1036 };
1037 NodeJSKernelBackend.prototype.avgPool3d = function (x, convInfo) {
1038 if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') {
1039 throw new Error("TF Backend supports only 'valid' and 'same' padding " +
1040 ("while padding was " + convInfo.padInfo.type));
1041 }
1042 var ksize = [
1043 1, convInfo.filterDepth, convInfo.filterHeight, convInfo.filterWidth, 1
1044 ];
1045 var strides = [
1046 1, convInfo.strideDepth, convInfo.strideHeight, convInfo.strideWidth, 1
1047 ];
1048 var padding = convInfo.padInfo.type;
1049 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NDHWC' : 'NCDHW';
1050 var opAttrs = [
1051 createTensorsTypeOpAttr('T', x.dtype),
1052 { name: 'ksize', type: this.binding.TF_ATTR_INT, value: ksize },
1053 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
1054 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding },
1055 {
1056 name: 'data_format',
1057 type: this.binding.TF_ATTR_STRING,
1058 value: dataFormat
1059 },
1060 ];
1061 return this.executeSingleOutput('AvgPool3D', opAttrs, [x]);
1062 };
1063 NodeJSKernelBackend.prototype.avgPool3dBackprop = function (dy, x, convInfo) {
1064 if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') {
1065 throw new Error("TF Backend supports only 'valid' and 'same' padding " +
1066 ("while padding type was " + convInfo.padInfo.type));
1067 }
1068 var ksize = [
1069 1, convInfo.filterDepth, convInfo.filterHeight, convInfo.filterWidth, 1
1070 ];
1071 var strides = [
1072 1, convInfo.strideDepth, convInfo.strideHeight, convInfo.strideWidth, 1
1073 ];
1074 var padding = convInfo.padInfo.type;
1075 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NDHWC' : 'NCDHW';
1076 var opAttrs = [
1077 createTensorsTypeOpAttr('T', x.dtype),
1078 { name: 'ksize', type: this.binding.TF_ATTR_INT, value: ksize },
1079 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
1080 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding },
1081 {
1082 name: 'data_format',
1083 type: this.binding.TF_ATTR_STRING,
1084 value: dataFormat
1085 },
1086 ];
1087 var origInputShape = tfjs_1.tensor1d(x.shape, 'int32');
1088 return this.executeSingleOutput('AvgPool3DGrad', opAttrs, [origInputShape, dy]);
1089 };
1090 NodeJSKernelBackend.prototype.maxPool3d = function (x, convInfo) {
1091 if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') {
1092 throw new Error("TF Backend supports only 'valid' and 'same' padding " +
1093 ("while padding was " + convInfo.padInfo.type));
1094 }
1095 var ksize = [
1096 1, convInfo.filterDepth, convInfo.filterHeight, convInfo.filterWidth, 1
1097 ];
1098 var strides = [
1099 1, convInfo.strideDepth, convInfo.strideHeight, convInfo.strideWidth, 1
1100 ];
1101 var padding = convInfo.padInfo.type;
1102 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NDHWC' : 'NCDHW';
1103 var opAttrs = [
1104 createTensorsTypeOpAttr('T', x.dtype),
1105 { name: 'ksize', type: this.binding.TF_ATTR_INT, value: ksize },
1106 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
1107 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, {
1108 name: 'data_format',
1109 type: this.binding.TF_ATTR_STRING,
1110 value: dataFormat
1111 }
1112 ];
1113 return this.executeSingleOutput('MaxPool3D', opAttrs, [x]);
1114 };
1115 NodeJSKernelBackend.prototype.maxPool3dBackprop = function (dy, x, y, convInfo) {
1116 if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') {
1117 throw new Error("TF Backend supports only 'valid' and 'same' padding " +
1118 ("while padding type was " + convInfo.padInfo.type));
1119 }
1120 var ksize = [
1121 1, convInfo.filterDepth, convInfo.filterHeight, convInfo.filterWidth, 1
1122 ];
1123 var strides = [
1124 1, convInfo.strideDepth, convInfo.strideHeight, convInfo.strideWidth, 1
1125 ];
1126 var padding = convInfo.padInfo.type;
1127 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NDHWC' : 'NCDHW';
1128 var opAttrs = [
1129 createTensorsTypeOpAttr('T', x.dtype),
1130 { name: 'ksize', type: this.binding.TF_ATTR_INT, value: ksize },
1131 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
1132 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding },
1133 {
1134 name: 'data_format',
1135 type: this.binding.TF_ATTR_STRING,
1136 value: dataFormat
1137 },
1138 ];
1139 return this.executeSingleOutput('MaxPool3DGrad', opAttrs, [x, y, dy]);
1140 };
1141 NodeJSKernelBackend.prototype.reshape = function (x, shape) {
1142 var shapeTensor = tfjs_1.tensor1d(shape, 'int32');
1143 var opAttrs = [
1144 createTensorsTypeOpAttr('T', x.dtype),
1145 createTensorsTypeOpAttr('Tshape', shapeTensor.dtype)
1146 ];
1147 return this.executeSingleOutput('Reshape', opAttrs, [x, shapeTensor]);
1148 };
1149 NodeJSKernelBackend.prototype.cast = function (x, dtype) {
1150 var opAttrs = [
1151 createTensorsTypeOpAttr('SrcT', x.dtype),
1152 createTensorsTypeOpAttr('DstT', dtype),
1153 { name: 'Truncate', type: this.binding.TF_ATTR_BOOL, value: false }
1154 ];
1155 return this.executeSingleOutput('Cast', opAttrs, [x]);
1156 };
1157 NodeJSKernelBackend.prototype.tile = function (x, reps) {
1158 var opAttrs = [
1159 createTensorsTypeOpAttr('T', x.dtype),
1160 createTensorsTypeOpAttr('Tmultiples', 'int32')
1161 ];
1162 var multiples = tfjs_1.tensor1d(reps, 'int32');
1163 return this.executeSingleOutput('Tile', opAttrs, [x, multiples]);
1164 };
1165 NodeJSKernelBackend.prototype.pad = function (x, paddings, constantValue) {
1166 // Bind tensor values
1167 var paddingsTensor = tfjs_1.tensor2d(paddings, [paddings.length, 2], 'int32');
1168 var constantTensor = tfjs_1.scalar(constantValue, x.dtype);
1169 var opAttrs = [
1170 createTensorsTypeOpAttr('T', x.dtype),
1171 createTensorsTypeOpAttr('Tpaddings', paddingsTensor.dtype)
1172 ];
1173 return this.executeSingleOutput('PadV2', opAttrs, [x, paddingsTensor, constantTensor]);
1174 };
1175 NodeJSKernelBackend.prototype.transpose = function (x, perm) {
1176 var permTensor = tfjs_1.tensor1d(perm, 'int32');
1177 var opAttrs = [
1178 createTensorsTypeOpAttr('T', x.dtype),
1179 createTensorsTypeOpAttr('Tperm', 'int32')
1180 ];
1181 return this.executeSingleOutput('Transpose', opAttrs, [x, permTensor]);
1182 };
1183 NodeJSKernelBackend.prototype.gather = function (x, indices, axis) {
1184 var axisTensor = tfjs_1.scalar(axis, 'int32');
1185 var opAttrs = [
1186 createTensorsTypeOpAttr('Tparams', x.dtype),
1187 createTensorsTypeOpAttr('Tindices', indices.dtype),
1188 createTensorsTypeOpAttr('Taxis', 'int32')
1189 ];
1190 return this.executeSingleOutput('GatherV2', opAttrs, [x, indices, axisTensor]);
1191 };
1192 NodeJSKernelBackend.prototype.gatherND = function (x, indices) {
1193 var opAttrs = [
1194 createTensorsTypeOpAttr('Tparams', x.dtype),
1195 createTensorsTypeOpAttr('Tindices', 'int32')
1196 ];
1197 return this.executeSingleOutput('GatherNd', opAttrs, [x, indices]);
1198 };
1199 NodeJSKernelBackend.prototype.scatterND = function (indices, updates, shape) {
1200 var opAttrs = [
1201 createTensorsTypeOpAttr('T', updates.dtype),
1202 createTensorsTypeOpAttr('Tindices', 'int32')
1203 ];
1204 var shapeTensor = tfjs_1.tensor1d(shape, 'int32');
1205 return this.executeSingleOutput('ScatterNd', opAttrs, [indices, updates, shapeTensor]);
1206 };
1207 NodeJSKernelBackend.prototype.batchToSpaceND = function (x, blockShape, crops) {
1208 var blockShapeTensor = tfjs_1.tensor1d(blockShape, 'int32');
1209 var cropsTensor = tfjs_1.tensor2d(crops, [crops.length, crops[0].length], 'int32');
1210 var opAttrs = [
1211 createTensorsTypeOpAttr('T', x.dtype),
1212 createTensorsTypeOpAttr('Tblock_shape', 'int32'),
1213 createTensorsTypeOpAttr('Tcrops', cropsTensor.dtype)
1214 ];
1215 return this.executeSingleOutput('BatchToSpaceND', opAttrs, [x, blockShapeTensor, cropsTensor]);
1216 };
1217 NodeJSKernelBackend.prototype.spaceToBatchND = function (x, blockShape, paddings) {
1218 var blockShapeTensor = tfjs_1.tensor1d(blockShape, 'int32');
1219 var paddingsTensor = tfjs_1.tensor2d(paddings, [paddings.length, paddings[0].length], 'int32');
1220 var opAttrs = [
1221 createTensorsTypeOpAttr('T', x.dtype),
1222 createTensorsTypeOpAttr('Tblock_shape', 'int32'),
1223 createTensorsTypeOpAttr('Tpaddings', paddingsTensor.dtype)
1224 ];
1225 return this.executeSingleOutput('SpaceToBatchND', opAttrs, [x, blockShapeTensor, paddingsTensor]);
1226 };
1227 NodeJSKernelBackend.prototype.resizeBilinear = function (x, newHeight, newWidth, alignCorners) {
1228 var opAttrs = [
1229 createTensorsTypeOpAttr('T', x.dtype),
1230 {
1231 name: 'align_corners',
1232 type: this.binding.TF_ATTR_BOOL,
1233 value: alignCorners
1234 },
1235 ];
1236 var size = tfjs_1.tensor1d([newHeight, newWidth], 'int32');
1237 return this.executeSingleOutput('ResizeBilinear', opAttrs, [x, size]);
1238 };
1239 NodeJSKernelBackend.prototype.resizeBilinearBackprop = function (dy, x, alignCorners) {
1240 var opAttrs = [
1241 createTensorsTypeOpAttr('T', x.dtype), {
1242 name: 'align_corners',
1243 type: this.binding.TF_ATTR_BOOL,
1244 value: alignCorners
1245 }
1246 ];
1247 return this.executeSingleOutput('ResizeBilinearGrad', opAttrs, [dy, x]);
1248 };
1249 NodeJSKernelBackend.prototype.resizeNearestNeighbor = function (x, newHeight, newWidth, alignCorners) {
1250 var opAttrs = [
1251 createTensorsTypeOpAttr('T', x.dtype),
1252 {
1253 name: 'align_corners',
1254 type: this.binding.TF_ATTR_BOOL,
1255 value: alignCorners
1256 },
1257 ];
1258 var size = tfjs_1.tensor1d([newHeight, newWidth], 'int32');
1259 return this.executeSingleOutput('ResizeNearestNeighbor', opAttrs, [x, size]);
1260 };
1261 NodeJSKernelBackend.prototype.resizeNearestNeighborBackprop = function (dy, x, alignCorners) {
1262 var opAttrs = [
1263 createTensorsTypeOpAttr('T', x.dtype), {
1264 name: 'align_corners',
1265 type: this.binding.TF_ATTR_BOOL,
1266 value: alignCorners
1267 }
1268 ];
1269 var _a = x.shape, origHeight = _a[1], origWidth = _a[2];
1270 var size = tfjs_1.tensor1d([origHeight, origWidth], 'int32');
1271 return this.executeSingleOutput('ResizeNearestNeighborGrad', opAttrs, [dy, size]);
1272 };
1273 NodeJSKernelBackend.prototype.batchNorm = function (x, mean, variance, offset, scale, varianceEpsilon) {
1274 if (mean.rank > 1) {
1275 // Fused batch norm doesn't work with high-dim mean/var/scale/offset.
1276 var inv = tfjs_1.rsqrt(variance.add(tfjs_1.scalar(varianceEpsilon)));
1277 if (scale != null) {
1278 inv = inv.mul(scale);
1279 }
1280 var xNorm = x.sub(mean).mul(inv);
1281 return offset != null ? xNorm.add(offset) : xNorm;
1282 }
1283 var dataFormat = 'NHWC';
1284 var depth = x.shape[3];
1285 var opAttrs = [
1286 createTensorsTypeOpAttr('T', x.dtype),
1287 {
1288 name: 'epsilon',
1289 type: this.binding.TF_ATTR_FLOAT,
1290 value: varianceEpsilon
1291 },
1292 {
1293 name: 'data_format',
1294 type: this.binding.TF_ATTR_STRING,
1295 value: dataFormat
1296 },
1297 { name: 'is_training', type: this.binding.TF_ATTR_BOOL, value: false },
1298 ];
1299 var numOutputs = 5;
1300 if (scale == null) {
1301 scale = tfjs_1.fill([depth], 1);
1302 }
1303 if (offset == null) {
1304 offset = tfjs_1.fill([depth], 0);
1305 }
1306 return this.executeMultipleOutputs('FusedBatchNorm', opAttrs, [x, scale, offset, mean, variance], numOutputs)[0];
1307 };
1308 NodeJSKernelBackend.prototype.localResponseNormalization4D = function (x, radius, bias, alpha, beta) {
1309 var opAttrs = [
1310 createTensorsTypeOpAttr('T', x.dtype),
1311 { name: 'depth_radius', type: this.binding.TF_ATTR_INT, value: radius },
1312 { name: 'bias', type: this.binding.TF_ATTR_FLOAT, value: bias },
1313 { name: 'alpha', type: this.binding.TF_ATTR_FLOAT, value: alpha },
1314 { name: 'beta', type: this.binding.TF_ATTR_FLOAT, value: beta },
1315 ];
1316 return this.executeSingleOutput('LRN', opAttrs, [x]);
1317 };
1318 NodeJSKernelBackend.prototype.LRNGrad = function (dy, inputImage, outputImage, radius, bias, alpha, beta) {
1319 var opAttrs = [
1320 createTensorsTypeOpAttr('T', dy.dtype),
1321 { name: 'depth_radius', type: this.binding.TF_ATTR_INT, value: radius },
1322 { name: 'bias', type: this.binding.TF_ATTR_FLOAT, value: bias },
1323 { name: 'alpha', type: this.binding.TF_ATTR_FLOAT, value: alpha },
1324 { name: 'beta', type: this.binding.TF_ATTR_FLOAT, value: beta },
1325 ];
1326 return this.executeSingleOutput('LRNGrad', opAttrs, [dy, inputImage, outputImage]);
1327 };
1328 NodeJSKernelBackend.prototype.multinomial = function (logits, normalized, numSamples, seed) {
1329 if (normalized) {
1330 throw new Error('TF Node backend does not support normalized logits ' +
1331 'passed to multinomial');
1332 }
1333 var opAttrs = [
1334 createTensorsTypeOpAttr('T', logits.dtype),
1335 createTensorsTypeOpAttr('output_dtype', 'int32'),
1336 { name: 'seed', type: this.binding.TF_ATTR_INT, value: seed },
1337 { name: 'seed2', type: this.binding.TF_ATTR_INT, value: seed * seed },
1338 ];
1339 return this.executeSingleOutput('Multinomial', opAttrs, [logits, tfjs_1.scalar(numSamples, 'int32')]);
1340 };
1341 NodeJSKernelBackend.prototype.oneHot = function (indices, depth, onValue, offValue) {
1342 var depthTensor = tfjs_1.scalar(depth, 'int32');
1343 var onValueTensor = tfjs_1.scalar(onValue, 'int32');
1344 var offValueTensor = tfjs_1.scalar(offValue, 'int32');
1345 var opAttrs = [
1346 { name: 'axis', type: this.binding.TF_ATTR_INT, value: -1 },
1347 createTensorsTypeOpAttr('T', indices.dtype),
1348 createTensorsTypeOpAttr('TI', indices.dtype)
1349 ];
1350 return this.executeSingleOutput('OneHot', opAttrs, [
1351 indices, depthTensor, onValueTensor, offValueTensor
1352 ]);
1353 };
1354 NodeJSKernelBackend.prototype.cumsum = function (x, axis, exclusive, reverse) {
1355 var axisTensor = tfjs_1.scalar(axis, 'int32');
1356 var opAttrs = [
1357 { name: 'exclusive', type: this.binding.TF_ATTR_BOOL, value: exclusive },
1358 { name: 'reverse', type: this.binding.TF_ATTR_BOOL, value: reverse },
1359 createTensorsTypeOpAttr('T', x.dtype),
1360 createTensorsTypeOpAttr('Tidx', 'int32')
1361 ];
1362 return this.executeSingleOutput('Cumsum', opAttrs, [x, axisTensor]);
1363 };
1364 NodeJSKernelBackend.prototype.nonMaxSuppression = function (boxes, scores, maxOutputSize, iouThreshold, scoreThreshold) {
1365 var opAttrs = [createTensorsTypeOpAttr('T', boxes.dtype)];
1366 var maxOutputSizeTensor = tfjs_1.scalar(maxOutputSize, 'int32');
1367 var iouThresholdTensor = tfjs_1.scalar(iouThreshold);
1368 var scoreThresholdTensor = tfjs_1.scalar(scoreThreshold);
1369 return this.executeSingleOutput('NonMaxSuppressionV3', opAttrs, [
1370 boxes, scores, maxOutputSizeTensor, iouThresholdTensor,
1371 scoreThresholdTensor
1372 ]);
1373 };
1374 NodeJSKernelBackend.prototype.fft = function (x) {
1375 var opAttrs = [createTensorsTypeOpAttr('Tcomplex', x.dtype)];
1376 return this.executeSingleOutput('FFT', opAttrs, [x]);
1377 };
1378 NodeJSKernelBackend.prototype.ifft = function (x) {
1379 var opAttrs = [createTensorsTypeOpAttr('Tcomplex', x.dtype)];
1380 return this.executeSingleOutput('IFFT', opAttrs, [x]);
1381 };
1382 NodeJSKernelBackend.prototype.complex = function (real, imag) {
1383 var opAttrs = [
1384 createTensorsTypeOpAttr('T', real),
1385 {
1386 name: 'Tout',
1387 type: this.binding.TF_ATTR_TYPE,
1388 value: this.binding.TF_COMPLEX64
1389 },
1390 ];
1391 var inputs = [real, imag];
1392 return this.executeSingleOutput('Complex', opAttrs, inputs);
1393 };
1394 NodeJSKernelBackend.prototype.real = function (input) {
1395 var opAttrs = [
1396 createTensorsTypeOpAttr('T', input), {
1397 name: 'Tout',
1398 type: this.binding.TF_ATTR_TYPE,
1399 value: this.binding.TF_FLOAT
1400 }
1401 ];
1402 var inputs = [input];
1403 return this.executeSingleOutput('Real', opAttrs, inputs);
1404 };
1405 NodeJSKernelBackend.prototype.imag = function (input) {
1406 var opAttrs = [
1407 {
1408 name: 'T',
1409 type: this.binding.TF_ATTR_TYPE,
1410 value: this.binding.TF_COMPLEX64
1411 },
1412 {
1413 name: 'Tout',
1414 type: this.binding.TF_ATTR_TYPE,
1415 value: this.binding.TF_FLOAT
1416 }
1417 ];
1418 var inputs = [input];
1419 return this.executeSingleOutput('Imag', opAttrs, inputs);
1420 };
1421 NodeJSKernelBackend.prototype.cropAndResize = function (image, boxes, boxIndex, cropSize, method, extrapolationValue) {
1422 var opAttrs = [
1423 createTensorsTypeOpAttr('T', image.dtype),
1424 { name: 'method', type: this.binding.TF_ATTR_STRING, value: method }, {
1425 name: 'extrapolation_value',
1426 type: this.binding.TF_ATTR_FLOAT,
1427 value: extrapolationValue
1428 }
1429 ];
1430 var cropSizeTensor = tfjs_1.tensor1d(cropSize, 'int32');
1431 return this.executeSingleOutput('CropAndResize', opAttrs, [image, boxes, boxIndex, cropSizeTensor]);
1432 };
1433 NodeJSKernelBackend.prototype.depthToSpace = function (x, blockSize, dataFormat) {
1434 var opAttrs = [
1435 createTensorsTypeOpAttr('T', x), {
1436 name: 'block_size',
1437 type: this.binding.TF_ATTR_INT,
1438 value: blockSize < 2 ? 2 : blockSize
1439 },
1440 {
1441 name: 'data_format',
1442 type: this.binding.TF_ATTR_STRING,
1443 value: dataFormat
1444 }
1445 ];
1446 var inputs = [x];
1447 return this.executeSingleOutput('DepthToSpace', opAttrs, inputs);
1448 };
1449 NodeJSKernelBackend.prototype.split = function (value, sizeSplits, axis) {
1450 var opAttrs = [
1451 {
1452 name: 'num_split',
1453 type: this.binding.TF_ATTR_INT,
1454 value: sizeSplits.length
1455 },
1456 createTensorsTypeOpAttr('T', value), {
1457 name: 'Tlen',
1458 type: this.binding.TF_ATTR_TYPE,
1459 value: this.binding.TF_INT32
1460 }
1461 ];
1462 var inputs = [value];
1463 inputs.push(tfjs_1.tensor1d(sizeSplits, 'int32'));
1464 inputs.push(tfjs_1.scalar(axis, 'int32'));
1465 return this.executeMultipleOutputs('SplitV', opAttrs, inputs, sizeSplits.length);
1466 };
1467 NodeJSKernelBackend.prototype.sparseToDense = function (sparseIndices, sparseValues, outputShape, defaultValue) {
1468 var opAttrs = [
1469 { name: 'validate_indices', type: this.binding.TF_ATTR_BOOL, value: true },
1470 createTensorsTypeOpAttr('T', sparseValues.dtype),
1471 createTensorsTypeOpAttr('Tindices', sparseIndices.dtype)
1472 ];
1473 var outputShapeTensor = tfjs_1.tensor1d(outputShape, 'int32');
1474 return this.executeSingleOutput('SparseToDense', opAttrs, [
1475 sparseIndices, outputShapeTensor, sparseValues, defaultValue
1476 ]);
1477 };
1478 NodeJSKernelBackend.prototype.linspace = function (start, stop, num) {
1479 var opAttrs = [
1480 createTensorsTypeOpAttr('T', 'float32'),
1481 createTensorsTypeOpAttr('Tidx', 'int32')
1482 ];
1483 var inputs = [
1484 tfjs_1.scalar(start, 'float32'), tfjs_1.scalar(stop, 'float32'), tfjs_1.scalar(num, 'int32')
1485 ];
1486 return this.executeSingleOutput('LinSpace', opAttrs, inputs);
1487 };
1488 NodeJSKernelBackend.prototype.decodeJpeg = function (contents, channels, ratio, fancyUpscaling, tryRecoverTruncated, acceptableFraction, dctMethod) {
1489 var opAttrs = [
1490 { name: 'channels', type: this.binding.TF_ATTR_INT, value: channels },
1491 { name: 'ratio', type: this.binding.TF_ATTR_INT, value: ratio }, {
1492 name: 'fancy_upscaling',
1493 type: this.binding.TF_ATTR_BOOL,
1494 value: fancyUpscaling
1495 },
1496 {
1497 name: 'try_recover_truncated',
1498 type: this.binding.TF_ATTR_BOOL,
1499 value: tryRecoverTruncated
1500 },
1501 {
1502 name: 'acceptable_fraction',
1503 type: this.binding.TF_ATTR_FLOAT,
1504 value: acceptableFraction
1505 },
1506 { name: 'dct_method', type: this.binding.TF_ATTR_STRING, value: dctMethod }
1507 ];
1508 var inputArgs = [tfjs_1.scalar(contents, 'string')];
1509 return this.executeSingleOutput('DecodeJpeg', opAttrs, inputArgs);
1510 };
1511 NodeJSKernelBackend.prototype.decodePng = function (contents, channels) {
1512 var opAttrs = [{ name: 'channels', type: this.binding.TF_ATTR_INT, value: channels }];
1513 var inputArgs = [tfjs_1.scalar(contents, 'string')];
1514 return this.executeSingleOutput('DecodePng', opAttrs, inputArgs);
1515 };
1516 NodeJSKernelBackend.prototype.decodeBmp = function (contents, channels) {
1517 var opAttrs = [{ name: 'channels', type: this.binding.TF_ATTR_INT, value: channels }];
1518 var inputArgs = [tfjs_1.scalar(contents, 'string')];
1519 return this.executeSingleOutput('DecodeBmp', opAttrs, inputArgs);
1520 };
1521 NodeJSKernelBackend.prototype.decodeGif = function (contents) {
1522 var inputArgs = [tfjs_1.scalar(contents, 'string')];
1523 return this.executeSingleOutput('DecodeGif', [], inputArgs);
1524 };
1525 NodeJSKernelBackend.prototype.executeEncodeImageOp = function (name, opAttrs, imageData, imageShape) {
1526 var inputTensorId = this.binding.createTensor(imageShape, this.binding.TF_UINT8, imageData);
1527 var outputMetadata = this.binding.executeOp(name, opAttrs, [inputTensorId], 1);
1528 var outputTensorInfo = outputMetadata[0];
1529 // prevent the tensor data from being converted to a UTF8 string, since
1530 // the encoded data is not valid UTF8
1531 outputTensorInfo.dtype = this.binding.TF_UINT8;
1532 return this.createOutputTensor(outputTensorInfo);
1533 };
1534 NodeJSKernelBackend.prototype.encodeJpeg = function (imageData, imageShape, format, quality, progressive, optimizeSize, chromaDownsampling, densityUnit, xDensity, yDensity, xmpMetadata) {
1535 var opAttrs = [
1536 { name: 'format', type: this.binding.TF_ATTR_STRING, value: format },
1537 { name: 'quality', type: this.binding.TF_ATTR_INT, value: quality }, {
1538 name: 'progressive',
1539 type: this.binding.TF_ATTR_BOOL,
1540 value: progressive
1541 },
1542 {
1543 name: 'optimize_size',
1544 type: this.binding.TF_ATTR_BOOL,
1545 value: optimizeSize
1546 },
1547 {
1548 name: 'chroma_downsampling',
1549 type: this.binding.TF_ATTR_BOOL,
1550 value: chromaDownsampling
1551 },
1552 {
1553 name: 'density_unit',
1554 type: this.binding.TF_ATTR_STRING,
1555 value: densityUnit
1556 },
1557 { name: 'x_density', type: this.binding.TF_ATTR_INT, value: xDensity },
1558 { name: 'y_density', type: this.binding.TF_ATTR_INT, value: yDensity }, {
1559 name: 'xmp_metadata',
1560 type: this.binding.TF_ATTR_STRING,
1561 value: xmpMetadata
1562 }
1563 ];
1564 return this.executeEncodeImageOp('EncodeJpeg', opAttrs, imageData, imageShape);
1565 };
1566 NodeJSKernelBackend.prototype.encodePng = function (imageData, imageShape, compression) {
1567 var opAttrs = [
1568 { name: 'compression', type: this.binding.TF_ATTR_INT, value: compression }
1569 ];
1570 return this.executeEncodeImageOp('EncodePng', opAttrs, imageData, imageShape);
1571 };
1572 NodeJSKernelBackend.prototype.deleteSavedModel = function (id) {
1573 this.binding.deleteSavedModel(id);
1574 };
1575 NodeJSKernelBackend.prototype.loadSavedModelMetaGraph = function (path, tags) {
1576 return this.binding.loadSavedModel(path, tags);
1577 };
1578 NodeJSKernelBackend.prototype.runSavedModel = function (id, inputs, inputOpNames, outputOpNames) {
1579 var _this = this;
1580 var outputMetadata = this.binding.runSavedModel(id, this.getInputTensorIds(inputs), inputOpNames.join(','), outputOpNames.join(','));
1581 return outputMetadata.map(function (m) { return _this.createOutputTensor(m); });
1582 };
1583 // ------------------------------------------------------------
1584 // TensorBoard-related (tfjs-node-specific) backend kernels.
1585 NodeJSKernelBackend.prototype.summaryWriter = function (logdir) {
1586 var opAttrs = [
1587 {
1588 name: 'shared_name',
1589 type: this.binding.TF_ATTR_STRING,
1590 value: "logdir:" + logdir
1591 },
1592 { name: 'container', type: this.binding.TF_ATTR_STRING, value: '' }
1593 ];
1594 var writerResource = this.executeSingleOutput('SummaryWriter', opAttrs, []);
1595 return writerResource;
1596 };
1597 NodeJSKernelBackend.prototype.createSummaryFileWriter = function (resourceHandle, logdir, maxQueue, flushMillis, filenameSuffix) {
1598 var inputArgs = [
1599 resourceHandle, tfjs_1.scalar(logdir),
1600 tfjs_1.scalar(maxQueue == null ? 10 : maxQueue, 'int32'),
1601 tfjs_1.scalar(flushMillis == null ? 2 * 60 * 1000 : flushMillis, 'int32'),
1602 tfjs_1.scalar(filenameSuffix == null ? '.v2' : filenameSuffix)
1603 ];
1604 this.executeMultipleOutputs('CreateSummaryFileWriter', [], inputArgs, 0);
1605 };
1606 NodeJSKernelBackend.prototype.writeScalarSummary = function (resourceHandle, step, name, value) {
1607 var _this = this;
1608 tfjs_1.tidy(function () {
1609 tfjs_1.util.assert(Number.isInteger(step), function () { return "step is expected to be an integer, but is instead " + step; });
1610 var inputArgs = [resourceHandle, new int64_tensors_1.Int64Scalar(step), tfjs_1.scalar(name, 'string')];
1611 var typeAttr;
1612 if (typeof value === 'number') {
1613 inputArgs.push(tfjs_1.scalar(value));
1614 typeAttr = _this.binding.TF_FLOAT;
1615 }
1616 else {
1617 // `value` is a Scalar.
1618 tfjs_1.util.assert(value.rank === 0, function () { return "A non-scalar tensor (rank " + value.rank + ") is passed to " +
1619 "writeScalarSummary()"; });
1620 inputArgs.push(value);
1621 typeAttr = _this.typeAttributeFromTensor(value);
1622 }
1623 var opAttrs = [{ name: 'T', type: _this.binding.TF_ATTR_TYPE, value: typeAttr }];
1624 _this.binding.executeOp('WriteScalarSummary', opAttrs, _this.getInputTensorIds(inputArgs), 0);
1625 });
1626 };
1627 NodeJSKernelBackend.prototype.flushSummaryWriter = function (resourceHandle) {
1628 var inputArgs = [resourceHandle];
1629 this.executeMultipleOutputs('FlushSummaryWriter', [], inputArgs, 0);
1630 };
1631 // ~ TensorBoard-related (tfjs-node-specific) backend kernels.
1632 // ------------------------------------------------------------
1633 NodeJSKernelBackend.prototype.memory = function () {
1634 // Due to automatic garbage collection, the numbers are unreliable.
1635 // TODO(kreeger): Since there is finalization in C, count the true
1636 // number of undisposed tensors.
1637 return { unreliable: true };
1638 };
1639 NodeJSKernelBackend.prototype.time = function (f) {
1640 return __awaiter(this, void 0, void 0, function () {
1641 var start, elapsed;
1642 return __generator(this, function (_a) {
1643 start = process.hrtime();
1644 f();
1645 elapsed = process.hrtime(start);
1646 return [2 /*return*/, { kernelMs: elapsed[0] * 1000 + elapsed[1] / 1000000 }];
1647 });
1648 });
1649 };
1650 NodeJSKernelBackend.prototype.getNumOfSavedModels = function () {
1651 return this.binding.getNumOfSavedModels();
1652 };
1653 return NodeJSKernelBackend;
1654}(tfjs_1.KernelBackend));
1655exports.NodeJSKernelBackend = NodeJSKernelBackend;
1656/** Returns an instance of the Node.js backend. */
1657function nodeBackend() {
1658 return tf.findBackend('tensorflow');
1659}
1660exports.nodeBackend = nodeBackend;
1661/** Returns the TF dtype for a given DataType. */
1662function getTFDType(dataType) {
1663 var binding = nodeBackend().binding;
1664 switch (dataType) {
1665 case 'float32':
1666 return binding.TF_FLOAT;
1667 case 'int32':
1668 return binding.TF_INT32;
1669 case 'bool':
1670 return binding.TF_BOOL;
1671 case 'complex64':
1672 return binding.TF_COMPLEX64;
1673 case 'string':
1674 return binding.TF_STRING;
1675 // tslint:disable-next-line:no-any
1676 case 'int64':
1677 // int64 is not a generally supported dtype in TensorFlow.js
1678 // (tfjs-core). However, it needs to be included here for the purpose of
1679 // writing the `step` value to TensorBoard via WriteScalarSummary and
1680 // other op kernels.
1681 return binding.TF_INT64;
1682 default:
1683 var errorMessage = "Unknown dtype: " + dataType;
1684 throw new Error(errorMessage);
1685 }
1686}
1687exports.getTFDType = getTFDType;
1688/**
1689 * Creates a TFEOpAttr for a 'type' OpDef attribute from a Tensor or list of
1690 * Tensors.
1691 */
1692function createTensorsTypeOpAttr(attrName, tensorsOrDtype) {
1693 if (util_1.isNullOrUndefined(tensorsOrDtype)) {
1694 throw new Error('Invalid input tensors value.');
1695 }
1696 return {
1697 name: attrName,
1698 type: nodeBackend().binding.TF_ATTR_TYPE,
1699 value: (tensorsOrDtype instanceof tf.Tensor || Array.isArray(tensorsOrDtype)) ?
1700 getTFDTypeForInputs(tensorsOrDtype) :
1701 getTFDType(tensorsOrDtype)
1702 };
1703}
1704exports.createTensorsTypeOpAttr = createTensorsTypeOpAttr;
1705/** Returns the dtype number for a single or list of input Tensors. */
1706function getTFDTypeForInputs(tensors) {
1707 if (util_1.isNullOrUndefined(tensors)) {
1708 throw new Error('Invalid input tensors value.');
1709 }
1710 if (util_1.isArray(tensors)) {
1711 for (var i = 0; i < tensors.length; i++) {
1712 return getTFDType(tensors[i].dtype);
1713 }
1714 return -1;
1715 }
1716 else {
1717 return getTFDType(tensors.dtype);
1718 }
1719}
1720function ensureTensorflowBackend() {
1721 tf.util.assert(tf.getBackend() === 'tensorflow', function () { return "Expect the current backend to be \"tensorflow\", but got \"" + tf.getBackend() + "\""; });
1722}
1723exports.ensureTensorflowBackend = ensureTensorflowBackend;