OpenCV-Python实战(18)——深度学习简介与入门示例
Python 库 Keras,并通过实战来推开深度学习的大门。GPU 进行优化并行计算
1400 万张带有标签的高分辨率图像,包含 20,000 多个类别。因此,2012 年 AlexNet 架构在解决 ImageNet 大规模视觉识别挑战赛 (ILSVRC) 上的突破性进展通常被认为是深度学习大爆发的开始。AlexNet 在 ILSVRC 比赛中取得成功之后,更多深度学习架构开始被应用于 ImageNet 挑战赛中,下图显示了在 ImageNet 挑战赛中的最相关深度学习模型的准确率和模型的参数量:
AlexNet:AlexNet 是 LSVRC-2012 的获胜者,是一种简单但功能强大的网络架构,其通过堆叠卷积层和池化层,最后顶部使用全连接层。VGG:VGGNet 由 Visual Geometry Group (VGG) 提出,在 LSVRC-2014 中排名第二,与 AlexNet 相比其在整个网络中仅使用 3 x 3 卷积核,而不是使用大尺寸卷积核(例如 7 x 7 和 11 x 11),主要贡献在于它表明网络的深度是在卷积神经网络中实现更好的识别或分类准确率的关键。它的主要缺点是训练速度非常慢,并且其网络架构权重参数量非常大(可以从上图看出)。GoogLeNet/Inception V1:GoogLeNet (也称 Inception V1) 是 LSVRC-2014 的获胜者,其 top-5 错误率仅为 6.67%,非常接近人类水平的表现。这种架构比 VGGNet 更深,但由于其使用 9 个并行的 Inception 模块,Inception 模块基于几个非常小的卷积,极大的减少了参数数量。ResNet:ResNets 是 LSVRC-2015 的获胜者,是迄今为止最深的网络,其包含 153 个卷积层 top-5 分类错误率仅为 4.9% (使深度学习模型准确率首次高于人类)。该架构使用跳跃连接,可实现增量学习修改。Inception V3:Inception V2 在 Inception 模块中引入了批归一化,Inception V3 架构包含了分解思想,其目标是在不降低网络效率的情况下减少参数的数量。Inception V4:Inception V4 具有比 Inception-V3 更统一的简化架构和更多的 Inception 模块,在 LSVRC 上达到了 80.2% 的 top-1 准确率和 95.2% 的 top-5 准确率。PASCAL Visual Object (PASCAL VOC) 数据集,包含 20 个类别的 10,000 张图像,数据集中包含目标的边界框;2) ImageNet 在 2013 年发布了一个目标检测数据集,它由大约 500,000 张图像和 200 个类别组成;3) Common Objects in Context (COCO) 是一个大规模的对象检测、分割数据集,其包括 328,000 张图像以及 250 万个标记目标。为了评估目标检测算法,通常使用平均精度均值 (mean Average Precision, mAP),用于目标检测深度学习算法:R-CNN:Region-based Convolutional Network (R-CNN) 是最早使用卷积神经网络进行目标检测的算法之一,与基于 HOG 特征的系统相比,卷积神经网络可以带来更高的对象检测性能。该算法可以分解为以下三个步骤:
AlexNet 的模型执行前向传递以提取特征向量SVM 分类器预测类别,利用线性回归器预测边界框的坐标Fast R-CNN:Fast Region-based Convolutional Network (Fast R-CNN) 是对 R-CNN的改进,以有效地对目标提议进行分类。此外,Fast R-CNN 采用多项创新来提高训练和测试速度,同时提高检测精度。Faster R-CNN:Faster R-CNN 是对 Fast R-CNN 的改进,它引入了候选区域网络 (region proposal network, RPN),与检测网络共享图像的卷积特征。R-FCN:Region-based Fully Convolutional Network (R-FCN) 是一个只有卷积层的框架,以实现准确高效的目标检测。YOLO: You only look once (YOLO) 可以在一个步骤中同时预测边界框和类别概率。与其他深度学习检测器相比,YOLO 产生更多的定位误差,但其产生假阳性的概率较小。SSD:Single Shot MultiBox Detector (SSD) 同样通过单一端到端卷积神经网络架构同时预测边界框和类别概率。YOLO V2: YOLO V2 是 YOLO 的改进版本,专注于提高准确性,同时是一个实时快速检测器。NASNet: NASNet 的作者介绍了神经网络搜索,通过使用循环神经网络来组成神经网络架构,NASNet 学习模型模型架构的同时提高准确性。Mask R-CNN:Mask Region-based Convolutional Network (Mask R-CNN) 是 Faster R-CNN 模型的改进,它为边界框检测添加了一个并行分支,目的是预测目标掩码。目标掩码是它在图像中按像素进行的分割,允许进行目标实例分割。YOLO V3:YOLO V3 是以 YOLO V1 和 YOLO V2 为基础调整了网络结构;利用多尺度特征进行对象检测。YOLO V4:YOLO-V4 算法是在原有 YOLO 目标检测架构的基础上,采用了 CNN 领域中优秀的优化策略,从数据处理、主干网络、网络训练、激活函数、损失函数等各个方面都有着不同程度的优化。Python 编写的开源高级神经网络 API,它能够在 TensorFlow、或 Theano 之上运行,其最大的特点是能够实现快速实验,因此本文利用它来进行深度学习实战。Keras,首先进行安装:pip install keras
# 产生一百个随机数据点作为训练数据
Number = 100
x = np.linspace(0, Number, Number)
y = 3 * np.linspace(0, Number, Number) + np.random.uniform(-12, 12, Number)
def create_model():
# 创建 Sequential 模型
model = Sequential()
# 使用具有线性激活函数的全连接层
model.add(Dense(input_dim=1, units=1, activation='linear', kernel_initializer='uniform'))
# 使用均方差(mse)作为损失函数,Adam作为优化器编译模型
model.compile(loss='mse', optimizer=Adam(lr=0.1))
return model
Keras 时,最简单的模型类型是 Sequential 模型,可以将其视为网络层的线性堆栈,对于更复杂的架构,可以使用 Keras 函数式 API,以创建任意网络架构。Sequential 模型,然后利用 model.add() 方法堆叠层来构建模型。在此示例中,使用了具有线性激活函数的单个全连接层。定义模型之后,需要使用损失函数与优化器编译模型,示例中使用均方差 (mean squared error, MSE) 作为损失函数,使用 Adam 作为优化器并设置学习率为 0.1。model.fit() 方法使用训练数据的训练模型:linear_reg_model.fit(x, y, epochs=100, validation_split=0.2, verbose=2)
w 和 b,这些值将用于接下来的:def get_weights(model):
w = model.get_weights()[0][0][0]
b = model.get_weights()[1][0]
return w, b
w_final, b_final = get_weights(linear_reg_model)
predictions = w_final * x + b_final
linear_reg_model.save_weights("my_model.h5")
plt.subplot(1, 2, 1)
plt.plot(x, y, 'ro', label='Original data')
plt.xlabel('x')
plt.ylabel('y')
plt.title("Training Data")plt.subplot(1, 2, 2)
plt.plot(x, y, 'ro', label='Original data')
plt.plot(x, predictions, label='Fitted line')
plt.xlabel('x')
plt.ylabel('y')
plt.title('Linear Regression Result', fontsize=10)
plt.legend()
plt.show()
# 加载模型
linear_reg_model.load_weights('my_model.h5')
# 构建测试数据集
M = 3
new_x = np.linspace(Number + 1, Number + 10, M)
# 使用模型进行预测
new_predictions = linear_reg_model.predict(new_x)
def create_model():
model = Sequential()
model.add(Dense(units=128, activation='relu', input_shape=(784,)))
model.add(Dense(units=128, activation='relu'))
model.add(Dense(units=64, activation='relu'))
model.add(Dense(units=10, activation='softmax'))
# 使用分类交叉熵(categorical_crossentropy)作为损失函数和随机梯度下降作为优化器编译模型
model.compile(optimizer=SGD(0.001), loss='categorical_crossentropy', metrics=['acc'])return model
categorical_crossentropy 损失函数编译模型,该损失函数非常适合比较两个概率分布,使用随机梯度下降 (stochastic gradient descent, SGD) 作为优化器。MNIST 数据集:(train_x, train_y), (test_x, test_y) = mnist.load_data()
train_x = train_x.reshape(60000, 784)
test_x = test_x.reshape(10000, 784)
train_y = keras.utils.to_categorical(train_y, 10)
test_y = keras.utils.to_categorical(test_y, 10)
# 模型创建
model = create_model()
# 模型训练
model.fit(train_x, train_y, batch_size=32, epochs=10, verbose=1)
# 模型保存
model.save("mnist-model.h5")
# 评估模型在测试数据集上的表现
accuracy = model.evaluate(x=test_x, y=test_y, batch_size=32)
# 打印准确率
print("Accuracy: ", accuracy[1])
def load_digit(image_name):
gray = cv2.imread(image_name, cv2.IMREAD_GRAYSCALE)
gray = cv2.resize(gray, (28, 28))
gray = gray.reshape((1, 784))
return gray
# 加载图片
test_digit_0 = load_digit("digit_0.png")
test_digit_1 = load_digit("digit_1.png")
test_digit_2 = load_digit("digit_2.png")
test_digit_3 = load_digit("digit_3.png")
imgs = np.array([test_digit_0, test_digit_1, test_digit_2, test_digit_3])
imgs = imgs.reshape(4, 784)
# 预测加载图像
prediction_class = model.predict_classes(imgs)
# 打印预测结果
print("Class: ", prediction_class)
Class: [0 1 2 3]
Keras 对深度学习进行了介绍。我们首先概述了用于图像分类和目标检测的深度学习架构。然后,我们介绍了 Keras,并通过示例训练了简单线性回归模型,介绍了如何利用 Keras 训练全连接网络识别手写数字。