tensorflow / tfjs

A WebGL accelerated JavaScript library for training and deploying ML models.
https://js.tensorflow.org
Apache License 2.0
18.52k stars 1.94k forks source link

Error: layer: improper config format when converting SavedModel #3487

Closed MyJumperBroke23 closed 4 years ago

MyJumperBroke23 commented 4 years ago

TensorFlow.js version

Keras: 2.3.1 Tensorflow: 2.20 Tensorflow.js: 1.7.2 tfjs-react-native: ^0.2.3 expo: ~37.0.3 react: ^16.9.0

Describe the problem or feature request

I'm trying to run a tfjs model in react native, but when I run it, I get

Error: layer: improper config format

and then what seems to be the entirety of my model.json starting from input. The SavedModel loads into python fine, but the error occurs after conversion.

One thing to note is that my SavedModel uses a custom loss function, so whilst loading it in I have to pass it in as a custom object.

Code to reproduce the bug / link to feature request

Link to model(h5): https://www.dropbox.com/s/6ginejkhna1sic8/unet_70.h5?dl=0 Link to model(Saved): https://www.dropbox.com/s/5pmogdeuwehblbz/saved-model.zip?dl=0 Link to Tensorflowjs Model: https://www.dropbox.com/s/1aewj9j4r489fcu/tfjs_model2.zip?dl=0

Command used to convert the SavedModel to tfjs:

tensorflowjs_converter --input_format=tf_saved_model --output_format=tfjs_graph_model --quantization_bytes=1 --weight_shard_size_bytes=9999999999999 ~/PycharmProjects/TrueSky/models/saved-model ~/PycharmProjects/TrueSky/models/tfjs_model2

Code used to convert h5 file to SavedModel:

import segmentation_models as sm
from keras import backend as K
from tensorflow.keras.models import load_model
from keras import layers
import tensorflow.keras.layers as KL
import tensorflow.keras.activations as tfa
from tensorflow import keras
import tensorflow as tf

def swish(x):
    return (K.sigmoid(x) * x)

path_to_model = "models/unet_70.h5"
loss = sm.losses.binary_focal_dice_loss
model = load_model(path_to_model, custom_objects={'binary_focal_loss_plus_dice_loss': loss, 'FixedDropout': KL.Dropout, 'swish': swish})

model.save('models/saved-model')

Code used to test model in tfjs:

import React, { Component } from 'react';
import { Camera } from 'expo-camera';
import { cameraWithTensors, fetch, decodeJpeg, bundleResourceIO } from '@tensorflow/tfjs-react-native';
import { View, Text, StyleSheet, Platform } from 'react-native'
import * as Permissions from 'expo-permissions';
import { CameraStyle } from './styles'
import * as tf from '@tensorflow/tfjs';
import { any } from '@tensorflow/tfjs';
//import Swish from '/Users/alex/Documents/GitHub/TrueSkyApp/src/components/swish.js'

class Swish extends tf.layers.Layer {
  constructor(config) {
    super(config);
    this.alpha = config.alpha;
  }

  call(input) {
    return tf.tidy(() => {
      const x = input[0]; //tf.getExactlyOneTensor(input);
      return tf.sigmoid(x.mul(this.alpha)).mul(x);
    });
  }

  computeOutputShape(inputShape){
    return inputShape;
  }

  static get className() {
  return 'swish';
  }
}
tf.serialization.registerClass(Swish)

class FixedDropout extends tf.layers.Layer {
  constructor(config) {
    super(config);
    this.alpha = config.alpha;
  }

  call(input) {
    return input;
  }

  computeOutputShape(inputShape){
    return inputShape;
  }

  static get className() {
  return 'FixedDropout';
  }
}
tf.serialization.registerClass(FixedDropout)

const modelJson = require('/Users/alex/Documents/GitHub/TrueSkyApp/assets/model/model.json');
const modelWeights = require('/Users/alex/Documents/GitHub/TrueSkyApp/assets/model/group1-shard1of1.bin');

class TFtest extends Component {
  state = {
    isModelReady: false
  }

  async componentDidMount() {
    await tf.ready()
    this.model = await tf.loadLayersModel(bundleResourceIO(modelJson, modelWeights));
    this.setState({
      isModelReady: true
    })

    //Output in Expo console
    console.log(this.state.isModelReady)
    const inputTensor = tf.randomNormal([1,320,320,3])
    const prediction = await this.model.predict(inputTensor)
    console.log(prediction)

  }

  render() {
    return (
      <View style={styles.container}>
        <Text>Model ready? {this.state.isModelReady ? <Text>Yes</Text> : ''}</Text>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center'
  }
})

export default TFtest;

Verification that the SavedModel loads correctly

MyJumperBroke23 commented 4 years ago

Just realised I was doing LoadLayersModel instead of LoadGraphModel