在处理神经网络或数组时,通常会避免使用循环,因为循环通常意味着效率低下。然而,在某些情况下,为了理解底层逻辑,可能会故意使用循环。在本文中,将探讨如何通过向量化方法来优化神经网络的解码过程,特别是针对YOLO(You Only Look Once)目标检测模型的输出。
向量化是利用现代CPU和GPU的并行处理能力来提高计算效率的一种技术。在神经网络的解码过程中,可以通过向量化来避免循环,从而提高计算速度。本文将展示如何使用Python和NumPy库来实现这一过程。
首先,需要定义一个新的softmax函数,它可以在2D数组上工作。这个函数将用于后续的解码过程。
def softmax_2d(x, axis=1):
x_max = np.max(x, axis=axis)[:, np.newaxis]
e_x = np.exp(x - x_max)
x_sum = np.sum(e_x, axis=axis)[:, np.newaxis]
return e_x / x_sum
接下来,需要定义一些常量数组,这些数组将用于后续的解码过程。这些数组包括锚点的宽度和高度,以及网格的中心坐标。
ANCHORS_W = np.array([
0.57273,
1.87446,
3.33843,
7.88282,
9.77052
]).reshape(1, 1, 5)
ANCHORS_H = np.array([
0.677385,
2.06253,
5.47434,
3.52778,
9.16828
]).reshape(1, 1, 5)
CX = np.tile(np.arange(GRID_SIZE), GRID_SIZE).reshape(1, GRID_SIZE**2, 1)
CY = np.tile(np.arange(GRID_SIZE), GRID_SIZE).reshape(1, GRID_SIZE, GRID_SIZE).transpose()
CY = CY.reshape(1, GRID_SIZE**2, 1)
现在,可以开始实现向量化的解码函数。这个函数将接受原始的预测结果,并返回解码后的预测结果。
def decode_preds_vec(raw_preds: []):
num_classes = len(COCO_CLASSES)
raw_preds = np.transpose(raw_preds, (0, 2, 3, 1))
raw_preds = raw_preds.reshape((1, GRID_SIZE**2, BOXES_PER_CELL, num_classes + 5))
decoded_preds = []
tx = raw_preds[:,:,:,0]
ty = raw_preds[:,:,:,1]
tw = raw_preds[:,:,:,2]
th = raw_preds[:,:,:,3]
tc = raw_preds[:,:,:,4]
x = ((CX + sigmoid(tx)) * CELL_SIZE).reshape(-1)
y = ((CY + sigmoid(ty)) * CELL_SIZE).reshape(-1)
w = (np.exp(tw) * ANCHORS_W * CELL_SIZE).reshape(-1)
h = (np.exp(th) * ANCHORS_H * CELL_SIZE).reshape(-1)
box_confidence = sigmoid(tc).reshape(-1)
classes_raw = raw_preds[:,:,:,5:5 + num_classes].reshape(GRID_SIZE**2 * BOXES_PER_CELL, -1)
classes_confidence = softmax_2d(classes_raw, axis=1)
box_class_idx = np.argmax(classes_confidence, axis=1)
box_class_confidence = classes_confidence.max(axis=1)
combined_box_confidence = box_confidence * box_class_confidence
decoded_boxes = np.stack([
box_class_idx,
combined_box_confidence,
x,
y,
w,
h]).transpose()
return sorted(
list(decoded_boxes), key=lambda p: p[1], reverse=True)
在这个函数中,首先对原始预测结果进行转置和重塑,以便将编码的框坐标和类别置信度移动到最后一个维度。然后,使用向量化操作来计算每个框的中心坐标、宽度、高度和置信度。最后,使用softmax函数来计算每个类别的置信度,并结合框的置信度来得到最终的解码结果。