Tfjs: Problem when running TF.js with Jest (unit testing)

Created on 25 Jul 2018  路  13Comments  路  Source: tensorflow/tfjs

TensorFlow.js version

0.12.3

Browser version

Node.js 10.6.0 (no browser)
Typescript 2.7.1

Describe the problem or feature request

I'm trying to use tf.sum() and tf.squaredDifference() (see below). Two issues -- some or all might be my fault:

  1. According to the docs, I can pass a tf.scalar to tf.squaredDifference; however, I get a Typescript error when passing a tf.scalar unless I cast to any. Seems it's expecting a Tensor. Are the docs wrong, or is the Typescript definition too restrictive here?
  2. When I run the below code to sum my tensor (vector), I get the error tensor1d() requires values to be a flat/TypedArray. This already should be a 1D tensor/vector, so why is tfjs complaining here? But moreover, the docs suggest I can sum with higher-order tensors as well, so not sure what the 1D restriction is about. Any ideas would be welcome!

Thanks in advance!

Code to reproduce the bug / link to feature request

    // state is a tf.Tensor1D
    console.log(state.squaredDifference(tf.scalar(0) as any).sum());

Most helpful comment

Can confirm that running with jest can cause this error to throw:

tensor1d() requires values to be a flat/TypedArray

All 13 comments

Hi @DABH ,

Can you share your project setup?

  1. It is likely that you have two imports of tf.js (which means implicitly tf.Tensor and tf2.Tensor) at which point the typescript compiler can't infer that tf.Scalar/Tensor is an instance of tf2.Scalar/Tensor.

  2. It's strange that you get this error at this line. Can you share the line that creates state? I'm guessing the error happens before the line, where you call smth like state = tensor1d(...)

Thanks for your reply!

Sure thing -- the relevant lines in my package.json look like

  "dependencies": {
    "@tensorflow/tfjs": "^0.12.3",
    "@tensorflow/tfjs-node": "^0.1.9",
    "@tensorflow/tfjs-node-gpu": "^0.1.9",
...

I just added these dependencies to my existing project, which previously had no references to anything TensorFlow-related.

The other potentially relevant thing is that I'm running my Typescript source file via jest to (try to) do some unit tests on my tfjs-based routines. So my command looks like jest tests/test1.ts.

Aside from that, the relevant imports in my test1.ts file are

import * as tf from '@tensorflow/tfjs';
// Node CPU backend
import '@tensorflow/tfjs-node';

and then later in the file I have functions which invoke tfjs stuff, like my previous post. If there's any more description I can give, let me know!

The line that creates state in my above example looks like

  const x = f(tf.tensor1d([1, 2, 3]));

Seems pretty straightforward so not sure what's going on or if I'm missing something obvious. Thanks again for looking into this!

Can confirm that running with jest can cause this error to throw:

tensor1d() requires values to be a flat/TypedArray

Hi Kyle,

So to confirm the error is happening as soon as you call tf.tensor1d([1, 2, 3])? That would be very strange since [1, 2, 3] has a length field, at which point we should NOT throw an error.

Can you share the stack trace and see exactly which lines in the code the error originates in? I haven't used jest, so something might be happening in that toolchain that confuses the library.

Here's the full test file with the stacktrace. This test is pulled straight from the Getting Started page

const tf = require("@tensorflow/tfjs");
require("@tensorflow/tfjs-node");

test("should be able to train a model", () => {
  const model = tf.sequential();
  model.add(tf.layers.dense({ units: 1, inputShape: [1] }));

  model.compile({ loss: "meanSquaredError", optimizer: "sgd" });

  const xs = tf.tensor2d([1, 2, 3, 4], [4, 1]);
  const ys = tf.tensor2d([1, 3, 5, 7], [4, 1]);

  return model.fit(xs, ys, { epochs: 10 }).then(() => {
    model.predict(tf.tensor2d([5], [1, 1])).print();
  });
});
tensor1d() requires values to be a flat/TypedArray
      at Object.tensor1d (node_modules/@tensorflow/tfjs-core/src/ops/tensor_ops.ts:123:11)
      at NodeJSKernelBackend.Object.<anonymous>.NodeJSKernelBackend.sum (node_modules/@tensorflow/tfjs-node/dist/
nodejs_kernel_backend.js:231:38)
      at environment_1.ENV.engine.runKernel.permutedX (node_modules/@tensorflow/tfjs-core/src/ops/reduction_ops.ts:124:28)
      at node_modules/@tensorflow/tfjs-core/src/engine.ts:166:22
      at Engine.Object.<anonymous>.Engine.scopedRun (node_modules/@tensorflow/tfjs-core/src/engine.ts:139:19)
      at Engine.Object.<anonymous>.Engine.runKernel (node_modules/@tensorflow/tfjs-core/src/engine.ts:162:10)
      at node_modules/@tensorflow/tfjs-core/src/ops/reduction_ops.ts:123:28
      at node_modules/@tensorflow/tfjs-core/src/engine.ts:416:21
      at node_modules/@tensorflow/tfjs-core/src/engine.ts:128:20
      at Engine.Object.<anonymous>.Engine.scopedRun (node_modules/@tensorflow/tfjs-core/src/engine.ts:139:19)

@dsmilkov Here's a repo that reproduces the bug:

https://github.com/smith-kyle/tfjs-jest-bug

Any update on this? My team may have to migrate our tests from jest to mocha if not 馃槄

I found a workaround - it seems the combination of jest with tfjs-node is where this bug manifests.
I have moved the require("@tensorflow/tfjs-node"); to code that does not run under jest and now the tests are passing and the app is running. Now, under jest, I get the warning ...Looks like you are running TensorFlow.js in Node.js. To speed things up dramatically, install our node backend... But I can live with that.

Automatically closing due to lack of recent activity. Please update the issue when new information becomes available, and we will reopen the issue. Thanks!

Workaround:

For me (only) an explicit call to tf.setBackend("cpu") fixed the issue.
I put it in the test after the imports.

@tensorflow/tfjs: 0.13.5
jest: 23.6.0
typescript: 3.2.1
node: v11.3.0

Same problem here.

  • If forcing MathBackendCPU ( the web cpu backend ) using tf.setBackend("cpu");
    => I have the @eram warning.

  • If forcing the NodeJSKernelBackend ( the node cpu backend ) using tf.setBackend("tensorflow");
    => I have the tensor1d() requires values to be a flat/TypedArray error similarly to @smith-kyle

This issue should be re opened i think , and maybe in the tjs-node repo

@tensorflow/tfjs-node: ^0.2.3
jest: 23.6.0
typescript: 3.0.3
node: v8.11.1

After some investigation i think i found something interesting:

When using the NodeJSKernelBackend (tf.setBackend("tensorflow"))

In tfjs-core/src/tensor_util_env.ts:34 in function inferShape(), if i change to use Array.isArray() instead of instanceof, the @smith-kyle error goes away and everything work perfectly.

while ( Array.isArray( firstElem ) || isTypedArray(firstElem)) {

I suspect that there is a problem with jest patching some builtin objects like Array thus invalidating tests using instanceof.

I think Array.isArray() should be enforced instead of instanceof

PR 1503 aim to fix that.

Nice find! Left some comments on your PR. Looks great!

Was this page helpful?
0 / 5 - 0 ratings