https://www.toutiao.com/a6708677717547549197/
交通标志是我们道路安全中最重要的部分,因为它们会在您开车行驶之前告诉您重要的事情。在主要交叉路口或十字路口须遵循的指示,指引司机确保道路交通安全和正常行驶。
每年大约有135万人由于道路交通事故死亡。世界上大多数国家的政府都强制要求遵守交通规则和标志。
在当今这个时代,世界各地的工程师都在尝试使用自动驾驶系统和高级驾驶员辅助系统
(ADAS)等现代技术来减少交通事故,检测道路标志同样重要。
概述
在这里,我们将尝试使用卷积神经网络(CNN)等深度学习技术解决手头的问题。我们将使用德国交通标志数据集来训练我们的神经网络。
数据
让我们来看看这些数据的重要特征,如下所示 -
- 多级分类问题。
- 超过40个分类。
- 总共超过50,000张图片。
- 图像大小在15x15到250x250像素之间变化。
- 交通标志的边界框是注释的一部分。
我们的数据集中有43种独特类型的交通标志,这使得它成为使用神经网络的多类分类问题。我们的图像是RGB格式,我们将转换为灰度。这将降低模型复杂度(需要调优的超参数的数量),并且这将迫使模型学习几何形状(符号的形状)。
我们还将对数据进行归一化调整,以避免由于特征的分布范围对权重进行过度补偿/欠补偿。
类分布
类分布
从上图中可以看出,数据集在本质上是高度不平衡的。这可能意味着我们经过训练的模型可能会偏向具有更大数量的类。
让我们训练模型来检测交通标志
我们从基本的CNN架构开始,并尝试使用Adadelta作为损失优化器来减少分类交叉熵损失。我们将使用ReLU作为卷积的激活函数,我们将在最后一层添加Softmax。
模型架构
网络由两个卷积层组成,每个层都有ReLU激活,第一层包含8个内核,内核大小为3x3,第二层包含16个内核,内核大小为3x3。接下来是MaxPooling层,然后是Dropout层,其Dropout率为0.75。然后我们将输出展平,将其输入到具有128个神经元的Dense层中。我们再添加一个Dropout层,其Dropout率为0.5。最后添加一个具有softmax激活的输出层。
epochs = 10
batch_size = 128
num_classes = 43
model = Sequential()
model.add(Conv2D(
8, kernel_size=(3, 3), activation='relu', input_shape=input_shape
))
model.add(Conv2D(16, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(rate=0.75))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(rate=0.5))
model.add(Dense(num_classes, activation='softmax'))
model.compile(
loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.Adadelta(), metrics=['accuracy']
)
model.summary()
history = model.fit(
x_train, y_train, batch_size=batch_size, epochs=epochs,
verbose=1, validation_data=(x_test, y_test)
)
我们可以使用上面代码中“ history ”变量中的信息来绘制训练损失和测试损失,我们得到如下图表。
从图中可以看出,每个周期之后,训练和验证损失都在稳步下降。并且该模型的Macro F1分数计算为0.97。
可视化特征映射
想知道了解卷积神经网络如何看待输入图像?我们可以明确的看到每一层的输出!代码如下。
layer_outputs = [layer.output for layer in model.layers]
activation_model = Model(inputs=model.input, outputs=layer_outputs)
def display_activation(activations, col_size, row_size, act_index):
activation = activations[act_index]
activation_index=0
fig, ax = plt.subplots(row_size, col_size, figsize=(row_size*2.5,col_size*1.5))
for row in range(0,row_size):
for col in range(0,col_size):
ax[row][col].imshow(activation[0, :, :, activation_index], cmap='gray')
activation_index += 1
plt.show()
# we are going to see the output of image no 11722 after
# each convolution layer
idx = 11722
activations = activation_model.predict(x_test[idx].reshape(1, 64, 64, 1))
对于特定图像,并非所有内核都由ReLU激活函数激活。因此,我们将在第一层中看到最活跃的内核的特征图。我们还在第一层绘制了一个显示内核激活的折线图。
图1:CNN的输入图像 图2:第一层最活跃内核的输出
从图中可以看出,即使内核6的特征识别有一些峰值,这个特定输入图像的大多数特征都被内核4识别。尽管内核激活中有一些很好的峰值,但是上面的图像是错误分类的。输入图像的实际类是5,但是我们的训练模型预测它是类2。让我们用条形图来看看前5个概率。
模型预测第2类的概率超过0.5,但实际情况是图像属于第5类,而我们训练的模型仅给出该类的概率超过0.3。
因此我们需要稍微改变模型架构。
我们 将 CNN架构的第一层和第二层中 的内核数量加倍 ,重新训练模型并使用与上述相同的测试图像进行测试。这次,模型预测了正确的类, 概率 超过 0.8 ,整体Macro F1分数为0.9825。
我已经训练了六种不同架构的模型,并试图稳步减少损失。
迁移学习
迁移学习是一种允许我们使用从其他任务中获得的知识的方法,以便快速有效地解决新的类似的问题。这减少了对于我们正在处理的特定任务相关的数据的需求。
在这种情况下,我们只使用CNN模型的一部分。我们在体系结构的末尾丢弃完全连接的层,然后您可以使用卷积层的输出特征来训练ML模型,或者您可以添加自己的完全连接的层并对其进行调优。
我使用VGG16,Inception,ResNet和RetinaNet进行了转移学习,以便直观地检测交通标志。
到目前为止我遇到的最有趣的神经网络之一是RetinaNet。它可以执行回归(用于边界框)和分类。上图显示的是在这个数据集上训练的RetinaNet模型的类似的输出。
结论
现在我们知道深度学习在解决计算机视觉等问题方面是非常有用的。在这个项目中,我们通过训练多个CNN模型架构,可以实现高达99%的Macro F1分数。
通过这个项目,我学到了很多东西并且在使用像Keras,TensorFlow,Matplotlib和Pandas这样的库在Python中编写代码时获得了实践经验。
下图显示的是模型的比较:
CNN架构及其测试MacroF1分数