Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem when running TF.js with Jest (unit testing) #545

Closed
DABH opened this issue Jul 24, 2018 · 13 comments
Closed

Problem when running TF.js with Jest (unit testing) #545

DABH opened this issue Jul 24, 2018 · 13 comments
Assignees

Comments

@DABH
Copy link

DABH commented Jul 24, 2018

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());
@dsmilkov
Copy link
Contributor

dsmilkov commented Jul 25, 2018

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(...)

@DABH
Copy link
Author

DABH commented Jul 25, 2018

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!

@smith-kyle
Copy link

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

tensor1d() requires values to be a flat/TypedArray

@dsmilkov
Copy link
Contributor

dsmilkov commented Aug 10, 2018

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.

@smith-kyle
Copy link

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)

@smith-kyle
Copy link

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

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

@smith-kyle
Copy link

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

@eram
Copy link

eram commented Sep 27, 2018

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.

@dsmilkov dsmilkov changed the title Issues with tf.sum() and tf.squaredDifference() Problem when running TF.js with Jest (unit testing framework) Oct 24, 2018
@dsmilkov dsmilkov changed the title Problem when running TF.js with Jest (unit testing framework) Problem when running TF.js with Jest (unit testing) Oct 24, 2018
@rthadur
Copy link
Contributor

rthadur commented Nov 28, 2018

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

@rthadur rthadur closed this as completed Nov 28, 2018
@gmatt
Copy link

gmatt commented Dec 3, 2018

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

@ClementVidal
Copy link
Contributor

ClementVidal commented Jan 23, 2019

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

@ClementVidal
Copy link
Contributor

ClementVidal commented Jan 23, 2019

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.

@dsmilkov
Copy link
Contributor

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

dsmilkov pushed a commit to tensorflow/tfjs-core that referenced this issue Jan 24, 2019
BUG

Fixes tensorflow/tfjs#545.

When testing TensorFlow models using jest and **tfjs-node**, errors like the one reported by [tfjs issue 545](tensorflow/tfjs#545) occurs.

I think they comes from the fact that jest patch several default objects like Array which make subsequent call to instanceof fail.

Probably because the Array object available at "creation time" is not the same that the one used at "test time".

Note that **this fix actually resolve the `tensor1d() requires values to be a flat/TypedArray` error** of me and @smith-kyle in [tfjs issue 545](tensorflow/tfjs#545)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants