teachablemachine-community icon indicating copy to clipboard operation
teachablemachine-community copied to clipboard

[BUG]: Teachable Machine model.json file not compatible with Tenserflow/Keras Expectations

Open MarkKocherovsky opened this issue 3 years ago • 1 comments

Describe the bug

To Reproduce Steps to reproduce the behavior:

  1. download model.json file from a teachable machine model

  2. read it in as a string in python with the following code: with open(modelPath) as f: lines=f.readLines() modelJson = ''.join(lines) model = models.model_from_json(modelJson)

  3. Run the program, receive a ValueError: Improper config format error

Reason for Bug

This occurs because the JSON given by teachable machine is not in the same format as that expected by TF. Tensorflow expects the following format (created by saving a tf model saved as a .h5 as a JSON): { "class_name": "Sequential", "config": { "name": "sequential", "layers": [ { "class_name": "InputLayer", "config": { "batch_input_shape": [ null, 256, 256, 1 ], "dtype": "float32", "sparse": false, "ragged": false, "name": "rescaling_input" } }, { "class_name": "Rescaling", "config": { "name": "rescaling", "trainable": true, "dtype": "float32", "scale": 0.00392156862745098, "offset": 0 } }, { "class_name": "Conv2D", "config": { "name": "conv2d", "trainable": true, "dtype": "float32", "filters": 32, "kernel_size": [ 3, 3 ], "strides": [ 1, 1 ], "padding": "valid", "data_format": "channels_last", "dilation_rate": [ 1, 1 ], "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": { "class_name": "GlorotUniform", "config": { "seed": null } }, "bias_initializer": { "class_name": "Zeros", "config": {} }, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null } }, { "class_name": "MaxPooling2D", "config": { "name": "max_pooling2d", "trainable": true, "dtype": "float32", "pool_size": [ 2, 2 ], "padding": "valid", "strides": [ 2, 2 ], "data_format": "channels_last" } }, { "class_name": "Conv2D", "config": { "name": "conv2d_1", "trainable": true, "dtype": "float32", "filters": 32, "kernel_size": [ 3, 3 ], "strides": [ 1, 1 ], "padding": "valid", "data_format": "channels_last", "dilation_rate": [ 1, 1 ], "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": { "class_name": "GlorotUniform", "config": { "seed": null } }, "bias_initializer": { "class_name": "Zeros", "config": {} }, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null } }, { "class_name": "MaxPooling2D", "config": { "name": "max_pooling2d_1", "trainable": true, "dtype": "float32", "pool_size": [ 2, 2 ], "padding": "valid", "strides": [ 2, 2 ], "data_format": "channels_last" } }, { "class_name": "Conv2D", "config": { "name": "conv2d_2", "trainable": true, "dtype": "float32", "filters": 32, "kernel_size": [ 3, 3 ], "strides": [ 1, 1 ], "padding": "valid", "data_format": "channels_last", "dilation_rate": [ 1, 1 ], "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": { "class_name": "GlorotUniform", "config": { "seed": null } }, "bias_initializer": { "class_name": "Zeros", "config": {} }, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null } }, { "class_name": "MaxPooling2D", "config": { "name": "max_pooling2d_2", "trainable": true, "dtype": "float32", "pool_size": [ 2, 2 ], "padding": "valid", "strides": [ 2, 2 ], "data_format": "channels_last" } }, { "class_name": "Flatten", "config": { "name": "flatten", "trainable": true, "dtype": "float32", "data_format": "channels_last" } }, { "class_name": "Dense", "config": { "name": "dense", "trainable": true, "dtype": "float32", "units": 128, "activation": "relu", "use_bias": true, "kernel_initializer": { "class_name": "GlorotUniform", "config": { "seed": null } }, "bias_initializer": { "class_name": "Zeros", "config": {} }, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null } }, { "class_name": "Dense", "config": { "name": "dense_1", "trainable": true, "dtype": "float32", "units": 4, "activation": "softmax", "use_bias": true, "kernel_initializer": { "class_name": "GlorotUniform", "config": { "seed": null } }, "bias_initializer": { "class_name": "Zeros", "config": {} }, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null } } ] }, "keras_version": "2.6.0", "backend": "tensorflow" }

However, teachable machine has the following format, seen here: { "modelTopology": { "class_name": "Sequential", "config": { "name": "sequential_2", "layers": [ { "class_name": "Dense", "config": { "units": 100, "activation": "relu", "use_bias": true, "kernel_initializer": { "class_name": "VarianceScaling", "config": { "scale": 1, "mode": "fan_in", "distribution": "normal", "seed": null } }, "bias_initializer": { "class_name": "Zeros", "config": {} }, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null, "name": "dense_Dense1", "trainable": true, "batch_input_shape": [ null, 14739 ], "dtype": "float32" } }, { "class_name": "Dropout", "config": { "rate": 0.5, "noise_shape": null, "seed": null, "name": "dropout_Dropout1", "trainable": true } }, { "class_name": "Dense", "config": { "units": 4, "activation": "softmax", "use_bias": false, "kernel_initializer": { "class_name": "VarianceScaling", "config": { "scale": 1, "mode": "fan_in", "distribution": "normal", "seed": null } }, "bias_initializer": { "class_name": "Zeros", "config": {} }, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null, "name": "dense_Dense2", "trainable": true } } ] }, "keras_version": "tfjs-layers 1.3.1", "backend": "tensor_flow.js" }, "format": "layers-model", "generatedBy": "TensorFlow.js tfjs-layers v1.3.1", "convertedBy": null, "weightsManifest": [ { "paths": [ "./model.weights.bin" ], "weights": [ { "name": "dense_Dense1/kernel", "shape": [ 14739, 100 ], "dtype": "float32" }, { "name": "dense_Dense1/bias", "shape": [ 100 ], "dtype": "float32" }, { "name": "dense_Dense2/kernel", "shape": [ 100, 4 ], "dtype": "float32" } ] } ] } The modelTopology section and the data at the bottom is unecessary.

Work Around

We found a work around by simply pruning the model.json file given by TM to the format given in the first example. However, our team believes this to be a problem that should be fixed.

Desktop (please complete the following information):

  • OS: Ubuntu 20.04

MarkKocherovsky avatar Oct 20 '21 20:10 MarkKocherovsky

I'm having the same issue. How do I get the weights in a h5 format?

mukulpatnaik avatar Dec 02 '22 03:12 mukulpatnaik