keras-team / keras

Deep Learning for humans
http://keras.io/
Apache License 2.0
62.14k stars 19.49k forks source link

Error when load combined mobile-net model #10428

Closed Slarker427 closed 3 years ago

Slarker427 commented 6 years ago

I used code below to combine 2 mobile-net model. After combine i save model as combined.hdf5. Keras version: 2.2.0 Using TensorFlow backend. TensorFlow version: 1.8.0

model_A = load_model('mobilenet_A.hdf5', custom_objects={'relu6': mobilenet.relu6})
model_B = load_model('mobilenet_B.hdf5', custom_objects={'relu6': mobilenet.relu6})
inputs = Input(shape=(224, 224, 3))

pred_A = model_A(inputs)
pred_B = model_B(inputs)

pred_average = keras.layers.Average()([pred_A, pred_B])

model_combined = Model(inputs=inputs, outputs=pred_average)
model_combined.save('combined_test.hdf5')
model_x = load_model('combined_test.hdf5', custom_objects={'relu6': mobilenet.relu6})

When i load saved model, i get error below:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-23-3df9104863a8> in <module>()
      1 model_x = load_model('combined_test.hdf5', 
----> 2                      custom_objects={'relu6': mobilenet.relu6})

~/virtualenvs/AILab/lib/python3.5/site-packages/keras/engine/saving.py in load_model(filepath, custom_objects, compile)
    262 
    263         # set weights
--> 264         load_weights_from_hdf5_group(f['model_weights'], model.layers)
    265 
    266         if compile:

~/virtualenvs/AILab/lib/python3.5/site-packages/keras/engine/saving.py in load_weights_from_hdf5_group(f, layers, reshape)
    914                                                        original_keras_version,
    915                                                        original_backend,
--> 916                                                        reshape=reshape)
    917         if len(weight_values) != len(symbolic_weights):
    918             raise ValueError('Layer #' + str(k) +

~/virtualenvs/AILab/lib/python3.5/site-packages/keras/engine/saving.py in preprocess_weights_for_loading(layer, weights, original_keras_version, original_backend, reshape)
    555         weights = convert_nested_time_distributed(weights)
    556     elif layer.__class__.__name__ in ['Model', 'Sequential']:
--> 557         weights = convert_nested_model(weights)
    558 
    559     if original_keras_version == '1':

~/virtualenvs/AILab/lib/python3.5/site-packages/keras/engine/saving.py in convert_nested_model(weights)
    543                     weights=weights[:num_weights],
    544                     original_keras_version=original_keras_version,
--> 545                     original_backend=original_backend))
    546                 weights = weights[num_weights:]
    547         return new_weights

~/virtualenvs/AILab/lib/python3.5/site-packages/keras/engine/saving.py in preprocess_weights_for_loading(layer, weights, original_keras_version, original_backend, reshape)
    555         weights = convert_nested_time_distributed(weights)
    556     elif layer.__class__.__name__ in ['Model', 'Sequential']:
--> 557         weights = convert_nested_model(weights)
    558 
    559     if original_keras_version == '1':

~/virtualenvs/AILab/lib/python3.5/site-packages/keras/engine/saving.py in convert_nested_model(weights)
    531                     weights=weights[:num_weights],
    532                     original_keras_version=original_keras_version,
--> 533                     original_backend=original_backend))
    534                 weights = weights[num_weights:]
    535 

~/virtualenvs/AILab/lib/python3.5/site-packages/keras/engine/saving.py in preprocess_weights_for_loading(layer, weights, original_keras_version, original_backend, reshape)
    673             weights[0] = np.reshape(weights[0], layer_weights_shape)
    674         elif layer_weights_shape != weights[0].shape:
--> 675             weights[0] = np.transpose(weights[0], (3, 2, 0, 1))
    676             if layer.__class__.__name__ == 'ConvLSTM2D':
    677                 weights[1] = np.transpose(weights[1], (3, 2, 0, 1))

~/virtualenvs/AILab/lib/python3.5/site-packages/numpy/core/fromnumeric.py in transpose(a, axes)
    548 
    549     """
--> 550     return _wrapfunc(a, 'transpose', axes)
    551 
    552 

~/virtualenvs/AILab/lib/python3.5/site-packages/numpy/core/fromnumeric.py in _wrapfunc(obj, method, *args, **kwds)
     55 def _wrapfunc(obj, method, *args, **kwds):
     56     try:
---> 57         return getattr(obj, method)(*args, **kwds)
     58 
     59     # An AttributeError occurs if the object does not have

ValueError: axes don't match array
anuar12 commented 6 years ago

Experiencing the same issue with exact same keras and tf versions. Using mobilenet backend in keras-yolo2 library. @Slarker427 Did you find any workarounds?

Traceback (most recent call last):
  File "predict.py", line 114, in <module>
    _main_(args)
  File "predict.py", line 66, in _main_
    yolo.load_weights(weights_path)
  File "/home/cheng/Desktop/repos/keras-yolo2/frontend.py", line 270, in load_weights
    self.model.load_weights(weight_path)
  File "/home/cheng/miniconda2/envs/tensorflow/lib/python2.7/site-packages/keras/engine/network.py", line 1180, in load_weights
    f, self.layers, reshape=reshape)
  File "/home/cheng/miniconda2/envs/tensorflow/lib/python2.7/site-packages/keras/engine/saving.py", line 916, in load_weights_from_hdf5_group
    reshape=reshape)
  File "/home/cheng/miniconda2/envs/tensorflow/lib/python2.7/site-packages/keras/engine/saving.py", line 557, in preprocess_weights_for_loading
    weights = convert_nested_model(weights)
  File "/home/cheng/miniconda2/envs/tensorflow/lib/python2.7/site-packages/keras/engine/saving.py", line 545, in convert_nested_model
    original_backend=original_backend))
  File "/home/cheng/miniconda2/envs/tensorflow/lib/python2.7/site-packages/keras/engine/saving.py", line 557, in preprocess_weights_for_loading
    weights = convert_nested_model(weights)
  File "/home/cheng/miniconda2/envs/tensorflow/lib/python2.7/site-packages/keras/engine/saving.py", line 533, in convert_nested_model
    original_backend=original_backend))
  File "/home/cheng/miniconda2/envs/tensorflow/lib/python2.7/site-packages/keras/engine/saving.py", line 675, in preprocess_weights_for_loading
    weights[0] = np.transpose(weights[0], (3, 2, 0, 1))
  File "/home/cheng/miniconda2/envs/tensorflow/lib/python2.7/site-packages/numpy/core/fromnumeric.py", line 575, in transpose
    return _wrapfunc(a, 'transpose', axes)
  File "/home/cheng/miniconda2/envs/tensorflow/lib/python2.7/site-packages/numpy/core/fromnumeric.py", line 52, in _wrapfunc
    return getattr(obj, method)(*args, **kwds)
ValueError: axes don't match array
Dref360 commented 6 years ago

Hey, I made a reproducible example. I think it has to do with naming. Keras doesn't check the naming scope before creating names. So if you create the same model twice, the name are duplicated.

import keras
import keras.backend as K
from keras import Input, Model
from keras.applications import mobilenet
from keras.engine.saving import load_model

inputs = Input(shape=(224, 224, 3))
with K.tf.name_scope('A'):
    model_A = mobilenet.MobileNet(input_tensor=inputs)
    pred_A = model_A.output

with K.tf.name_scope('B'):
    model_B = mobilenet.MobileNet(input_tensor=inputs)
    pred_B = model_B.output

with K.tf.name_scope('out'):
    pred_average = keras.layers.Average()([pred_A, pred_B])
    model_combined = Model(inputs=inputs, outputs=pred_average)
model_combined.save('combined_test.hdf5')
K.clear_session()
model_x = load_model('combined_test.hdf5', custom_objects={'relu6': mobilenet.relu6})

I'll label as bug for now.

NobleYd commented 6 years ago

Model summary:

Layer (type) Output Shape Param # Connected to
image1 (InputLayer) (None, 160, 140, 3) 0
image2 (InputLayer) (None, 160, 140, 3) 0
encoder (Sequential) (None, 128) 54533472 image1[0][0]
image2[0][0]
distance-calculator (Model) (None, 1) 0 encoder[1][0]
encoder[2][0]
classifier (Sequential) (None, 1) 2 distance-calculator[1][0]

Total params: 54,533,474 Trainable params: 54,472,930 Non-trainable params: 60,544

This is a simple summary of my model. I have the same question when use one model on two inputs to get two embeddings, then the distance-calculator model is just to calculate euclidean distance which has no trainable params. The final model(layer) is just a dense layer with sigmoid activation for judge whether the two input images are from one class. The errors as follow: Traceback (most recent call last): File "train-human-discriminator.py", line 4, in <module> start_train(train_conf) File "/mnt/python-workspace/human-body-recognition/src/utils/train_utils.py", line 135, in start_train final_model.load_weights(filepath=train_conf.model_path,by_name=True) File "/usr/lib64/python3.6/site-packages/keras/engine/network.py", line 1177, in load_weights reshape=reshape) File "/usr/lib64/python3.6/site-packages/keras/engine/saving.py", line 986, in load_weights_from_hdf5_group_by_name reshape=reshape) File "/usr/lib64/python3.6/site-packages/keras/engine/saving.py", line 557, in preprocess_weights_for_loading weights = convert_nested_model(weights) File "/usr/lib64/python3.6/site-packages/keras/engine/saving.py", line 545, in convert_nested_model original_backend=original_backend)) File "/usr/lib64/python3.6/site-packages/keras/engine/saving.py", line 557, in preprocess_weights_for_loading weights = convert_nested_model(weights) File "/usr/lib64/python3.6/site-packages/keras/engine/saving.py", line 533, in convert_nested_model original_backend=original_backend)) File "/usr/lib64/python3.6/site-packages/keras/engine/saving.py", line 675, in preprocess_weights_for_loading weights[0] = np.transpose(weights[0], (3, 2, 0, 1)) File "/usr/lib64/python3.6/site-packages/numpy/core/fromnumeric.py", line 575, in transpose return _wrapfunc(a, 'transpose', axes) File "/usr/lib64/python3.6/site-packages/numpy/core/fromnumeric.py", line 52, in _wrapfunc return getattr(obj, method)(*args, **kwds) ValueError: axes don't match array I really do not know how to fix this problem.

letilessa commented 6 years ago

Hi @anuar12, I'm having the same issue using mobilenet backend in keras-yolo2. Did you fix it?

pixelatedbrian commented 6 years ago

I had this same issue with a triplet loss model that had 3 of the same model concatenated and then used in the final model.

After reading @Dref360 's comment I had the idea of explicitly creating the model that I'm trying to load and then loading the weights into that model afterwards. This has been working as a workaround for me and I am now able to load a saved model successfully. Hope that this helps others with this issue.

letilessa commented 6 years ago

For me it was an issue with the versions of keras and tensorflow, using keras=2.1.5 and tf=1.8.0 fixed it.

andrey999333 commented 6 years ago

Same problem. keras = 2.2.2, tf = 1.10. Tried different things: Sequential model, functional API. Now will try to downgrade keras

SteveIb commented 6 years ago

anybody got a solution for this issue? I downgraded keras to 2.1.5 but still the same my tensorflow is 1.11

wwzhou commented 5 years ago

Had the same issue with TensorFlow 1.11.0, Keras 2.2.4 and MobileNet. A two-input one-output model. The first input goes through a MobileNet. The second a very simple structure before they are merged.

Traceback (most recent call last): File "v3x.py", line 427, in <module> model = load_model(fn) File "C:\Users\wzhou\AppData\Local\Continuum\Anaconda2\envs\tensorflow\lib\site-packages\keras\engine\saving.py", line 419, in load_model model = _deserialize_model(f, custom_objects, compile) File "C:\Users\wzhou\AppData\Local\Continuum\Anaconda2\envs\tensorflow\lib\site-packages\keras\engine\saving.py", line 274, in _deserialize_model reshape=False) File "C:\Users\wzhou\AppData\Local\Continuum\Anaconda2\envs\tensorflow\lib\site-packages\keras\engine\saving.py", line 682, in preprocess_weights_for_loading weights = convert_nested_model(weights) File "C:\Users\wzhou\AppData\Local\Continuum\Anaconda2\envs\tensorflow\lib\site-packages\keras\engine\saving.py", line 670, in convert_nested_model original_backend=original_backend)) File "C:\Users\wzhou\AppData\Local\Continuum\Anaconda2\envs\tensorflow\lib\site-packages\keras\engine\saving.py", line 682, in preprocess_weights_for_loading weights = convert_nested_model(weights) File "C:\Users\wzhou\AppData\Local\Continuum\Anaconda2\envs\tensorflow\lib\site-packages\keras\engine\saving.py", line 658, in convert_nested_model original_backend=original_backend)) File "C:\Users\wzhou\AppData\Local\Continuum\Anaconda2\envs\tensorflow\lib\site-packages\keras\engine\saving.py", line 801, in preprocess_weights_for_loading weights[0] = np.transpose(weights[0], (3, 2, 0, 1)) File "C:\Users\wzhou\AppData\Local\Continuum\Anaconda2\envs\tensorflow\lib\site-packages\numpy\core\fromnumeric.py", line 575, in transpose return _wrapfunc(a, 'transpose', axes) File "C:\Users\wzhou\AppData\Local\Continuum\Anaconda2\envs\tensorflow\lib\site-packages\numpy\core\fromnumeric.py", line 52, in _wrapfunc return getattr(obj, method)(*args, **kwds) ValueError: axes don't match array

Is this issue particular to MobileNet?

mingzhao03 commented 5 years ago

I believe this is related to #10784. When you have a nested model, there is a bug in loading trainable and untrainable weights (from BatchNorm layers?).

I just ran into this issue. I have a Siamese model that consists of two branch models and a head model. If I use a custom branch model that doesn't contain BatchNorm, saving and loading the model works fine. But if I use something like ResNet18, I can't load saved models because "axes don't match array".

ruinianxu commented 5 years ago

Join the model into one will solve this problem.

dr-askar commented 5 years ago

@ruinianxu how can i join the models in one ?

ruinianxu commented 5 years ago

@dr-askar You can refer to #358

vade commented 5 years ago

Hi all,

Using Keras 2.2.5 via google collab -

Im trying to work around a bug in tf.keras in 1.1.4 - by exporting my weights and loading them into a pure keras model, but it fails with:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-9-fb4f84d2f8a0> in <module>()
----> 1 model.load_weights("/tmp/"+ weights_name)

7 frames
/usr/local/lib/python3.6/dist-packages/keras/engine/saving.py in load_wrapper(*args, **kwargs)
    456                 os.remove(tmp_filepath)
    457             return res
--> 458         return load_function(*args, **kwargs)
    459 
    460     return load_wrapper

/usr/local/lib/python3.6/dist-packages/keras/engine/network.py in load_weights(self, filepath, by_name, skip_mismatch, reshape)
   1215             else:
   1216                 saving.load_weights_from_hdf5_group(
-> 1217                     f, self.layers, reshape=reshape)
   1218             if hasattr(f, 'close'):
   1219                 f.close()

/usr/local/lib/python3.6/dist-packages/keras/engine/saving.py in load_weights_from_hdf5_group(f, layers, reshape)
   1184                                                        original_keras_version,
   1185                                                        original_backend,
-> 1186                                                        reshape=reshape)
   1187         if len(weight_values) != len(symbolic_weights):
   1188             raise ValueError('Layer #' + str(k) +

/usr/local/lib/python3.6/dist-packages/keras/engine/saving.py in preprocess_weights_for_loading(layer, weights, original_keras_version, original_backend, reshape)
    821         weights = convert_nested_time_distributed(weights)
    822     elif layer.__class__.__name__ in ['Model', 'Sequential']:
--> 823         weights = convert_nested_model(weights)
    824 
    825     if original_keras_version == '1':

/usr/local/lib/python3.6/dist-packages/keras/engine/saving.py in convert_nested_model(weights)
    797                     weights=weights[:num_weights],
    798                     original_keras_version=original_keras_version,
--> 799                     original_backend=original_backend))
    800                 weights = weights[num_weights:]
    801 

/usr/local/lib/python3.6/dist-packages/keras/engine/saving.py in preprocess_weights_for_loading(layer, weights, original_keras_version, original_backend, reshape)
    940             weights[0] = np.reshape(weights[0], layer_weights_shape)
    941         elif layer_weights_shape != weights[0].shape:
--> 942             weights[0] = np.transpose(weights[0], (3, 2, 0, 1))
    943             if layer.__class__.__name__ == 'ConvLSTM2D':
    944                 weights[1] = np.transpose(weights[1], (3, 2, 0, 1))

/usr/local/lib/python3.6/dist-packages/numpy/core/fromnumeric.py in transpose(a, axes)
    637 
    638     """
--> 639     return _wrapfunc(a, 'transpose', axes)
    640 
    641 

/usr/local/lib/python3.6/dist-packages/numpy/core/fromnumeric.py in _wrapfunc(obj, method, *args, **kwds)
     54 def _wrapfunc(obj, method, *args, **kwds):
     55     try:
---> 56         return getattr(obj, method)(*args, **kwds)
     57 
     58     # An AttributeError occurs if the object does not have

ValueError: axes don't match array

My model is defined like so:

IMG_SIZE = 224

base_model = keras.applications.nasnet.NASNetMobile(input_shape=(IMG_SIZE, IMG_SIZE, 3), include_top=False, weights='imagenet')
base_model.trainable = False

print("Number of layers in the base model: ", len(base_model.layers))

num_labels = 229
output = keras.layers.Dense(num_labels, activation = 'sigmoid', name="cinemanet_output")

model = keras.Sequential([
  base_model,
  keras.layers.GlobalAveragePooling2D(),
  output])

Ive seen the note by @ruinianxu pointing to #358 - but its unclear to me since I have nested models, and the NASNetMobile architecture is obfuscated by using the sort of factory loader. Do I need to re-create the entire NASNetMobile architecture and define it by hand in to a flat sequence model to load these weights?

What is the path forward for me to successfully load my weights exported from a training session in tf 1.14 / using tf.keras model defined like so:


base_model = tf.keras.applications.NASNetMobile(input_shape=(IMG_SIZE, IMG_SIZE, 3),
                                               include_top=False,
                                               weights='imagenet')
base_model.trainable = False
output = tf.keras.layers.Dense(num_labels, activation = 'sigmoid', name="cinemanet_output")

model = tf.keras.Sequential([
  base_model,
  tf.keras.layers.GlobalAveragePooling2D(),
  output])
```?
vade commented 5 years ago

I tried 'unrolling' the layers from the NASNet base model and appending my own and passing a list of layers to Sequence() like so:

base_model = keras.applications.nasnet.NASNetMobile(input_shape=(IMG_SIZE, IMG_SIZE, 3), include_top=False, weights='imagenet')
base_model.trainable = False

print("Number of layers in the base model: ", len(base_model.layers))

num_labels = 229
output = keras.layers.Dense(num_labels, activation = 'sigmoid', name="cinemanet_output")

#unroll our layers so we dont nest our model
layers = base_model.layers
layers.append(keras.layers.GlobalAveragePooling2D())
layers.append(output)

model = keras.Sequential(layers)

But I got:

ValueError                                Traceback (most recent call last)
<ipython-input-11-ff0a0c087554> in <module>()
     14 layers.append(output)
     15 
---> 16 model = keras.Sequential(layers)
     17 model.summary()
     18 

3 frames
/usr/local/lib/python3.6/dist-packages/keras/engine/base_layer.py in assert_input_compatibility(self, inputs)
    344                                 str(axis) + ' of input shape to have '
    345                                 'value ' + str(value) +
--> 346                                 ' but got shape ' + str(x_shape))
    347             # Check shape.
    348             if spec.shape is not None:

ValueError: Input 0 is incompatible with layer separable_conv_1_reduction_right1_stem_1: expected axis -1 of input shape to have value 32 but got shape (None, 59, 59, 11)
vade commented 5 years ago

Also, ive tried @letilessa suggestion of rolling back Keras and TF versions, that did not work either, It appears that the number of layers is different (749 vs 769) for the base model, which I suspect is using layers not implemented in TF 1.8 / Keras 2.1.5 - but this is speculation.

!pip install keras==2.1.5
!pip install tensorflow==1.8.0
chaudharyachint08 commented 5 years ago

Resolved same issue by saving individual components seprately & loading weights back. You can save in two parts, architecture as JSON file, & model as h5py.

During loading you can load entire sub-models (both JSON & Weights), for main architecture can use layers then