UNPKG

82.9 kBJavaScriptView Raw
1"use strict";
2/**
3 * @license
4 * Copyright 2018 Google LLC. 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, x.dtype));
637 return this.maximum(xMin, tfjs_1.scalar(min, x.dtype));
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 convInfo.padInfo.type !== 'EXPLICIT') {
739 throw new Error("TF Backend supports only 'valid' and 'same' padding " +
740 ("while padding was " + convInfo.padInfo.type));
741 }
742 var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1];
743 var padding = convInfo.padInfo.type;
744 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW';
745 var dilations = [1, convInfo.dilationHeight, convInfo.dilationWidth, 1];
746 var opAttrs = [
747 createTensorsTypeOpAttr('T', x.dtype),
748 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
749 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding },
750 {
751 name: 'data_format',
752 type: this.binding.TF_ATTR_STRING,
753 value: dataFormat
754 },
755 { name: 'use_cudnn_on_gpu', type: this.binding.TF_ATTR_BOOL, value: true },
756 { name: 'dilations', type: this.binding.TF_ATTR_INT, value: dilations },
757 ];
758 if (padding === 'EXPLICIT') {
759 var padValue = [
760 convInfo.padInfo.top, convInfo.padInfo.bottom, convInfo.padInfo.left,
761 convInfo.padInfo.right
762 ];
763 opAttrs.push({
764 name: 'explicit_paddings',
765 type: this.binding.TF_ATTR_INT,
766 value: dataFormat === 'NHWC' ? [0, 0].concat(padValue, [0, 0]) : [0, 0, 0, 0].concat(padValue)
767 });
768 }
769 return this.executeSingleOutput('Conv2D', opAttrs, [x, filter]);
770 };
771 NodeJSKernelBackend.prototype.conv2dDerInput = function (dy, filter, convInfo) {
772 if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') {
773 throw new Error("TF Backend supports only 'valid' and 'same' padding " +
774 ("while padding was " + convInfo.padInfo.type));
775 }
776 var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1];
777 var padding = convInfo.padInfo.type;
778 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW';
779 var dilations = [1, convInfo.dilationHeight, convInfo.dilationWidth, 1];
780 var opAttrs = [
781 createTensorsTypeOpAttr('T', 'float32'),
782 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
783 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, {
784 name: 'data_format',
785 type: this.binding.TF_ATTR_STRING,
786 value: dataFormat
787 },
788 { name: 'use_cudnn_on_gpu', type: this.binding.TF_ATTR_BOOL, value: true },
789 { name: 'dilations', type: this.binding.TF_ATTR_INT, value: dilations }
790 ];
791 var inputSizes = tfjs_1.tensor1d(convInfo.inShape, 'int32');
792 return this.executeSingleOutput('Conv2DBackpropInput', opAttrs, [inputSizes, filter, dy]);
793 };
794 NodeJSKernelBackend.prototype.conv2dDerFilter = function (x, dy, convInfo) {
795 if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') {
796 throw new Error("TF Backend supports only 'valid' and 'same' padding " +
797 ("while padding was " + convInfo.padInfo.type));
798 }
799 var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1];
800 var padding = convInfo.padInfo.type;
801 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW';
802 var dilations = [1, convInfo.dilationHeight, convInfo.dilationWidth, 1];
803 var opAttrs = [
804 createTensorsTypeOpAttr('T', 'float32'),
805 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
806 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, {
807 name: 'data_format',
808 type: this.binding.TF_ATTR_STRING,
809 value: dataFormat
810 },
811 { name: 'use_cudnn_on_gpu', type: this.binding.TF_ATTR_BOOL, value: true },
812 { name: 'dilations', type: this.binding.TF_ATTR_INT, value: dilations }
813 ];
814 var filterSizes = tfjs_1.tensor1d(convInfo.filterShape, 'int32');
815 return this.executeSingleOutput('Conv2DBackpropFilter', opAttrs, [x, filterSizes, dy]);
816 };
817 NodeJSKernelBackend.prototype.depthwiseConv2DDerInput = function (dy, filter, convInfo) {
818 var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1];
819 var padding = convInfo.padInfo.type;
820 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW';
821 var dilations = [1, convInfo.dilationHeight, convInfo.dilationWidth, 1];
822 var opAttrs = [
823 createTensorsTypeOpAttr('T', 'float32'),
824 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
825 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, {
826 name: 'data_format',
827 type: this.binding.TF_ATTR_STRING,
828 value: dataFormat
829 },
830 { name: 'dilations', type: this.binding.TF_ATTR_INT, value: dilations }
831 ];
832 var inputSizes = tfjs_1.tensor1d(convInfo.inShape, 'int32');
833 return this.executeSingleOutput('DepthwiseConv2dNativeBackpropInput', opAttrs, [inputSizes, filter, dy]);
834 };
835 NodeJSKernelBackend.prototype.depthwiseConv2DDerFilter = function (x, dY, convInfo) {
836 var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1];
837 var padding = convInfo.padInfo.type;
838 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW';
839 var dilations = [1, convInfo.dilationHeight, convInfo.dilationWidth, 1];
840 var opAttrs = [
841 createTensorsTypeOpAttr('T', 'float32'),
842 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
843 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, {
844 name: 'data_format',
845 type: this.binding.TF_ATTR_STRING,
846 value: dataFormat
847 },
848 { name: 'dilations', type: this.binding.TF_ATTR_INT, value: dilations }
849 ];
850 var filterSizes = tfjs_1.tensor1d(convInfo.filterShape, 'int32');
851 return this.executeSingleOutput('DepthwiseConv2dNativeBackpropFilter', opAttrs, [x, filterSizes, dY]);
852 };
853 NodeJSKernelBackend.prototype.fusedDepthwiseConv2D = function (_a) {
854 var input = _a.input, filter = _a.filter, convInfo = _a.convInfo, bias = _a.bias, activation = _a.activation, preluActivationWeights = _a.preluActivationWeights;
855 var result = this.depthwiseConv2D(input, filter, convInfo);
856 if (bias != null) {
857 result = this.add(result, bias);
858 }
859 result = this.applyActivation(result, activation, preluActivationWeights);
860 return result;
861 };
862 NodeJSKernelBackend.prototype.depthwiseConv2D = function (input, filter, convInfo) {
863 if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') {
864 throw new Error("TF Backend supports only 'valid' and 'same' padding " +
865 ("while padding was " + convInfo.padInfo.type));
866 }
867 var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1];
868 var padding = convInfo.padInfo.type;
869 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW';
870 var dilations = [1, convInfo.dilationHeight, convInfo.dilationWidth, 1];
871 var opAttrs = [
872 createTensorsTypeOpAttr('T', input.dtype),
873 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
874 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, {
875 name: 'data_format',
876 type: this.binding.TF_ATTR_STRING,
877 value: dataFormat
878 },
879 { name: 'dilations', type: this.binding.TF_ATTR_INT, value: dilations }
880 ];
881 return this.executeSingleOutput('DepthwiseConv2dNative', opAttrs, [input, filter]);
882 };
883 NodeJSKernelBackend.prototype.conv3d = function (x, filter, convInfo) {
884 var strides = [
885 1, convInfo.strideDepth, convInfo.strideHeight, convInfo.strideWidth, 1
886 ];
887 var padding = convInfo.padInfo.type;
888 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NDHWC' : 'NCDHW';
889 if (!this.isGPUPackage && convInfo.dilationDepth > 1) {
890 throw new Error('CPU Dilation depth must be 1');
891 }
892 var dilations = [
893 1, convInfo.dilationDepth, convInfo.dilationHeight,
894 convInfo.dilationWidth, 1
895 ];
896 var opAttrs = [
897 createTensorsTypeOpAttr('T', x.dtype),
898 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
899 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, {
900 name: 'data_format',
901 type: this.binding.TF_ATTR_STRING,
902 value: dataFormat
903 },
904 { name: 'dilations', type: this.binding.TF_ATTR_INT, value: dilations }
905 ];
906 return this.executeSingleOutput('Conv3D', opAttrs, [x, filter]);
907 };
908 NodeJSKernelBackend.prototype.conv3dDerInput = function (dy, filter, convInfo) {
909 var strides = [
910 1, convInfo.strideDepth, convInfo.strideHeight, convInfo.strideWidth, 1
911 ];
912 var padding = convInfo.padInfo.type;
913 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NDHWC' : 'NCDHW';
914 if (!this.isGPUPackage && convInfo.dilationDepth > 1) {
915 throw new Error('CPU Dilation depth must be 1');
916 }
917 var dilations = [
918 1, convInfo.dilationDepth, convInfo.dilationHeight,
919 convInfo.dilationWidth, 1
920 ];
921 var opAttrs = [
922 createTensorsTypeOpAttr('T', dy.dtype),
923 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
924 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, {
925 name: 'data_format',
926 type: this.binding.TF_ATTR_STRING,
927 value: dataFormat
928 },
929 { name: 'dilations', type: this.binding.TF_ATTR_INT, value: dilations },
930 createTensorsTypeOpAttr('Tshape', 'int32')
931 ];
932 var inputSizes = tfjs_1.tensor1d(convInfo.inShape, 'int32');
933 return this.executeSingleOutput('Conv3DBackpropInputV2', opAttrs, [inputSizes, filter, dy]);
934 };
935 NodeJSKernelBackend.prototype.conv3dDerFilter = function (x, dY, convInfo) {
936 var strides = [
937 1, convInfo.strideDepth, convInfo.strideHeight, convInfo.strideWidth, 1
938 ];
939 var padding = convInfo.padInfo.type;
940 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NDHWC' : 'NCDHW';
941 if (!this.isGPUPackage && convInfo.dilationDepth > 1) {
942 throw new Error('CPU Dilation depth must be 1');
943 }
944 var dilations = [
945 1, convInfo.dilationDepth, convInfo.dilationHeight,
946 convInfo.dilationWidth, 1
947 ];
948 var opAttrs = [
949 createTensorsTypeOpAttr('T', x.dtype),
950 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
951 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, {
952 name: 'data_format',
953 type: this.binding.TF_ATTR_STRING,
954 value: dataFormat
955 },
956 { name: 'dilations', type: this.binding.TF_ATTR_INT, value: dilations }
957 ];
958 var filterSizes = tfjs_1.tensor1d(convInfo.filterShape, 'int32');
959 return this.executeSingleOutput('Conv3DBackpropFilterV2', opAttrs, [x, filterSizes, dY]);
960 };
961 NodeJSKernelBackend.prototype.maxPool = function (x, convInfo) {
962 if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') {
963 throw new Error("TF Backend supports only 'valid' and 'same' padding " +
964 ("while padding was " + convInfo.padInfo.type));
965 }
966 var ksize = [1, convInfo.filterHeight, convInfo.filterWidth, 1];
967 var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1];
968 var padding = convInfo.padInfo.type;
969 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW';
970 var opAttrs = [
971 createTensorsTypeOpAttr('T', x.dtype),
972 { name: 'ksize', type: this.binding.TF_ATTR_INT, value: ksize },
973 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
974 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, {
975 name: 'data_format',
976 type: this.binding.TF_ATTR_STRING,
977 value: dataFormat
978 }
979 ];
980 return this.executeSingleOutput('MaxPool', opAttrs, [x]);
981 };
982 NodeJSKernelBackend.prototype.maxPoolBackprop = function (dy, x, y, convInfo) {
983 if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') {
984 throw new Error("TF Backend supports only 'valid' and 'same' padding " +
985 ("while padding type was " + convInfo.padInfo.type));
986 }
987 var ksize = [1, convInfo.filterHeight, convInfo.filterWidth, 1];
988 var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1];
989 var padding = convInfo.padInfo.type;
990 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW';
991 var opAttrs = [
992 createTensorsTypeOpAttr('T', x.dtype),
993 { name: 'ksize', type: this.binding.TF_ATTR_INT, value: ksize },
994 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
995 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding },
996 {
997 name: 'data_format',
998 type: this.binding.TF_ATTR_STRING,
999 value: dataFormat
1000 },
1001 ];
1002 return this.executeSingleOutput('MaxPoolGrad', opAttrs, [x, y, dy]);
1003 };
1004 NodeJSKernelBackend.prototype.avgPool = function (x, convInfo) {
1005 if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') {
1006 throw new Error("TF Backend supports only 'valid' and 'same' padding " +
1007 ("while padding was " + convInfo.padInfo.type));
1008 }
1009 var ksize = [1, convInfo.filterHeight, convInfo.filterWidth, 1];
1010 var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1];
1011 var padding = convInfo.padInfo.type;
1012 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW';
1013 var opAttrs = [
1014 createTensorsTypeOpAttr('T', x.dtype),
1015 { name: 'ksize', type: this.binding.TF_ATTR_INT, value: ksize },
1016 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
1017 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding },
1018 {
1019 name: 'data_format',
1020 type: this.binding.TF_ATTR_STRING,
1021 value: dataFormat
1022 },
1023 ];
1024 return this.executeSingleOutput('AvgPool', opAttrs, [x]);
1025 };
1026 NodeJSKernelBackend.prototype.avgPoolBackprop = function (dy, x, convInfo) {
1027 if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') {
1028 throw new Error("TF Backend supports only 'valid' and 'same' padding " +
1029 ("while padding type was " + convInfo.padInfo.type));
1030 }
1031 var ksize = [1, convInfo.filterHeight, convInfo.filterWidth, 1];
1032 var strides = [1, convInfo.strideHeight, convInfo.strideWidth, 1];
1033 var padding = convInfo.padInfo.type;
1034 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NHWC' : 'NCHW';
1035 var opAttrs = [
1036 createTensorsTypeOpAttr('T', x.dtype),
1037 { name: 'ksize', type: this.binding.TF_ATTR_INT, value: ksize },
1038 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
1039 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding },
1040 {
1041 name: 'data_format',
1042 type: this.binding.TF_ATTR_STRING,
1043 value: dataFormat
1044 },
1045 ];
1046 var origInputShape = tfjs_1.tensor1d(x.shape, 'int32');
1047 return this.executeSingleOutput('AvgPoolGrad', opAttrs, [origInputShape, dy]);
1048 };
1049 NodeJSKernelBackend.prototype.avgPool3d = function (x, convInfo) {
1050 if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') {
1051 throw new Error("TF Backend supports only 'valid' and 'same' padding " +
1052 ("while padding was " + convInfo.padInfo.type));
1053 }
1054 var ksize = [
1055 1, convInfo.filterDepth, convInfo.filterHeight, convInfo.filterWidth, 1
1056 ];
1057 var strides = [
1058 1, convInfo.strideDepth, convInfo.strideHeight, convInfo.strideWidth, 1
1059 ];
1060 var padding = convInfo.padInfo.type;
1061 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NDHWC' : 'NCDHW';
1062 var opAttrs = [
1063 createTensorsTypeOpAttr('T', x.dtype),
1064 { name: 'ksize', type: this.binding.TF_ATTR_INT, value: ksize },
1065 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
1066 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding },
1067 {
1068 name: 'data_format',
1069 type: this.binding.TF_ATTR_STRING,
1070 value: dataFormat
1071 },
1072 ];
1073 return this.executeSingleOutput('AvgPool3D', opAttrs, [x]);
1074 };
1075 NodeJSKernelBackend.prototype.avgPool3dBackprop = function (dy, x, convInfo) {
1076 if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') {
1077 throw new Error("TF Backend supports only 'valid' and 'same' padding " +
1078 ("while padding type was " + convInfo.padInfo.type));
1079 }
1080 var ksize = [
1081 1, convInfo.filterDepth, convInfo.filterHeight, convInfo.filterWidth, 1
1082 ];
1083 var strides = [
1084 1, convInfo.strideDepth, convInfo.strideHeight, convInfo.strideWidth, 1
1085 ];
1086 var padding = convInfo.padInfo.type;
1087 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NDHWC' : 'NCDHW';
1088 var opAttrs = [
1089 createTensorsTypeOpAttr('T', x.dtype),
1090 { name: 'ksize', type: this.binding.TF_ATTR_INT, value: ksize },
1091 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
1092 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding },
1093 {
1094 name: 'data_format',
1095 type: this.binding.TF_ATTR_STRING,
1096 value: dataFormat
1097 },
1098 ];
1099 var origInputShape = tfjs_1.tensor1d(x.shape, 'int32');
1100 return this.executeSingleOutput('AvgPool3DGrad', opAttrs, [origInputShape, dy]);
1101 };
1102 NodeJSKernelBackend.prototype.maxPool3d = function (x, convInfo) {
1103 if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') {
1104 throw new Error("TF Backend supports only 'valid' and 'same' padding " +
1105 ("while padding was " + convInfo.padInfo.type));
1106 }
1107 var ksize = [
1108 1, convInfo.filterDepth, convInfo.filterHeight, convInfo.filterWidth, 1
1109 ];
1110 var strides = [
1111 1, convInfo.strideDepth, convInfo.strideHeight, convInfo.strideWidth, 1
1112 ];
1113 var padding = convInfo.padInfo.type;
1114 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NDHWC' : 'NCDHW';
1115 var opAttrs = [
1116 createTensorsTypeOpAttr('T', x.dtype),
1117 { name: 'ksize', type: this.binding.TF_ATTR_INT, value: ksize },
1118 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
1119 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding }, {
1120 name: 'data_format',
1121 type: this.binding.TF_ATTR_STRING,
1122 value: dataFormat
1123 }
1124 ];
1125 return this.executeSingleOutput('MaxPool3D', opAttrs, [x]);
1126 };
1127 NodeJSKernelBackend.prototype.maxPool3dBackprop = function (dy, x, y, convInfo) {
1128 if (convInfo.padInfo.type !== 'VALID' && convInfo.padInfo.type !== 'SAME') {
1129 throw new Error("TF Backend supports only 'valid' and 'same' padding " +
1130 ("while padding type was " + convInfo.padInfo.type));
1131 }
1132 var ksize = [
1133 1, convInfo.filterDepth, convInfo.filterHeight, convInfo.filterWidth, 1
1134 ];
1135 var strides = [
1136 1, convInfo.strideDepth, convInfo.strideHeight, convInfo.strideWidth, 1
1137 ];
1138 var padding = convInfo.padInfo.type;
1139 var dataFormat = convInfo.dataFormat === 'channelsLast' ? 'NDHWC' : 'NCDHW';
1140 var opAttrs = [
1141 createTensorsTypeOpAttr('T', x.dtype),
1142 { name: 'ksize', type: this.binding.TF_ATTR_INT, value: ksize },
1143 { name: 'strides', type: this.binding.TF_ATTR_INT, value: strides },
1144 { name: 'padding', type: this.binding.TF_ATTR_STRING, value: padding },
1145 {
1146 name: 'data_format',
1147 type: this.binding.TF_ATTR_STRING,
1148 value: dataFormat
1149 },
1150 ];
1151 return this.executeSingleOutput('MaxPool3DGrad', opAttrs, [x, y, dy]);
1152 };
1153 NodeJSKernelBackend.prototype.reshape = function (x, shape) {
1154 var shapeTensor = tfjs_1.tensor1d(shape, 'int32');
1155 var opAttrs = [
1156 createTensorsTypeOpAttr('T', x.dtype),
1157 createTensorsTypeOpAttr('Tshape', shapeTensor.dtype)
1158 ];
1159 return this.executeSingleOutput('Reshape', opAttrs, [x, shapeTensor]);
1160 };
1161 NodeJSKernelBackend.prototype.cast = function (x, dtype) {
1162 var opAttrs = [
1163 createTensorsTypeOpAttr('SrcT', x.dtype),
1164 createTensorsTypeOpAttr('DstT', dtype),
1165 { name: 'Truncate', type: this.binding.TF_ATTR_BOOL, value: false }
1166 ];
1167 return this.executeSingleOutput('Cast', opAttrs, [x]);
1168 };
1169 NodeJSKernelBackend.prototype.tile = function (x, reps) {
1170 var opAttrs = [
1171 createTensorsTypeOpAttr('T', x.dtype),
1172 createTensorsTypeOpAttr('Tmultiples', 'int32')
1173 ];
1174 var multiples = tfjs_1.tensor1d(reps, 'int32');
1175 return this.executeSingleOutput('Tile', opAttrs, [x, multiples]);
1176 };
1177 NodeJSKernelBackend.prototype.pad = function (x, paddings, constantValue) {
1178 // Bind tensor values
1179 var paddingsTensor = tfjs_1.tensor2d(paddings, [paddings.length, 2], 'int32');
1180 var constantTensor = tfjs_1.scalar(constantValue, x.dtype);
1181 var opAttrs = [
1182 createTensorsTypeOpAttr('T', x.dtype),
1183 createTensorsTypeOpAttr('Tpaddings', paddingsTensor.dtype)
1184 ];
1185 return this.executeSingleOutput('PadV2', opAttrs, [x, paddingsTensor, constantTensor]);
1186 };
1187 NodeJSKernelBackend.prototype.transpose = function (x, perm) {
1188 var permTensor = tfjs_1.tensor1d(perm, 'int32');
1189 var opAttrs = [
1190 createTensorsTypeOpAttr('T', x.dtype),
1191 createTensorsTypeOpAttr('Tperm', 'int32')
1192 ];
1193 return this.executeSingleOutput('Transpose', opAttrs, [x, permTensor]);
1194 };
1195 NodeJSKernelBackend.prototype.gather = function (x, indices, axis) {
1196 var axisTensor = tfjs_1.scalar(axis, 'int32');
1197 var opAttrs = [
1198 createTensorsTypeOpAttr('Tparams', x.dtype),
1199 createTensorsTypeOpAttr('Tindices', indices.dtype),
1200 createTensorsTypeOpAttr('Taxis', 'int32')
1201 ];
1202 return this.executeSingleOutput('GatherV2', opAttrs, [x, indices, axisTensor]);
1203 };
1204 NodeJSKernelBackend.prototype.gatherND = function (x, indices) {
1205 var opAttrs = [
1206 createTensorsTypeOpAttr('Tparams', x.dtype),
1207 createTensorsTypeOpAttr('Tindices', 'int32')
1208 ];
1209 return this.executeSingleOutput('GatherNd', opAttrs, [x, indices]);
1210 };
1211 NodeJSKernelBackend.prototype.scatterND = function (indices, updates, shape) {
1212 var opAttrs = [
1213 createTensorsTypeOpAttr('T', updates.dtype),
1214 createTensorsTypeOpAttr('Tindices', 'int32')
1215 ];
1216 var shapeTensor = tfjs_1.tensor1d(shape, 'int32');
1217 return this.executeSingleOutput('ScatterNd', opAttrs, [indices, updates, shapeTensor]);
1218 };
1219 NodeJSKernelBackend.prototype.batchToSpaceND = function (x, blockShape, crops) {
1220 var blockShapeTensor = tfjs_1.tensor1d(blockShape, 'int32');
1221 var cropsTensor = tfjs_1.tensor2d(crops, [crops.length, crops[0].length], 'int32');
1222 var opAttrs = [
1223 createTensorsTypeOpAttr('T', x.dtype),
1224 createTensorsTypeOpAttr('Tblock_shape', 'int32'),
1225 createTensorsTypeOpAttr('Tcrops', cropsTensor.dtype)
1226 ];
1227 return this.executeSingleOutput('BatchToSpaceND', opAttrs, [x, blockShapeTensor, cropsTensor]);
1228 };
1229 NodeJSKernelBackend.prototype.spaceToBatchND = function (x, blockShape, paddings) {
1230 var blockShapeTensor = tfjs_1.tensor1d(blockShape, 'int32');
1231 var paddingsTensor = tfjs_1.tensor2d(paddings, [paddings.length, paddings[0].length], 'int32');
1232 var opAttrs = [
1233 createTensorsTypeOpAttr('T', x.dtype),
1234 createTensorsTypeOpAttr('Tblock_shape', 'int32'),
1235 createTensorsTypeOpAttr('Tpaddings', paddingsTensor.dtype)
1236 ];
1237 return this.executeSingleOutput('SpaceToBatchND', opAttrs, [x, blockShapeTensor, paddingsTensor]);
1238 };
1239 NodeJSKernelBackend.prototype.resizeBilinear = function (x, newHeight, newWidth, alignCorners) {
1240 var opAttrs = [
1241 createTensorsTypeOpAttr('T', x.dtype),
1242 {
1243 name: 'align_corners',
1244 type: this.binding.TF_ATTR_BOOL,
1245 value: alignCorners
1246 },
1247 ];
1248 var size = tfjs_1.tensor1d([newHeight, newWidth], 'int32');
1249 return this.executeSingleOutput('ResizeBilinear', opAttrs, [x, size]);
1250 };
1251 NodeJSKernelBackend.prototype.resizeBilinearBackprop = function (dy, x, alignCorners) {
1252 var opAttrs = [
1253 createTensorsTypeOpAttr('T', x.dtype), {
1254 name: 'align_corners',
1255 type: this.binding.TF_ATTR_BOOL,
1256 value: alignCorners
1257 }
1258 ];
1259 return this.executeSingleOutput('ResizeBilinearGrad', opAttrs, [dy, x]);
1260 };
1261 NodeJSKernelBackend.prototype.resizeNearestNeighbor = function (x, newHeight, newWidth, alignCorners) {
1262 var opAttrs = [
1263 createTensorsTypeOpAttr('T', x.dtype),
1264 {
1265 name: 'align_corners',
1266 type: this.binding.TF_ATTR_BOOL,
1267 value: alignCorners
1268 },
1269 ];
1270 var size = tfjs_1.tensor1d([newHeight, newWidth], 'int32');
1271 return this.executeSingleOutput('ResizeNearestNeighbor', opAttrs, [x, size]);
1272 };
1273 NodeJSKernelBackend.prototype.resizeNearestNeighborBackprop = function (dy, x, alignCorners) {
1274 var opAttrs = [
1275 createTensorsTypeOpAttr('T', x.dtype), {
1276 name: 'align_corners',
1277 type: this.binding.TF_ATTR_BOOL,
1278 value: alignCorners
1279 }
1280 ];
1281 var _a = x.shape, origHeight = _a[1], origWidth = _a[2];
1282 var size = tfjs_1.tensor1d([origHeight, origWidth], 'int32');
1283 return this.executeSingleOutput('ResizeNearestNeighborGrad', opAttrs, [dy, size]);
1284 };
1285 NodeJSKernelBackend.prototype.batchNorm = function (x, mean, variance, offset, scale, varianceEpsilon) {
1286 if (mean.rank > 1) {
1287 // Fused batch norm doesn't work with high-dim mean/var/scale/offset.
1288 var inv = tfjs_1.rsqrt(variance.add(tfjs_1.scalar(varianceEpsilon)));
1289 if (scale != null) {
1290 inv = inv.mul(scale);
1291 }
1292 var xNorm = x.sub(mean).mul(inv);
1293 return offset != null ? xNorm.add(offset) : xNorm;
1294 }
1295 var dataFormat = 'NHWC';
1296 var depth = x.shape[3];
1297 var opAttrs = [
1298 createTensorsTypeOpAttr('T', x.dtype),
1299 {
1300 name: 'epsilon',
1301 type: this.binding.TF_ATTR_FLOAT,
1302 value: varianceEpsilon
1303 },
1304 {
1305 name: 'data_format',
1306 type: this.binding.TF_ATTR_STRING,
1307 value: dataFormat
1308 },
1309 { name: 'is_training', type: this.binding.TF_ATTR_BOOL, value: false },
1310 ];
1311 var numOutputs = 5;
1312 if (scale == null) {
1313 scale = tfjs_1.fill([depth], 1);
1314 }
1315 if (offset == null) {
1316 offset = tfjs_1.fill([depth], 0);
1317 }
1318 return this.executeMultipleOutputs('FusedBatchNorm', opAttrs, [x, scale, offset, mean, variance], numOutputs)[0];
1319 };
1320 NodeJSKernelBackend.prototype.localResponseNormalization4D = function (x, radius, bias, alpha, beta) {
1321 var opAttrs = [
1322 createTensorsTypeOpAttr('T', x.dtype),
1323 { name: 'depth_radius', type: this.binding.TF_ATTR_INT, value: radius },
1324 { name: 'bias', type: this.binding.TF_ATTR_FLOAT, value: bias },
1325 { name: 'alpha', type: this.binding.TF_ATTR_FLOAT, value: alpha },
1326 { name: 'beta', type: this.binding.TF_ATTR_FLOAT, value: beta },
1327 ];
1328 return this.executeSingleOutput('LRN', opAttrs, [x]);
1329 };
1330 NodeJSKernelBackend.prototype.LRNGrad = function (dy, inputImage, outputImage, radius, bias, alpha, beta) {
1331 var opAttrs = [
1332 createTensorsTypeOpAttr('T', dy.dtype),
1333 { name: 'depth_radius', type: this.binding.TF_ATTR_INT, value: radius },
1334 { name: 'bias', type: this.binding.TF_ATTR_FLOAT, value: bias },
1335 { name: 'alpha', type: this.binding.TF_ATTR_FLOAT, value: alpha },
1336 { name: 'beta', type: this.binding.TF_ATTR_FLOAT, value: beta },
1337 ];
1338 return this.executeSingleOutput('LRNGrad', opAttrs, [dy, inputImage, outputImage]);
1339 };
1340 NodeJSKernelBackend.prototype.multinomial = function (logits, normalized, numSamples, seed) {
1341 if (normalized) {
1342 throw new Error('TF Node backend does not support normalized logits ' +
1343 'passed to multinomial');
1344 }
1345 var opAttrs = [
1346 createTensorsTypeOpAttr('T', logits.dtype),
1347 createTensorsTypeOpAttr('output_dtype', 'int32'),
1348 { name: 'seed', type: this.binding.TF_ATTR_INT, value: seed },
1349 { name: 'seed2', type: this.binding.TF_ATTR_INT, value: seed * seed },
1350 ];
1351 return this.executeSingleOutput('Multinomial', opAttrs, [logits, tfjs_1.scalar(numSamples, 'int32')]);
1352 };
1353 NodeJSKernelBackend.prototype.oneHot = function (indices, depth, onValue, offValue) {
1354 var depthTensor = tfjs_1.scalar(depth, 'int32');
1355 var onValueTensor = tfjs_1.scalar(onValue, 'int32');
1356 var offValueTensor = tfjs_1.scalar(offValue, 'int32');
1357 var opAttrs = [
1358 { name: 'axis', type: this.binding.TF_ATTR_INT, value: -1 },
1359 createTensorsTypeOpAttr('T', indices.dtype),
1360 createTensorsTypeOpAttr('TI', indices.dtype)
1361 ];
1362 return this.executeSingleOutput('OneHot', opAttrs, [
1363 indices, depthTensor, onValueTensor, offValueTensor
1364 ]);
1365 };
1366 NodeJSKernelBackend.prototype.cumsum = function (x, axis, exclusive, reverse) {
1367 var axisTensor = tfjs_1.scalar(axis, 'int32');
1368 var opAttrs = [
1369 { name: 'exclusive', type: this.binding.TF_ATTR_BOOL, value: exclusive },
1370 { name: 'reverse', type: this.binding.TF_ATTR_BOOL, value: reverse },
1371 createTensorsTypeOpAttr('T', x.dtype),
1372 createTensorsTypeOpAttr('Tidx', 'int32')
1373 ];
1374 return this.executeSingleOutput('Cumsum', opAttrs, [x, axisTensor]);
1375 };
1376 NodeJSKernelBackend.prototype.nonMaxSuppression = function (boxes, scores, maxOutputSize, iouThreshold, scoreThreshold) {
1377 var opAttrs = [createTensorsTypeOpAttr('T', boxes.dtype)];
1378 var maxOutputSizeTensor = tfjs_1.scalar(maxOutputSize, 'int32');
1379 var iouThresholdTensor = tfjs_1.scalar(iouThreshold);
1380 var scoreThresholdTensor = tfjs_1.scalar(scoreThreshold);
1381 return this.executeSingleOutput('NonMaxSuppressionV3', opAttrs, [
1382 boxes, scores, maxOutputSizeTensor, iouThresholdTensor,
1383 scoreThresholdTensor
1384 ]);
1385 };
1386 NodeJSKernelBackend.prototype.fft = function (x) {
1387 var opAttrs = [createTensorsTypeOpAttr('Tcomplex', x.dtype)];
1388 return this.executeSingleOutput('FFT', opAttrs, [x]);
1389 };
1390 NodeJSKernelBackend.prototype.ifft = function (x) {
1391 var opAttrs = [createTensorsTypeOpAttr('Tcomplex', x.dtype)];
1392 return this.executeSingleOutput('IFFT', opAttrs, [x]);
1393 };
1394 NodeJSKernelBackend.prototype.complex = function (real, imag) {
1395 var opAttrs = [
1396 createTensorsTypeOpAttr('T', real),
1397 {
1398 name: 'Tout',
1399 type: this.binding.TF_ATTR_TYPE,
1400 value: this.binding.TF_COMPLEX64
1401 },
1402 ];
1403 var inputs = [real, imag];
1404 return this.executeSingleOutput('Complex', opAttrs, inputs);
1405 };
1406 NodeJSKernelBackend.prototype.real = function (input) {
1407 var opAttrs = [
1408 createTensorsTypeOpAttr('T', input), {
1409 name: 'Tout',
1410 type: this.binding.TF_ATTR_TYPE,
1411 value: this.binding.TF_FLOAT
1412 }
1413 ];
1414 var inputs = [input];
1415 return this.executeSingleOutput('Real', opAttrs, inputs);
1416 };
1417 NodeJSKernelBackend.prototype.imag = function (input) {
1418 var opAttrs = [
1419 {
1420 name: 'T',
1421 type: this.binding.TF_ATTR_TYPE,
1422 value: this.binding.TF_COMPLEX64
1423 },
1424 {
1425 name: 'Tout',
1426 type: this.binding.TF_ATTR_TYPE,
1427 value: this.binding.TF_FLOAT
1428 }
1429 ];
1430 var inputs = [input];
1431 return this.executeSingleOutput('Imag', opAttrs, inputs);
1432 };
1433 NodeJSKernelBackend.prototype.cropAndResize = function (image, boxes, boxIndex, cropSize, method, extrapolationValue) {
1434 var opAttrs = [
1435 createTensorsTypeOpAttr('T', image.dtype),
1436 { name: 'method', type: this.binding.TF_ATTR_STRING, value: method }, {
1437 name: 'extrapolation_value',
1438 type: this.binding.TF_ATTR_FLOAT,
1439 value: extrapolationValue
1440 }
1441 ];
1442 var cropSizeTensor = tfjs_1.tensor1d(cropSize, 'int32');
1443 return this.executeSingleOutput('CropAndResize', opAttrs, [image, boxes, boxIndex, cropSizeTensor]);
1444 };
1445 NodeJSKernelBackend.prototype.depthToSpace = function (x, blockSize, dataFormat) {
1446 var opAttrs = [
1447 createTensorsTypeOpAttr('T', x), {
1448 name: 'block_size',
1449 type: this.binding.TF_ATTR_INT,
1450 value: blockSize < 2 ? 2 : blockSize
1451 },
1452 {
1453 name: 'data_format',
1454 type: this.binding.TF_ATTR_STRING,
1455 value: dataFormat
1456 }
1457 ];
1458 var inputs = [x];
1459 return this.executeSingleOutput('DepthToSpace', opAttrs, inputs);
1460 };
1461 NodeJSKernelBackend.prototype.split = function (value, sizeSplits, axis) {
1462 var opAttrs = [
1463 {
1464 name: 'num_split',
1465 type: this.binding.TF_ATTR_INT,
1466 value: sizeSplits.length
1467 },
1468 createTensorsTypeOpAttr('T', value), {
1469 name: 'Tlen',
1470 type: this.binding.TF_ATTR_TYPE,
1471 value: this.binding.TF_INT32
1472 }
1473 ];
1474 var inputs = [value];
1475 inputs.push(tfjs_1.tensor1d(sizeSplits, 'int32'));
1476 inputs.push(tfjs_1.scalar(axis, 'int32'));
1477 return this.executeMultipleOutputs('SplitV', opAttrs, inputs, sizeSplits.length);
1478 };
1479 NodeJSKernelBackend.prototype.sparseToDense = function (sparseIndices, sparseValues, outputShape, defaultValue) {
1480 var opAttrs = [
1481 { name: 'validate_indices', type: this.binding.TF_ATTR_BOOL, value: true },
1482 createTensorsTypeOpAttr('T', sparseValues.dtype),
1483 createTensorsTypeOpAttr('Tindices', sparseIndices.dtype)
1484 ];
1485 var outputShapeTensor = tfjs_1.tensor1d(outputShape, 'int32');
1486 return this.executeSingleOutput('SparseToDense', opAttrs, [
1487 sparseIndices, outputShapeTensor, sparseValues, defaultValue
1488 ]);
1489 };
1490 NodeJSKernelBackend.prototype.linspace = function (start, stop, num) {
1491 var opAttrs = [
1492 createTensorsTypeOpAttr('T', 'float32'),
1493 createTensorsTypeOpAttr('Tidx', 'int32')
1494 ];
1495 var inputs = [
1496 tfjs_1.scalar(start, 'float32'), tfjs_1.scalar(stop, 'float32'), tfjs_1.scalar(num, 'int32')
1497 ];
1498 return this.executeSingleOutput('LinSpace', opAttrs, inputs);
1499 };
1500 NodeJSKernelBackend.prototype.decodeJpeg = function (contents, channels, ratio, fancyUpscaling, tryRecoverTruncated, acceptableFraction, dctMethod) {
1501 var opAttrs = [
1502 { name: 'channels', type: this.binding.TF_ATTR_INT, value: channels },
1503 { name: 'ratio', type: this.binding.TF_ATTR_INT, value: ratio }, {
1504 name: 'fancy_upscaling',
1505 type: this.binding.TF_ATTR_BOOL,
1506 value: fancyUpscaling
1507 },
1508 {
1509 name: 'try_recover_truncated',
1510 type: this.binding.TF_ATTR_BOOL,
1511 value: tryRecoverTruncated
1512 },
1513 {
1514 name: 'acceptable_fraction',
1515 type: this.binding.TF_ATTR_FLOAT,
1516 value: acceptableFraction
1517 },
1518 { name: 'dct_method', type: this.binding.TF_ATTR_STRING, value: dctMethod }
1519 ];
1520 var inputArgs = [tfjs_1.scalar(contents, 'string')];
1521 return this.executeSingleOutput('DecodeJpeg', opAttrs, inputArgs);
1522 };
1523 NodeJSKernelBackend.prototype.decodePng = function (contents, channels) {
1524 var opAttrs = [{ name: 'channels', type: this.binding.TF_ATTR_INT, value: channels }];
1525 var inputArgs = [tfjs_1.scalar(contents, 'string')];
1526 return this.executeSingleOutput('DecodePng', opAttrs, inputArgs);
1527 };
1528 NodeJSKernelBackend.prototype.decodeBmp = function (contents, channels) {
1529 var opAttrs = [{ name: 'channels', type: this.binding.TF_ATTR_INT, value: channels }];
1530 var inputArgs = [tfjs_1.scalar(contents, 'string')];
1531 return this.executeSingleOutput('DecodeBmp', opAttrs, inputArgs);
1532 };
1533 NodeJSKernelBackend.prototype.decodeGif = function (contents) {
1534 var inputArgs = [tfjs_1.scalar(contents, 'string')];
1535 return this.executeSingleOutput('DecodeGif', [], inputArgs);
1536 };
1537 NodeJSKernelBackend.prototype.executeEncodeImageOp = function (name, opAttrs, imageData, imageShape) {
1538 var inputTensorId = this.binding.createTensor(imageShape, this.binding.TF_UINT8, imageData);
1539 var outputMetadata = this.binding.executeOp(name, opAttrs, [inputTensorId], 1);
1540 var outputTensorInfo = outputMetadata[0];
1541 // prevent the tensor data from being converted to a UTF8 string, since
1542 // the encoded data is not valid UTF8
1543 outputTensorInfo.dtype = this.binding.TF_UINT8;
1544 return this.createOutputTensor(outputTensorInfo);
1545 };
1546 NodeJSKernelBackend.prototype.encodeJpeg = function (imageData, imageShape, format, quality, progressive, optimizeSize, chromaDownsampling, densityUnit, xDensity, yDensity, xmpMetadata) {
1547 var opAttrs = [
1548 { name: 'format', type: this.binding.TF_ATTR_STRING, value: format },
1549 { name: 'quality', type: this.binding.TF_ATTR_INT, value: quality }, {
1550 name: 'progressive',
1551 type: this.binding.TF_ATTR_BOOL,
1552 value: progressive
1553 },
1554 {
1555 name: 'optimize_size',
1556 type: this.binding.TF_ATTR_BOOL,
1557 value: optimizeSize
1558 },
1559 {
1560 name: 'chroma_downsampling',
1561 type: this.binding.TF_ATTR_BOOL,
1562 value: chromaDownsampling
1563 },
1564 {
1565 name: 'density_unit',
1566 type: this.binding.TF_ATTR_STRING,
1567 value: densityUnit
1568 },
1569 { name: 'x_density', type: this.binding.TF_ATTR_INT, value: xDensity },
1570 { name: 'y_density', type: this.binding.TF_ATTR_INT, value: yDensity }, {
1571 name: 'xmp_metadata',
1572 type: this.binding.TF_ATTR_STRING,
1573 value: xmpMetadata
1574 }
1575 ];
1576 return this.executeEncodeImageOp('EncodeJpeg', opAttrs, imageData, imageShape);
1577 };
1578 NodeJSKernelBackend.prototype.encodePng = function (imageData, imageShape, compression) {
1579 var opAttrs = [
1580 { name: 'compression', type: this.binding.TF_ATTR_INT, value: compression }
1581 ];
1582 return this.executeEncodeImageOp('EncodePng', opAttrs, imageData, imageShape);
1583 };
1584 NodeJSKernelBackend.prototype.deleteSavedModel = function (id) {
1585 this.binding.deleteSavedModel(id);
1586 };
1587 NodeJSKernelBackend.prototype.loadSavedModelMetaGraph = function (path, tags) {
1588 return this.binding.loadSavedModel(path, tags);
1589 };
1590 NodeJSKernelBackend.prototype.runSavedModel = function (id, inputs, inputOpNames, outputOpNames) {
1591 var _this = this;
1592 var outputMetadata = this.binding.runSavedModel(id, this.getInputTensorIds(inputs), inputOpNames.join(','), outputOpNames.join(','));
1593 return outputMetadata.map(function (m) { return _this.createOutputTensor(m); });
1594 };
1595 // ------------------------------------------------------------
1596 // TensorBoard-related (tfjs-node-specific) backend kernels.
1597 NodeJSKernelBackend.prototype.summaryWriter = function (logdir) {
1598 var opAttrs = [
1599 {
1600 name: 'shared_name',
1601 type: this.binding.TF_ATTR_STRING,
1602 value: "logdir:" + logdir
1603 },
1604 { name: 'container', type: this.binding.TF_ATTR_STRING, value: '' }
1605 ];
1606 var writerResource = this.executeSingleOutput('SummaryWriter', opAttrs, []);
1607 return writerResource;
1608 };
1609 NodeJSKernelBackend.prototype.createSummaryFileWriter = function (resourceHandle, logdir, maxQueue, flushMillis, filenameSuffix) {
1610 var inputArgs = [
1611 resourceHandle, tfjs_1.scalar(logdir),
1612 tfjs_1.scalar(maxQueue == null ? 10 : maxQueue, 'int32'),
1613 tfjs_1.scalar(flushMillis == null ? 2 * 60 * 1000 : flushMillis, 'int32'),
1614 tfjs_1.scalar(filenameSuffix == null ? '.v2' : filenameSuffix)
1615 ];
1616 this.executeMultipleOutputs('CreateSummaryFileWriter', [], inputArgs, 0);
1617 };
1618 NodeJSKernelBackend.prototype.writeScalarSummary = function (resourceHandle, step, name, value) {
1619 var _this = this;
1620 tfjs_1.tidy(function () {
1621 tfjs_1.util.assert(Number.isInteger(step), function () { return "step is expected to be an integer, but is instead " + step; });
1622 var inputArgs = [resourceHandle, new int64_tensors_1.Int64Scalar(step), tfjs_1.scalar(name, 'string')];
1623 var typeAttr;
1624 if (typeof value === 'number') {
1625 inputArgs.push(tfjs_1.scalar(value));
1626 typeAttr = _this.binding.TF_FLOAT;
1627 }
1628 else {
1629 // `value` is a Scalar.
1630 tfjs_1.util.assert(value.rank === 0, function () { return "A non-scalar tensor (rank " + value.rank + ") is passed to " +
1631 "writeScalarSummary()"; });
1632 inputArgs.push(value);
1633 typeAttr = _this.typeAttributeFromTensor(value);
1634 }
1635 var opAttrs = [{ name: 'T', type: _this.binding.TF_ATTR_TYPE, value: typeAttr }];
1636 _this.binding.executeOp('WriteScalarSummary', opAttrs, _this.getInputTensorIds(inputArgs), 0);
1637 });
1638 };
1639 NodeJSKernelBackend.prototype.flushSummaryWriter = function (resourceHandle) {
1640 var inputArgs = [resourceHandle];
1641 this.executeMultipleOutputs('FlushSummaryWriter', [], inputArgs, 0);
1642 };
1643 // ~ TensorBoard-related (tfjs-node-specific) backend kernels.
1644 // ------------------------------------------------------------
1645 NodeJSKernelBackend.prototype.memory = function () {
1646 // Due to automatic garbage collection, the numbers are unreliable.
1647 // TODO(kreeger): Since there is finalization in C, count the true
1648 // number of undisposed tensors.
1649 return { unreliable: true };
1650 };
1651 NodeJSKernelBackend.prototype.time = function (f) {
1652 return __awaiter(this, void 0, void 0, function () {
1653 var start, elapsed;
1654 return __generator(this, function (_a) {
1655 start = process.hrtime();
1656 f();
1657 elapsed = process.hrtime(start);
1658 return [2 /*return*/, { kernelMs: elapsed[0] * 1000 + elapsed[1] / 1000000 }];
1659 });
1660 });
1661 };
1662 NodeJSKernelBackend.prototype.getNumOfSavedModels = function () {
1663 return this.binding.getNumOfSavedModels();
1664 };
1665 return NodeJSKernelBackend;
1666}(tfjs_1.KernelBackend));
1667exports.NodeJSKernelBackend = NodeJSKernelBackend;
1668/** Returns an instance of the Node.js backend. */
1669function nodeBackend() {
1670 return tf.findBackend('tensorflow');
1671}
1672exports.nodeBackend = nodeBackend;
1673/** Returns the TF dtype for a given DataType. */
1674function getTFDType(dataType) {
1675 var binding = nodeBackend().binding;
1676 switch (dataType) {
1677 case 'float32':
1678 return binding.TF_FLOAT;
1679 case 'int32':
1680 return binding.TF_INT32;
1681 case 'bool':
1682 return binding.TF_BOOL;
1683 case 'complex64':
1684 return binding.TF_COMPLEX64;
1685 case 'string':
1686 return binding.TF_STRING;
1687 // tslint:disable-next-line:no-any
1688 case 'int64':
1689 // int64 is not a generally supported dtype in TensorFlow.js
1690 // (tfjs-core). However, it needs to be included here for the purpose of
1691 // writing the `step` value to TensorBoard via WriteScalarSummary and
1692 // other op kernels.
1693 return binding.TF_INT64;
1694 default:
1695 var errorMessage = "Unknown dtype: " + dataType;
1696 throw new Error(errorMessage);
1697 }
1698}
1699exports.getTFDType = getTFDType;
1700/**
1701 * Creates a TFEOpAttr for a 'type' OpDef attribute from a Tensor or list of
1702 * Tensors.
1703 */
1704function createTensorsTypeOpAttr(attrName, tensorsOrDtype) {
1705 if (util_1.isNullOrUndefined(tensorsOrDtype)) {
1706 throw new Error('Invalid input tensors value.');
1707 }
1708 return {
1709 name: attrName,
1710 type: nodeBackend().binding.TF_ATTR_TYPE,
1711 value: (tensorsOrDtype instanceof tf.Tensor || Array.isArray(tensorsOrDtype)) ?
1712 getTFDTypeForInputs(tensorsOrDtype) :
1713 getTFDType(tensorsOrDtype)
1714 };
1715}
1716exports.createTensorsTypeOpAttr = createTensorsTypeOpAttr;
1717function createOpAttr(attrName, tensorsOrDtype, value) {
1718 if (util_1.isNullOrUndefined(tensorsOrDtype)) {
1719 throw new Error('Invalid input tensors value.');
1720 }
1721 return { name: attrName, type: nodeBackend().binding.TF_BOOL, value: value };
1722}
1723exports.createOpAttr = createOpAttr;
1724/** Returns the dtype number for a single or list of input Tensors. */
1725function getTFDTypeForInputs(tensors) {
1726 if (util_1.isNullOrUndefined(tensors)) {
1727 throw new Error('Invalid input tensors value.');
1728 }
1729 if (util_1.isArray(tensors)) {
1730 for (var i = 0; i < tensors.length; i++) {
1731 return getTFDType(tensors[i].dtype);
1732 }
1733 return -1;
1734 }
1735 else {
1736 return getTFDType(tensors.dtype);
1737 }
1738}
1739function ensureTensorflowBackend() {
1740 tf.util.assert(tf.getBackend() === 'tensorflow', function () { return "Expect the current backend to be \"tensorflow\", but got \"" + tf.getBackend() + "\""; });
1741}
1742exports.ensureTensorflowBackend = ensureTensorflowBackend;