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

[Model] error loading weights - bug fix #76

Open ghost opened 7 years ago

ghost commented 7 years ago

When loading a network with PReLU activations, KerasJS throws an error:

[Model] error loading weights

I have found the source of this error. In this part of the KerasJS code: } else u = "TimeDistributed" === e ? i.layer.params.map(function(t) { return n.name + "/" + t }) : i.params.map(function(t) { return n.name + "/" + t /* <----- HERE */ }); if (u && u.length) { var f = u.map(function(t) { var e = (0, _.default)(o.data.metadata, function(e) { return new RegExp("^" + t).test(e.weight_name) }); if (!e) throw new Error("[Model] error loading weights.");

The library is not finding the layer it needs because t is 'alphas' when it should be just 'alpha'. I don't know where the names of the layer properties are defined, so I won't be submitting a pull request, but this naming inconsistency should be easy to fix.

As for me, I fixed it adding an if statement in there, but that is no permanent fix.

ghost commented 7 years ago

The code I attached was for the compiled version of Keras. In the master branch, the equivalent code would be:

weightNames = layer.layer.params.map(param => '${layerConfig.name}/${param}') } else { weightNames = layer.params.map(param => '${layerConfig.name}/${param}') /*<---HERE*/ } if (w

Line 328 of Model.js, where param should be 'alpha' instead of 'alphas'.

red42 commented 7 years ago

I'm getting the same error on the same line, but for relu activations, even building keras.js from repo. I'm not quite sure what I can do to pinpoint the error.

The model was trained on Keras 2.0.5 and Tensorflow 1.1.0. Here's my model summary:

Layer (type)                 Output Shape              Param #   
conv2d_1 (Conv2D)            (None, 32, 127, 1)        12992     
max_pooling2d_1 (MaxPooling2 (None, 16, 63, 1)         0         
conv2d_2 (Conv2D)            (None, 14, 61, 64)        640       
max_pooling2d_2 (MaxPooling2 (None, 7, 30, 64)         0         
conv2d_3 (Conv2D)            (None, 5, 28, 128)        73856     
max_pooling2d_3 (MaxPooling2 (None, 2, 14, 128)        0         
flatten_1 (Flatten)          (None, 3584)              0         
dense_1 (Dense)              (None, 64)                229440    
dense_2 (Dense)              (None, 144)               9360      
kmader commented 6 years ago

I have the same error with Keras 2.1.3 and some ugly hacking seems to show that the generated weight names do not match up to the actual names of the weights

The weight names are made by using the LayerConfig while the names in the model can be different

For the first BatchNormalization layer in my model, for example,

weightNames = ["prebn_elbow/gamma", "prebn_elbow/beta", "prebn_elbow/moving_mean", "prebn_elbow/moving_variance"]

while the actual names in the model are

prebn_elbow_6/gamma:0
prebn_elbow_6/beta:0
...

so the regular expression does not match

kmader commented 6 years ago

the name issue can be fixed by renaming all of the layers (reloading weights) and then saving

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)

fix_model = Model.from_config(n_config)
fix_model.load_weights('variable_sized_model.h5')
fix_model.save('clean_fixed_model.h5')
rychuelektryk commented 6 years ago

I've also encoutered this problem with layer names. It'd be awesome if keras.js author could fix this issue.

@kmader thanks for workaround!