在商业环境中,顾客的排队等待是一个常见现象。然而,根据最新研究,长队列会阻碍更多人加入排队。例如,当饥饿时,最不想做的就是排队等待吃饭。因此,对于企业来说,拥有一个有效的排队策略至关重要。十年前,让计算机计算排队中的人数是一个非常困难的问题。公司通常不得不雇佣整个学术研究团队来尝试准确计算。然后深度学习出现了。曾经非常困难的问题现在可以由任何拥有体面GPU或能够访问负担得起的云GPU实例的人解决。
在本系列文章中,将展示如何制作一个AI排队长度检测器。将从从头开始实现一个简单的对象检测器开始,训练自定义的数据集,并逐步实现实时检测和跟踪对象(或人类)。稍后,还将看到如何通过使用预训练的对象检测网络如YOLO使解决方案更有效。
对象检测被认为是一个复杂的计算机视觉问题,因为需要在给定的图像或视频中找到所需对象/对象的位置,还需要确定检测到的对象类型。基于深度学习模型的最新进展使得开发对象检测应用程序变得更加容易。这些模型不仅性能有显著提高,而且还利用最先进的技术和庞大的数据集来高效地实现所需的结果。
在本文中,将保持简单,并尝试实现一个用于对象检测的卷积神经网络(CNN)。在进入编码部分之前,先快速回顾一下CNN是什么。
简单地说,CNN是一类通常用于分析视觉图像的深度神经网络。像其他神经网络一样,它由不同的层组成(即输入层、一个或多个隐藏层和输出层)。它可以将图像作为输入,为图像中的不同方面或对象分配权重,并将它们彼此区分开来。每个隐藏层使用特定的模式和特征转换其输入,并将其传递给下一层,而最后一层通常对对象进行分类。
在继续之前,重要的是要注意假设对Python有一定的了解,并且对深度学习也有一定的理解,所以将跳过常见Python库的安装过程。将使用Anaconda发行版在Windows上工作Jupyter Notebook,但请随意选择任何IDE一起工作。代码不是平台特定的,应该可以正常工作。
对于本文,将使用cifar10数据集来训练一个简单的对象检测器。
让从导入需要的库开始。
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from keras import losses, metrics
from keras.optimizers import Adam
from keras.models import Sequential
from keras.callbacks import EarlyStopping
from keras.utils.np_utils import to_categorical
from keras.layers import MaxPool2D, Dense, Conv2D, Flatten
from sklearn.metrics import classification_report, confusion_matrix, accuracy_score
下一步是加载数据。可以使用以下几行代码直接在笔记本中下载它。
from keras.datasets import cifar10
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
让验证每组的形状。
print(X_train.shape)
print(X_test.shape)
print(y_train.shape)
print(y_test.shape)
cifar10数据集有十种不同的对象类别,数量相等,这将有助于算法平等地学习所有类别。这可以通过以下方式验证:
print(np.unique(y_train, return_counts=True))
在可以将其输入神经网络之前,需要标准化这些数据,还需要将类变量更改为矩阵。
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 200
x_test /= 200
y_train = to_categorical(y_train)
y_test = to_categorical(y_test)
现在是定义模型来分类这些对象的时候了。将使用一个顺序模型,其中有两个卷积层。这些层将有32个过滤器(稍后将应用最大池化来减少空间维度)。将使用Adam激活编译模型。
model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=(32, 32, 3), activation='relu'))
model.add(Conv2D(32, (3, 3), activation='relu'))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(512, activation='relu'))
model.add(Dense(10, activation='softmax'))
model.compile(loss=losses.categorical_crossentropy, optimizer=Adam(), metrics=[metrics.categorical_accuracy])
可以按如下方式查看模型摘要:
print(model.summary())
现在让将模型拟合到训练数据上。
early = EarlyStopping(monitor='loss')
hist = model.fit(x_train, y_train, batch_size=100, validation_split=0.2, epochs=5, callbacks=[early])
现在模型已经训练好了,可以使用evaluate函数评估模型的表现。
print(model.evaluate(x_test, y_test, batch_size=100))
应该看到类似于以下输出:
100/100 [==============================] - 10s 97ms/step - loss: 0.8231 - categorical_accuracy: 0.7128
[0.8231054544448853, 0.7128000259399414]
获得了71%的准确率,这已经足够好了,因为可以看到它没有过拟合。还可以绘制训练和验证的准确率。
现在让使用新训练的模型预测测试数据集的类别。
y_pred = model.predict_classes(x_test)
可以使用accuracy_score再次测试模型的准确性。
print(accuracy_score(y_test_classes, y_pred))