transcranial / keras-js

Run Keras models in the browser, with GPU support using WebGL
https://transcranial.github.io/keras-js
MIT License
4.96k stars 501 forks source link

Variable-size input layers appear to be unsupported #25

Open madebyollin opened 7 years ago

madebyollin commented 7 years ago

Keras supports variable-size input layers; they're specified as follows (where the two "None"s would typically be width and height):

inputlayer = Input(shape=(None, None, 4))

This feature is very useful for certain applications (e.g. entirely convolutional networks for image processing). This input layer is then encoded to JSON by encoder.py as:

...
    "config": {
        "batch_input_shape": [null, null, null, 4],
        "input_dtype": "float32",
        "sparse": false,
        "name": "input_1"
    },
...

However, trying to use this model in keras.js results in a "Specified shape incompatible with data." error from checkShape when trying to predict (since shape.reduce((a, b) => a * b, 1) is 0 if shape contains a null). This suggests that variable-size input layers are not yet supported as part of Keras.js.

I'm not sure if this is a planned feature, unplanned feature, or already implemented (and I just missed a configuration step somewhere), so feel free to label/delete this issue as appropriate. Thanks for the amazing library!

transcranial commented 7 years ago

Yep, good catch. It isn't supported currently, but definitely should be.

madebyollin commented 7 years ago

Got it! Not to impose, but do you happen to have an idea for how difficult something like this would be? I was thinking of trying to hack together a tile-splitting-and-combining engine or something for the tiny project I'm using this in [https://github.com/madebyollin/hintbot/] in order to get things working for my particular application, but if making arbitrary-size layers work in keras.js is just a matter of translating some portion of the keras python code into JS, I might be able to patch a copy of the library directly rather than trying to build stuff outside of it.

I'll try to look into it myself this weekend. Thanks! Edit: I did some initial poking around but not sure how to implement it yet. I'll keep looking once winter break comes around.

LRonHubs commented 7 years ago

Have you found a reason this would be impossible or especially difficult in this codebase? I'm hoping to just try and change the shape of the InputLayer given for Sequential or will it be more difficult than that? I think it should be possible even for larger data sets, especially for prediction since it's less computationally intensive.

Gor97 commented 7 years ago

@transcranial is there any solution for variable-sized input layers? If not, will it be supported in KerasJS?

mayuanyang commented 6 years ago

I get into the same problem, any update on this one? work around?

kmader commented 6 years ago

I have done a temporary workout around where you can change the config of the first layer (or any input layers, you have to rename layers as well with tensorflow since they names are already used by the original model)

base_model = load_model('variable_sized_model.h5')
s_config = base_model.get_config()
model_idx = np.random.choice(500)
name_mapping = {v['name']: '%04d_%04d' % (model_idx, c_idx) for c_idx,v in enumerate(s_config['layers'])}
raw_str = json.dumps(s_config)
for k,v in name_mapping.items():
    raw_str = raw_str.replace('"{}"'.format(k), '"{}"'.format(v))
n_config = json.loads(raw_str)
n_config['layers'][0]['config']['batch_input_shape'] = (None, 512, 512, 3)

fix_model = Model.from_config(n_config)
fix_model.load_weights('variable_sized_model.h5')
fix_model.save('clean_fixed_model.h5')