利用深度学习检测行驶中的车辆驾驶员是否有分散注意力活动行为!
一、定义
1.1项目概况
减少交通事故的一种有效方法是防止分散注意力驾驶,这是在驾驶时进行其他活动(例如发信息,通话等)的行为。这种性质的活动会分散驾驶员对道路的注意力。这些干扰反过来会危机司机,乘客,路人和其他车辆和车辆中的其他人的安全。根据交通信息报道,五分之一的车祸是由驾驶员分散注意力造成的。
在这个项目中,我们开发并完善了一套机器学习模型,用于通过在一家名为State Farm的保险公司获得的数据集上来检测驾驶员在驾驶过程中的行为并对其进行分类。
1.2问题陈述
为了改进项目概述部分中的警报统计状态,应该测试创新方法。其中一种方法是开发一种算法,通过向驾驶员提供二维仪表盘摄像机图像来检测驾驶员是否有分散注意力行为。然后,该算法可以作为设备中的API,通过检查驾驶员是否专心驾驶、系好安全带并提醒他们是否专心驾驶,来对驾驶员的行为进行分类。
State Farm提供的数据集由图像组成,这意味着解决手头问题的最有效方法是开发深度卷积神经网络模型,然后在数据集的训练子集上训练它,目的是优化某个评估指标。然后,将在数据集的测试子集上测试该模型并进行评估。
1.3权值
模型将使用图像的预测类和实际类之间的多类对数损失进行评估。评估权值的公式为:
其中N是数据集中图像的数量,M是图像类标签的数量,log是自然对数,如果观察i属于j类则y=1,否则为0,P为观测i属于j类的预测概率。
对数损失通过将预测输入作为0和1之间的概率值而不是简单的真或假来测量分类模型的性能。这意味着对数损失考虑了模型预测的不确定性,该不确定性基于模型预测与实际标签的差异程度,从而对模型的性能进行更细致的评估。
二、分析
2.1数据探索
该项目中使用的数据集是由State Farm通过Kaggle competition提供的,如果在车内捕获他们的活动(如发信息,通话,吃东西,伸手到后座,化妆等)的一组司机图像。这些活动分为10个类:
- c0:安全驾驶
- c1:发信息 - 右手
- c2:通电话 - 右手
- c3:发信息 - 左手
- c4:通电话 - 左手
- c5:操作收音机
- c6:喝东西
- c7:将手伸到后座
- c8:整理头发和化妆
- c9:与乘客交谈
该数据集包含总共102150张图像,这些图像被分成22424张图像的训练集和79726张图像的测试集。以下是数据集图像的示例。
图1.数据集的示例
图像是480×640像素,并且训练集中的类的分布是相对均匀的。数据集的总大小为4 GB:
该数据包含三个文件:
- imgs.zip - 所有文件的压缩文件夹(训练/测试)
- images sample_submission.csv -Kaggle提交的正确格式的示例提交文件。
- driver_imgs_list.csv - 训练图像列表,项目(驾驶)ID和类ID
2.2探索性可视化
选择评估度量和验证方法的一个重要因素是目标类分布的均匀性。从图2中可以看出,该数据集的类分布是相对均匀的。这允许我们使用一个模型来训练整个数据集,如果它不是均匀的,那么每个类将分别使用一个单独的二元分类模型,然后对这些模型的评估进行平均,以便对分类方法进行最终评估。此外,由于数据是均匀的,所以绘制验证集是一项简单的任务,从打乱的训练集中分离一定比例的验证集将产生一组类似的特征。
图2.数据集的类分布
2.3算法和技术
该项目使用卷积神经网络(CNN)执行。CNN或ConvNets由具有可学习的权值和偏差的神经元组成,每个神经元接收一个输入,执行一个点积,通常后面跟着一个非线性函数。ConvNets的输入是图像像素作为向量,其输出是类得分。当向量从输入层到输出层时,它们通过一系列隐藏层,每个隐藏层由神经元组成,其中每个神经元完全连接到前一层中的每个神经元,同时完全独立于同一隐藏层中的其它神经元。
图3. CNN的视觉表示
CNN与其他神经网络的不同之处在于它的神经元在三个维度(高度,宽度,深度)排列。CNN中使用的主要层类型是:
- 卷积层:通过在其权重值和区域值之间应用点积来计算连接到输入区域的神经元的输出。
- 池化层:沿空间维度(即高度和宽度)执行下采样操作。
- 完全连接的层:计算类得分数。
计算机视觉任务中一种被称为迁移学习的流行方法也被用来解决这个项目中提到的问题。迁移学习是在解决一个问题并将其应用于不同但相似的问题时存储所获得的知识的过程。迁移学习有两种主要方法:
- 使用预先训练的CNN作为固定特征提取器:该技术使用在大型数据集(例如Imagenet)上预训练的CNN ,丢弃最后一个完全连接的层,然后使用网络的其余部分作为不同数据集的特征提取器。对于新数据中的每个图像,该过程将根据预训练的模型架构计算某个维度的向量,计算出的向量包含分类器之前隐藏层的激活权值,称为CNN码。提取CNN码后,对新数据集进行线性分类器训练。
- 微调预先训练的CNN:这种方法与前一种方法不同,它通过继续反向传播来微调预训练网络的权重,这可以通过微调整个网络或冻结前期层来完成。只调整网络的更高层,后者有两个目的,其中一个是通过保持第一层固定演化模型防止过度拟合数据,另一个是减少训练时间作为早期层包含适用于大多数应用程序的通用特征,如边缘和曲线。
2.4基准
该项目的基准模型是一个简单的CNN模型,由三个块组成,每个块以卷积层开始,应用relu激活,然后是max-pooling层。然后使用flatten层,接着是dropout层,接着是另一个dropout层,最后是另一个10个输出的dense层,对应于类的数量和softmax激活。该模型使用rmsprop优化器和分类交叉熵损失函数进行编译。该模型训练了4个batch大小为32的周期。该模型很好地在验证数据集上实现了对数损失为0.04,并且在测试集上实现了对数损失为0.2。
三、方法
3.1数据预处理
最初,该项目旨在使用整个数据集,但在预处理数据时,虚拟实例的内存已经耗尽,因为只预处理了包含22424张图像的训练集,占用了超过20GB的内存。该实例具有61GB的内存,并且测试集仅保留80000张没有标签的图像,这意味着要在测试集上测试模型,其预测必须提交给Kaggle。因此,不能使用测试数据集的子集,因为这会导致Kaggle的提交不完整。通过将训练数据集视为整个数据集然后将其10%作为验证集并将另外10%作为测试集分开来解决此问题。此外,该项目将使用keras tensorflow作为后端,这意味着输入必须是四维张量与keras的CNN兼容,因此,图像首先调整为224 x 224像素,然后转换成三维张量和形状的四维张量(N,224、224、3),N是图像的数量。之后,通过将张量除以255来缩放张量。
3.2实现
基准模型首先通过使用keras函数Sequential创建模型,并添加16个滤波器的卷积层,内核大小2X2,相同的填充,relu激活和输入形状与四维张量相同(None, 224,224,3)。添加与池大小2X2的最大池化层,之后还添加了多个卷积层,每个层随后是2X2最大池层。第一个Conv层和后两个Conv层之间的区别在于没有指定输入形状,只指定模型的第一层所需的形状,并且滤波器的数量是前一层的两倍,如图4所示。通过加入速率为0.3的drop - layer,再加入Flatten,然后加入relu激活的80个layer,对模型进行正则化。输出由另一个速率为0.4的drop - layer进行正则化,最后得到一个10个output的Dense层,代表softmax激活的数据类
图4.基准模型的摘要
使用rmsprop优化器编译模型,对训练数据进行分类交叉熵损失函数的训练,并对4个batch大小为32的周期的验证数据上进行验证。在训练期间,获得最佳对数损失分数的权重验证数据保存在hdf5文件中。在从sklearn的度量标准导入对数损失函数后,将这些加载到模型中以在测试集上测试它们。然后将模型的预测与对数损失的实际标签进行比较。
最初的解决方案是通过导入预先训练的CNN模型开始的。选择的模型是Xception,因为它是精度方面表现第二好的模型,参数小于最佳模型的一半。Xception模型是在Imagenet上训练的,这是一个包含1000多个分类的120多万张图像的海量数据集。最后一层被删除,因为它是1000个分类的分类器。然后,通过preprocess_input另一个keras函数运行张量后,使用keras的预测函数提取三个数据集中所有图像的CNN编码。第二个模型是使用keras的顺序函数创建的,其中Dropout层的速率为0.3,输入形状与CNN编码形状相匹配(None,7,7,2048)添加到模型中,接着是Flatten层和Dense层,其中10个输出对应于数据集类的数量和softmax函数。使用rmsprop优化器编译该模型,然后对训练数据进行分类交叉熵损失函数训练,并在20个batch大小为16的周期验证数据上验证,同时在该过程中保存验证集上的最佳性能权重。测试以与基准模型相同的方式进行。
3.3细化
优化结果的第一个尝试是继续使用预先训练的Xception模型作为特征提取器,但是在分类之前对CNN编码进行进一步的训练。为此,使用顺序函数创建了一个新模型,其中添加了速率为0.3的Dropout层和与CNN编码相同尺寸的输入形状。然后通过向模型添加Flatten层,接着是250个输出的密集层和relu激活来平坦化数据,以使密集层的输出正规化,将另一个0.4的Dropout层添加到模型中,该模型由10个输出分类层和softmax激活完成。该模型使用Adam优化器和分类交叉熵损失函数进行编译,然后对训练数据进行训练,并在20个batch大小为16的周期进行验证,在验证过程中保留验证集得分最高的权重。模型的测试与前面的解决方案是相同的。
最终的解决方案采用了第二种迁移学习方法,即对预先训练好的ConvNet进行微调。使用的预训练模型是相同的Xception模型,导入模型时唯一的区别是输入形状必须指定为与三维张量相同的形状,即(224,224,3)。一个新模型使用Sequential函数,并为其添加一个Dropout层,其0.3比率和输入形状与Xception模型的输出形状相匹配,Flatten层和10个输出的Dense层以及softmax函数。由于Model函数没有添加函数性,因此使用Model函数创建另一个模型,其中输入被指定为预训练模型。
输入即(224,224,3),输出是本段描述的第二个模型的输出(即使用Sequential函数创建的输出)将Xception模型的输出作为输入。Xception模型有131层14个块,最终的解决方案是通过微调最后2个块完成的,因此在编译模型之前,使前116层的权重固定。该模型使用Adam优化器和分类交叉熵损失函数进行编译,然后在训练数据集上进行训练,并在验证数据集上验证10个batch大小为64的周期,并保存验证集上具有最佳对数损失的权重。使用与上述相同的方法在测试数据上测试模型。
四、结果
4.1模型评估和验证
使用微调技术训练最终模型,其结果比其他两种解决方案获得了更好的结果。首先,就准确性而言,最终模型的最佳权重比训练集和验证集中的初始和中间模型都具有更高的准确度,如表1所示。
最终模型在该项目的评估指标(即多类对数损失)方面也比表2中所示的两组训练和验证中的早期解决方案表现得更好。
值得注意的是,从上表中可以看出,最终的解决方案在训练集中比在验证集中获得了更好的结果,与其他两种解决方案不同。这表明数据的最终解决方案有更好的泛化比早些时候尝试他们取得更好的结果在较小的验证集。所有解决方案都在2242张图像的测试数据子集上进行测试,其中最终解决方案在评估指标方面也优于初始和中间解决方案,如表3所示。
4.2理由
虽然是一个简单的模型,只经过4个周期的训练,但是它的基准性能相对较好,它优于初始和中间解决方案。在准确性方面,它在训练集中达到94.70%,在验证集中达到98.93%,而在损失函数中,在训练集和验证集中分别达到0.1736和0.0422。此外,它遇到了早期解决方案相同的问题,即高偏差,因为其在验证集中的结果比训练数据集中的结果好得多。而最终解决方案有更好的泛化以及更高的精度(即训练:99.54%,验证:99.33%)和更少的对数损失(即训练:0.0192,验证:0.0271)。最后,对测试数据集的基准模型评估产生了0.2157的对数损失,
五、结论
5.1自由形式可视化
该算法能够区分同一驾驶员在安全驾驶时的图像和在驾驶时进行分散注意力的活动行为时的图像,如图5所示。它还能够识别各种分散注意力的活动,如图6所示。
图5.最终解决方案的分类图像
图6.最终解决方案确定的分散注意力的活动
5.2反射
原始数据来自Kaggle,然后将它们分为训练,验证和测试集。对这些集合进行了探索、计算,计算了它们的标签分布,并显示了一些示例以便对数据进行一般性的理解。数据被转换为四维阵列并进行缩放。创建了一个简单的基准模型来了解问题的复杂性,然后尝试使用预训练模型作为特征提取器的初始解决方案,通过在分类之前添加额外的完全连接层来改进。最后,实施了使用微调预训练模型的解决方案。
一个有趣的方面是,对初始解决方案的进一步训练导致不仅在验证和测试集上而且在训练集上导致更糟糕的结果。最终解决方案的结果令人失望,因为它们并没有明显优于简单基准模型的结果,该结果仅训练了4个周期,而最终解决方案模型训练超过27小时。
5.3改进
该项目可以通过测试其他预先训练的模型(如ResNet50或InceptionResNetV2)来改进。此外,测试具有较小学习率和动量更高的优化器。最重要的是训练更多的周期,并可能微调更深层次。一个有趣的实验是使用初始解决方案中的分类器权重来初始化最终解决方案模型的分类器层的权重,以减少训练时间。