解决yolo改yolo-tiny中的某些问题
使用的是这个著名的版本:
https://github.com/qqwweee/keras-yolo3
修改成为tiny版本参考了这篇博客:
https://www.jianshu.com/p/d76adef49293
修改的时候看到一个博主说
filters实际上等于
num/3*(classes+5)
而不是大家认同的
3*(classes+5)
乌干达代码能力稍微看了下代码之后,认为后面这个大家公认的公式是正确的,在train.py文件中,关于使用yolo模型时候有这样的计算:
def create_model(input_shape, anchors, num_classes, load_pretrained=True, freeze_body=2,
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))
h, w = input_shape
num_anchors = len(anchors)
y_true = [Input(shape=(h//{0:32, 1:16, 2:8}[l], w//{0:32, 1:16, 2:8}[l], \
num_anchors//3, num_classes+5)) for l in range(3)]
model_body = yolo_body(image_input, num_anchors//3, num_classes)
print('Create YOLOv3 model with {} anchors and {} classes.'.format(num_anchors, num_classes))
而在使用tiny模型时,这个计算是这样的:
def create_tiny_model(input_shape, anchors, num_classes, load_pretrained=True, freeze_body=2,
weights_path='model_data/tiny_yolo_weights.h5'):
'''create the training model, for Tiny YOLOv3'''
K.clear_session() # get a new session
image_input = Input(shape=(None, None, 3))
h, w = input_shape
num_anchors = len(anchors)
y_true = [Input(shape=(h//{0:32, 1:16}[l], w//{0:32, 1:16}[l], \
num_anchors//2, num_classes+5)) for l in range(2)]
model_body = tiny_yolo_body(image_input, num_anchors//2, num_classes)
print('Create Tiny YOLOv3 model with {} anchors and {} classes.'.format(num_anchors, num_classes))
而在yolo中,num_anchors=9,tiny中num_anchors=6,所以认为是原来大家公认的
3*(classes+5)
是正确的。
然后说说改成tiny版本时某些报错的问题。
ValueError: You are trying to load a weight file containing 24 layers into a model with 147 layers.
报错全文是这样的:
Traceback (most recent call last):
File "yolo_video.py", line 73, in <module>
detect_img(YOLO(**vars(FLAGS)))
File "E:\testshengduxuexi\yolotiny\keras-yolo3-master\yolo.py", line 45, in __init__
self.boxes, self.scores, self.classes = self.generate()
File "E:\testshengduxuexi\yolotiny\keras-yolo3-master\yolo.py", line 75, in generate
self.yolo_model.load_weights(self.model_path)
File "F:\python\Anaconda\lib\site-packages\keras\engine\topology.py", line 2656, in load_weights
f, self.layers, reshape=reshape)
File "F:\python\Anaconda\lib\site-packages\keras\engine\topology.py", line 3354, in load_weights_from_hdf5_group
str(len(filtered_layers)) + ' layers.')
ValueError: You are trying to load a weight file containing 24 layers into a model with 147 layers.
全部的重点其实在这一句:
self.yolo_model.load_weights(self.model_path)
层数不匹配,查阅资料以及查看self.yolo_model.load_weights的源码得知,修改成这样可以解决问题:
self.yolo_model.load_weights(self.model_path, by_name=True)
但是再次报错了这样的问题:
ValueError: Layer #42 (named "conv2d_10") expects 1 weight(s), but the saved weights have 2 element(s).
怀疑是.h5文件出了问题或者是卷积层参数被改变,通过查看.h5文件该层,认定没有出什么问题。
从头查看代码,在train.py文件中看到了这样一句话:
model_body.load_weights(weights_path, by_name=True, skip_mismatch=True)
也应用了model_body.load_weights这个函数,为什么没有报错?
于是把yolo.py的这句话
self.yolo_model.load_weights(self.model_path)
改成这样:
self.yolo_model.load_weights(self.model_path, by_name=True , skip_mismatch=True)
解决问题。
意思是这样的:
加载预训练模型:
根据预训练模型的地址 weights_path, 加载模型, 按名称对应 by_name, 略过不匹配 skip_mismatch
为什么还不知道,欢迎大家讨论与指教。