OpenCV-Python实战(18)——深度学习简介与入门示例

0. 前言

深度学习已经成为机器学习中最受欢迎和发展最快的领域。自 2012 年深度学习性能超越机器学习等传统方法以来,深度学习架构开始快速应用于包括计算机视觉在内的众多领域。深度学习的常见应用包括语音识别、图像识别、自然语言处理、推荐系统等等。大多数现代深度学习架构都基于人工神经网络,深度学习中的“深”是指架构的层数。在本文中,首先介绍传统机器学习方法与深度学习间的差异,然后将介绍图像分类和对象检测中常见的深度学习架构,最后,将介绍深度学习Python库Keras,并通过实战来推开深度学习的大门。

1. 计算机视觉中的深度学习简介

深度学习推动了计算机视觉领域的深刻变革。我们首先解释深度学习中的关键概念,以便更好地了解深度学习的广阔世界。

1.1 深度学习的特点

在许多计算机视觉任务中,深度学习的性能优于传统机器学习方法,但在选择完成特定计算任务的方法时,应明确深度学习与传统机器学习方法的区别,以选择合适的方法。方法:

  • 传统的机器学习算法大多可以在低端机器上运行,而深度学习算法需要较高的算力才能正确训练,通常这些计算可以使用GPU进行优化并行计算
  • 当缺乏对特征工程的领域理解时,深度学习技术将是首选方法,因为在深度学习中,寻找相关特征的任务是通过减少特征工程问题来实现自动化的算法的一部分。特征工程是应用领域知识来创建特征检测器和提取器的过程,其目标是降低数据的复杂性,以便传统的机器学习方法可以正确学习。因此,传统机器学习算法的性能取决于识别和提取特征的准确性,而深度学习技术试图从数据中自动提取高级特征。
  • 传统机器学习和深度学习都能够处理海量数据集。但是这两种方法的主要区别在于它们的性能随着数据大小的增加而变化的程度。例如,在处理小型数据集时,深度学习算法难以在数据中找到映射,因此可能表现不佳,因为深度学习通常需要大量数据来调整其内部参数。根据经验,如果数据集很大,深度学习会优于其他技术,而当数据集较小时,传统的机器学习算法更可取。

机器学习和深度学习的主要区别可以用下图概括:

机器学习与深度学习的区别
从上图可以看出,机器学习和深度学习的关键选择点如下:

  • 计算资源(深度学习<-高算力计算机;机器学习<-低算力计算机)
  • 特征工程(深度学习<-同一步骤中的特征提取和目标任务;机器学习<-不同步骤中的特征提取和目标任务)
  • 数据集大小(深度学习 <- 大型或超大型数据集;机器学习 <- 小型或中型数据集)

1.2 深度学习大爆发

深度学习的概念可以追溯至 1986 年,但直到 2012 年深度学习性能超越传统机器学习时,才出现了深度学习的大爆发。ImageNet是一个大型视觉数据库,包含超过1400万张带有标签的高分辨率图像,包含20,000多个类别。因此,2012 年AlexNet架构在解决ImageNet大规模视觉识别挑战赛 (ILSVRC) 上的突破性进展通常被认为是深度学习大爆发的开始。

2. 用于图像分类的深度学习简介

继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准确率。

3. 用于目标检测的深度学习简介

目标检测是深度学习中的一个热门话题,其用于识别和定位图像中的多个对象。目标检测算法通常使用以下三个数据集进行基准测试:1)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领域中优秀的优化策略,从数据处理、主干网络、网络训练、激活函数、损失函数等各个方面都有着不同程度的优化。

4. 深度学习框架 keras 介绍与使用

在本节中,我们将通过两个简单示例来一窥深度学习的神秘面纱。在第一个示例中,构造输入数据来解决线性回归问题;在第二个示例中,使用 MNIST 数据集对手写数字进行分类。

4.1 keras 库简介与安装

Keras是用Python编写的开源高级神经网络API,它能够在TensorFlow、或Theano之上运行,其最大的特点是能够实现快速实验,因此本文利用它来进行深度学习实战。
要安装Keras,首先进行安装:

pip install keras

4.2 使用 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)

运行程序的结果如下图所示:

线性回归预测

4.3 使用 keras 进行手写数字识别

接下来,我们使用 Keras 识别手写数字,与第一个示例相同,首先需要构建模型:

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训练全连接网络识别手写数字。

系列链接

OpenCV-Python实战(1)——OpenCV简介与图像处理基础
OpenCV-Python实战(2)——图像与视频文件的处理
OpenCV-Python实战(3)——OpenCV中绘制图形与文本
OpenCV-Python实战(4)——OpenCV常见图像处理技术
OpenCV-Python实战(5)——OpenCV图像运算
OpenCV-Python实战(6)——OpenCV中的色彩空间和色彩映射
OpenCV-Python实战(7)——直方图详解
OpenCV-Python实战(8)——直方图均衡化
OpenCV-Python实战(9)——OpenCV用于图像分割的阈值技术
OpenCV-Python实战(10)——OpenCV轮廓检测
OpenCV-Python实战(11)——OpenCV轮廓检测相关应用
OpenCV-Python实战(12)——一文详解AR增强现实
OpenCV-Python实战(13)——OpenCV与机器学习的碰撞
OpenCV-Python实战(14)——人脸检测详解
OpenCV-Python实战(15)——面部特征点检测详解
OpenCV-Python实战(16)——人脸追踪详解
OpenCV-Python实战(17)——人脸识别详解

版权声明:本文为博主盼小辉丶原创文章,版权归属原作者,如果侵权,请联系我们删除!

原文链接:https://blog.csdn.net/LOVEmy134611/article/details/120070364

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
心中带点小风骚的头像心中带点小风骚普通用户
上一篇 2022年2月18日 下午3:46
下一篇 2022年2月18日 下午4:17

相关推荐