1. 问题描述
教学的演示代码中发现一个问题,去年的代码,用的是tf1.14,准确率以及IOU能到90%+,但今年用tf2.12.0,准确率降低了非常多,而且iou降的根本就没法看了。代码只是将模型的激活函数层Activation('sigmoid')的激活函数由relu修改为了sigmoid,也正是因为做了这部分修改,准确率从60%上升到了82%。
2. 整个代码解决问题
该代码首先是生成了5w个8*8像素的图片,然后再在里面随机生成一个黑色的小方块,训练深度模型用来检测方框的边界。
3. 具体代码
具体代码如下,不依赖其他的包即可运行。
import numpy as np #处理科学数组的苦
import warnings
import matplotlib.pyplot as plt #画图的库
import matplotlib #画图的苦
%matplotlib inline
warnings.filterwarnings("ignore")
num_imgs = 50000
img_size = 8
min_object_size = 1
max_object_size = 4
num_objects = 1
show_img_idx = 10
bboxes = np.zeros((num_imgs, num_objects, 4))
imgs = np.zeros((num_imgs, img_size, img_size))
for i_img in range(num_imgs):
for i_object in range(num_objects):
w, h = np.random.randint(min_object_size, max_object_size, size=2)
x = np.random.randint(0, img_size - w)
y = np.random.randint(0, img_size - h)
imgs[i_img, x:x+w, y:y+h] = 1.
bboxes[i_img, i_object] = [x, y, w, h]
#print( imgs[show_img_idx], bboxes[show_img_idx])
plt.imshow(imgs[show_img_idx].T, cmap='Greys', interpolation='none', origin='lower', extent=[0, img_size, 0, img_size])
X = (imgs.reshape(num_imgs, -1) - np.mean(imgs)) / np.std(imgs) #归一化操作
y = bboxes.reshape(num_imgs, -1) / img_size #
# Split training and test.
i = int(0.8 * num_imgs)
train_X = X[:i]
test_X = X[i:]
train_y = y[:i]
test_y = y[i:]
test_imgs = imgs[i:]
test_bboxes = bboxes[i:]
# Build the model.
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Activation, Dropout
from tensorflow.keras.optimizers import SGD, Adam
model = Sequential([Dense(256, input_dim=train_X.shape[-1]),
Dropout(0.2),
Activation('sigmoid'),
Dense(test_y.shape[-1])
])
#model.compile('adadelta', 'mse')
model.compile(optimizer=Adam(), loss='mse', metrics=['accuracy'])
model.summary()
# Train
model.fit(train_X, train_y, epochs=30, validation_data=(test_X, test_y), verbose=2) #300 4.6900
# Predict bounding boxes on the test images.
pred_y = model.predict(test_X)
pred_bboxes = pred_y *img_size
pred_bboxes = pred_bboxes.reshape(len(pred_bboxes), num_objects, -1)
def IOU(bbox1, bbox2):
'''Calculate overlap between two bounding boxes [x, y, w, h] as the area of intersection over the area of unity'''
x1, y1, w1, h1 = bbox1[0], bbox1[1], bbox1[2], bbox1[3]
x2, y2, w2, h2 = bbox2[0], bbox2[1], bbox2[2], bbox2[3]
w_I = min(x1 + w1, x2 + w2) - max(x1, x2)
h_I = min(y1 + h1, y2 + h2) - max(y1, y2)
if w_I <= 0 or h_I <= 0: # no overlap
return 0.
I = w_I * h_I
U = w1 * h1 + w2 * h2 - I
return I / U
summed_IOU = 0.
for pred_bbox, test_bbox in zip(pred_bboxes.reshape(-1, 4), test_bboxes.reshape(-1, 4)):
#print(pred_bbox, test_bbox)
this_iou = IOU(pred_bbox, test_bbox)
#print(this_iou)
summed_IOU += this_iou
mean_IOU = summed_IOU/len(pred_bboxes)
print("平均IOU为 ", mean_IOU)
Epoch 30/30
1250/1250 - 3s - loss: 5.1984e-04 - accuracy: 0.8519 - val_loss: 0.0012 - val_accuracy: 0.8214 - 3s/epoch - 3ms/step
IOU为0.52626
太奇怪了,求大佬解答,有以下怀疑点。
1、版本更新,导致激活函数有不同。
2、tf版本的更新使得训练模型的步骤出现了问题。