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

[tfjs-react-native] AsyncStorageIO fails to save big GraphModels: "Error: Exception in HostFunction: Malformed calls from JS: field sizes are different" #2773

Closed
enpinzolas opened this issue Feb 19, 2020 · 6 comments

Comments

@enpinzolas
Copy link

To get help from the community, we encourage using Stack Overflow and the tensorflow.js tag.

TensorFlow.js version

All the relevant dependencies:

@react-native-community/async-storage: 1.8.0,
@tensorflow/tfjs: 1.5.2,
@tensorflow/tfjs-converter: 1.5.2,
@tensorflow/tfjs-core: 1.5.2,
@tensorflow/tfjs-react-native: 0.2.3,
expo-camera: 8.0.0,
expo-gl: 7.0.0,
expo-image-manipulator: 8.0.0,
react: 16.9.0,
react-native: 0.61.5,
react-native-fs: 2.16.4,
react-native-svg: 11.0.1,
react-native-unimodules: 0.7.0

Browser version

React native.

Describe the problem or feature request

After loading a big model via loadGraphModel through http (the model is served locally but it should not be a problem once loaded), I try to save it in local storage using an AsyncStorageIO handler it fails, showing the following error:

Error: Failed to save model 'mymodel' to AsyncStorage.
            Error info Error: Exception in HostFunction: Malformed calls from JS: field sizes are different.

[[20,34],[5,0],[[296,2000,1582122742037,false]],211]
save$@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:145067:32
tryCatch@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:25666:23
invoke@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:25841:32
tryCatch@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:25666:23
invoke@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:25742:30
http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:25772:19
tryCallTwo@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:27030:9
doResolve@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:27194:25
Promise@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:27053:14
callInvokeWithMethodAndArg@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:25771:29
enqueue@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:25776:157
async@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:25792:69
http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:174620:39
step@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:174457:25
http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:174359:73
tryCallTwo@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:27030:9
doResolve@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:27194:25
Promise@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:27053:14
http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:174336:36
http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:193155:41
step@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:192995:25
http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:192897:73
tryCallTwo@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:27030:9
doResolve@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:27194:25
Promise@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:27053:14
http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:192874:36
componentDidMount$@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:192559:66
tryCatch@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:25666:23
invoke@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:25841:32
tryCatch@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:25666:23
invoke@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:25742:30
http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:25752:21
tryCallOne@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:27021:16
http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:27122:27
_callTimer@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:30576:17
_callImmediatesPass@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:30612:19
callImmediates@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:30831:33
callImmediates@[native code]
__callImmediates@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:2619:35
http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:2396:34
__guard@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:2602:15
flushedQueue@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:2395:21
flushedQueue@[native code]
callFunctionReturnFlushedQueue@[native code]

Worth noting that the original SaveModel weights were 200MB, which is way bigger than any example at hand, and since the conversion shards them, the model has 49 shards of 4MB each, besides the model.json.

Code to reproduce the bug / link to feature request

import * as tfconv from '@tensorflow/tfjs-converter';
import * as tf from '@tensorflow/tfjs-core';
import {asyncStorageIO} from '@tensorflow/tfjs-react-native';

const model = await tfconv.loadGraphModel('http://xxx.xxx.xxx.xxx:xxxx/model.json')
await this.model.save(asyncStorageIO('mymodel')); // <- This fails.
@rthadur rthadur added comp:react-native type:support user support questions P1 type:bug Something isn't working and removed type:support user support questions labels Feb 19, 2020
@tafsiri
Copy link
Contributor

tafsiri commented Feb 20, 2020

This might be related to this issue facebook/react-native#23835. One potential cause is a (seemingly) unserializable values like NaN or Infinity/-Infinity in your weights.

Could you check your weights to see if you have any of these values? If you load your model in a browser you can use https://js.tensorflow.org/api_vis/1.4.0/#show.layer to look at counts for these for each layer (you can also just count them directly).

@enpinzolas
Copy link
Author

Thank you for checking in!

Given that my model is a GraphModel, it lacks the layer property, and I am unable to visualize it using tfjs-vis since the method you linked uses layers, and the summary one accepts only LayerModels. However, I manually checked the weights using the model.weights property. Here is the snippet run just after loading it:

var model = await tfconv.loadGraphModel(this.modelPath);
var result = Object.keys(model.model.weights).map(function(key) {
  return  model.model.weights[key][0].dataSync().map(value => ( value == Infinity || value == -Infinity || value == NaN ));
}); // <-- this takes a long time since the weights are in total 200MB
result.map(a=>(a.length)).reduce((a, b) => (a+b)) // 50537445
result.map(val => (val.reduce((a, b) => (a+b)))).reduce((a, b) => (a+b)) // 0

My apologies if I made the comparisons wrong, I believe that since all the weights are ints and floats stored in Int32Arrays and Float32Arrays a simple comparison with NaN, Infinity or -Infinity should suffice.

By the way, the loaded model predicts the expected results both in tfjs (browser and RN) and in python, so I'm not sure if the issue is in the model.

@tafsiri
Copy link
Contributor

tafsiri commented Feb 21, 2020

One correction, since NaN === NaN is false, you should use isNaN(value) to test for NaN. (You can also simplify your code a bit Array.filter

The fact that it is predicting correctly doesn't completely rule out NaNs or Infinities. So just trying to pin down what might cause the serialization issue.

Also what OS/Platform are you running this on?

@enpinzolas
Copy link
Author

enpinzolas commented Feb 24, 2020

Thanks for the correction and suggestion, I checked for NaNs too and there's none.

var result = Object.keys(model.model.weights).filter(function(key) {
  return  model.model.weights[key][0].dataSync().filter(value => isNaN(value)).length > 0;
});
// Array []

I'm developing it on a linux machine (ubuntu), and running it on an android device, with android 10.

@tafsiri
Copy link
Contributor

tafsiri commented Feb 25, 2020

Though the error produced looks strange for this. It looks like on Android there is a default 6MB limit for AsyncStorage.

This asyncStorage PR suggests that it is configurable in a gradle config. Configuration is documented here.

Try that and see if it helps.

@rthadur
Copy link
Contributor

rthadur commented Mar 12, 2020

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 Mar 12, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants