keras-yolo3 icon indicating copy to clipboard operation
keras-yolo3 copied to clipboard

Layer shape mismatch when loading pretrained weight when using Keras included in Tensorflow

Open Nakeuh opened this issue 5 years ago • 1 comments

I wanted to load YOLOv3 model and retrain it using provided pre-trained model.

I got stuck for a while on this error : ValueError: Layer #1 (named "conv2d_1"), weight <tf.Variable 'conv2d_1/kernel:0' shape=(3, 3, 32, 64) dtype=float32> has shape (3, 3, 32, 64), but the saved weight has shape (32, 3, 3, 3). It is actually an easy to fix error, so I share what I learnt here so nobody have to get stuck on it like me :) .

Here is how to reproduce the error :

git clone https://github.com/qqwweee/keras-yolo3.git
cd keras-yolo3
wget https://pjreddie.com/media/files/yolov3.weights
python convert.py yolov3.cfg yolov3.weights model_data/yolo.h5

I created the file pretrain-model-minimal.py, which contains a minimal version of train.py to reproduce my error.

from tensorflow.python.keras import backend as K
from tensorflow.python.keras.layers import Input

from yolo3.model import yolo_body
from train import get_classes, get_anchors

def _main():
	classes_path = "model_data/coco_classes.txt"
	pretrained_weights = "model_data/yolo.h5"
	anchors_path = "model_data/yolo_anchors.txt"

	class_names = get_classes(classes_path) # Reuse the function from train.py
	num_classes = len(class_names)
	anchors = get_anchors(anchors_path) # Reuse the function from train.py

	create_model(anchors, num_classes,weights_path=pretrained_weights)

def create_model(anchors, num_classes, weights_path='model_data/yolo_weights.h5'):
	'''create the training model'''
	K.clear_session()  # get a new session
	image_input = Input(shape=(None, None, 3))
	num_anchors = len(anchors)

	model_body = yolo_body(image_input, num_anchors // 3, num_classes)
	print('Create YOLOv3 model with {} anchors and {} classes.'.format(num_anchors, num_classes))

	model_body.load_weights(weights_path, by_name=True)
	print('Load weights {}.'.format(weights_path))

if __name__ == '__main__':
	_main()

When running this code, the line model_body.load_weights throw the error about layer shape mismatch.

You might have noticed from the imports that I use the Keras included in Tensorflow (I also modified the imports on the other files). And this is the source of the error. When running the exact same code using Keras out of Tensorflow, everything work well.

I hope it will help some people.

Have a nice day !

Nakeuh avatar Apr 19 '19 13:04 Nakeuh

I have solved the kind of issue as follows. Hope the solution would be helpful.

1. Delete "by_name=True"

# -model.load_weights(weights_path, by_name=True)
model.load_weights(weights_path)

2. Change the number of class

While it throws another throwing "ValueError: Shapes (1536, 1000) and (1536, 1001) are incompatible", I change num_classes from 1000 to 1001.

# -num_classes = 1000
num_classes = 1001

And then it shows the correct model summary.

mikechen66 avatar Sep 17 '20 09:09 mikechen66