文章目录
- 一、VGG-16
- 二、残差网络
- 三、常用数据集
-
- 3.1MNIST
- 3.2Fashion-MNIST数据集
- [3.3CIFAR 10数据集](#3.3CIFAR 10数据集)
- [3.4PASCAL VOC数据集](#3.4PASCAL VOC数据集)
- [3.5MS COCO数据集](#3.5MS COCO数据集)
- 3.6ImageNet数据集与ILSVRC
- 四、深度学习视觉应用
一、VGG-16
- VGG-16 是一种由牛津大学的 Visual Geometry Group (VGG) 提出的卷积神经网络(CNN)架构。
- 它以其简单性和在图像分类任务中的有效性而闻名。
- "16" 表示网络中总共的权重层数,包括 13 个卷积层和 3 个全连接层。
1.1结构组成
- VGG-16 由一系列卷积层和接着的最大池化层组成,最后是三个全连接层。
![[Pasted image 20240408160826.png]]
![[Pasted image 20240408160914.png]]
卷积层
- VGG-16 中的卷积层使用 3x3 的滤波器,并且步幅为 1,它们使用 'same' 填充以确保输入和输出的空间维度保持不变。
最大池化
- 在每个卷积层块之后,VGG-16 使用最大池化层,其滤波器大小为 2x2,步幅为 2。这有助于减小特征图的空间维度,同时保留最重要的信息。
激活函数
- 在整个网络中,除了输出层外,每个卷积层和全连接层后都使用修正线性单元(ReLU)激活函数,对于多类别分类任务,输出层通常使用 softmax。
全连接层 - VGG-16 的最后三层是全连接层。前两个全连接层各有 4096 个单元,然后是一个具有 1000 个单元的全连接层,这通常是 ImageNet 数据集的输出层,因为 VGG-16 最初是在 ImageNet 上进行图像分类训练的。
Dropout
为了防止过拟合,在前两个全连接层之后应用了 dropout 正则化,丢弃概率为 0.5。
1.2应用场景
- VGG-16 在计算机视觉领域有许多应用场景,其中包括但不限于以下几个方面
-
图像分类:最初,VGG-16 是设计用于图像分类任务的。它在 ImageNet 数据集上进行了训练,并且在该任务上表现出色。因此,它可以应用于各种需要对图像进行分类的场景,如物体识别、动物识别、植物分类等。
-
特征提取:VGG-16 的卷积部分可以用作特征提取器。通过移除全连接层,并仅使用卷积和池化层,可以将其作为预训练模型应用于其他计算机视觉任务,例如目标检测、图像分割等。在这种情况下,卷积部分的特征提取能力是其主要价值所在。
-
图像风格转换:VGG-16 在图像风格转换任务中也有应用。通过将其作为特征提取器,并将输入图像和目标风格图像的特征表示之间的差异最小化,可以生成具有目标风格的图像。
-
图像检索:VGG-16 的特征表示可以用于图像检索任务。通过将图像转换为其在 VGG-16 中的特征向量,并计算这些特征向量之间的相似性,可以实现图像检索,找到与给定查询图像相似的图像。
-
医学影像分析:在医学影像分析领域,VGG-16 可以用于诊断支持、疾病检测和分割等任务。例如,它可以用于识别 X 射线图像中的疾病迹象,或者对病理切片图像进行细胞分类。
1.3简单例子
python
import tensorflow as tf
from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, Flatten, Dense, Dropout
from tensorflow.keras.models import Model
def VGG_16(input_shape=(224, 224, 3), num_classes=1000):
# 输入层
inputs = Input(shape=input_shape)
# 第一组卷积层(包括两个卷积层和一个最大池化层)
x = Conv2D(64, (3, 3), activation='relu', padding='same')(inputs)
x = Conv2D(64, (3, 3), activation='relu', padding='same')(x)
x = MaxPooling2D((2, 2), strides=(2, 2))(x)
# 第二组卷积层
x = Conv2D(128, (3, 3), activation='relu', padding='same')(x)
x = Conv2D(128, (3, 3), activation='relu', padding='same')(x)
x = MaxPooling2D((2, 2), strides=(2, 2))(x)
# 第三组卷积层
x = Conv2D(256, (3, 3), activation='relu', padding='same')(x)
x = Conv2D(256, (3, 3), activation='relu', padding='same')(x)
x = Conv2D(256, (3, 3), activation='relu', padding='same')(x)
x = MaxPooling2D((2, 2), strides=(2, 2))(x)
# 第四组卷积层
x = Conv2D(512, (3, 3), activation='relu', padding='same')(x)
x = Conv2D(512, (3, 3), activation='relu', padding='same')(x)
x = Conv2D(512, (3, 3), activation='relu', padding='same')(x)
x = MaxPooling2D((2, 2), strides=(2, 2))(x)
# 第五组卷积层
x = Conv2D(512, (3, 3), activation='relu', padding='same')(x)
x = Conv2D(512, (3, 3), activation='relu', padding='same')(x)
x = Conv2D(512, (3, 3), activation='relu', padding='same')(x)
x = MaxPooling2D((2, 2), strides=(2, 2))(x)
# 全连接层
x = Flatten()(x)
x = Dense(4096, activation='relu')(x)
x = Dropout(0.5)(x)
x = Dense(4096, activation='relu')(x)
x = Dropout(0.5)(x)
outputs = Dense(num_classes, activation='softmax')(x)
# 创建模型
model = Model(inputs, outputs, name='VGG-16')
return model
# 创建 VGG-16 模型
vgg16_model = VGG_16()
# 打印模型摘要
vgg16_model.summary()
输出结果
python
Model: "VGG-16"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) [(None, 224, 224, 3)] 0
conv2d (Conv2D) (None, 224, 224, 64) 1792
conv2d_1 (Conv2D) (None, 224, 224, 64) 36928
max_pooling2d (MaxPooling2 (None, 112, 112, 64) 0
D)
conv2d_2 (Conv2D) (None, 112, 112, 128) 73856
conv2d_3 (Conv2D) (None, 112, 112, 128) 147584
max_pooling2d_1 (MaxPoolin (None, 56, 56, 128) 0
g2D)
conv2d_4 (Conv2D) (None, 56, 56, 256) 295168
conv2d_5 (Conv2D) (None, 56, 56, 256) 590080
conv2d_6 (Conv2D) (None, 56, 56, 256) 590080
max_pooling2d_2 (MaxPoolin (None, 28, 28, 256) 0
g2D)
conv2d_7 (Conv2D) (None, 28, 28, 512) 1180160
conv2d_8 (Conv2D) (None, 28, 28, 512) 2359808
conv2d_9 (Conv2D) (None, 28, 28, 512) 2359808
max_pooling2d_3 (MaxPoolin (None, 14, 14, 512) 0
g2D)
conv2d_10 (Conv2D) (None, 14, 14, 512) 2359808
conv2d_11 (Conv2D) (None, 14, 14, 512) 2359808
conv2d_12 (Conv2D) (None, 14, 14, 512) 2359808
max_pooling2d_4 (MaxPoolin (None, 7, 7, 512) 0
g2D)
flatten (Flatten) (None, 25088) 0
dense (Dense) (None, 4096) 102764544
dropout (Dropout) (None, 4096) 0
dense_1 (Dense) (None, 4096) 16781312
dropout_1 (Dropout) (None, 4096) 0
dense_2 (Dense) (None, 1000) 4097000
=================================================================
Total params: 138357544 (527.79 MB)
Trainable params: 138357544 (527.79 MB)
Non-trainable params: 0 (0.00 Byte)
_________________________________________________________________
Process finished with exit code 0
二、残差网络
2.1非残差网络的缺陷
![[Pasted image 20240408162627.png]]
- 非残差网络(例如传统的卷积神经网络,如VGG、LeNet等)虽然在一定程度上取得了成功,但也存在一些缺陷,这些缺陷可能在一定程度上限制了它们的性能和应用范围。以下是一些非残差网络的缺陷:
-
梯度消失和梯度爆炸:在非残差网络中,随着网络层数的增加,反向传播过程中容易出现梯度消失或梯度爆炸的问题。这可能导致训练过程变得困难,甚至导致模型无法收敛。
-
难以训练深层网络:由于梯度消失和梯度爆炸问题,非残差网络在训练深层网络时会遇到困难。更深的网络需要更多的层来提取抽象特征,但非残差网络的性能在深层网络中可能会下降,因为梯度传播的效果变得更加不稳定。
-
网络性能饱和:随着网络层数的增加,非残差网络的性能可能会饱和或下降,而不是继续提高。这意味着增加网络深度不能简单地提高性能,而可能需要采取其他方法来改进网络结构。
-
特征传递限制:在非残差网络中,特征必须逐层传递,没有直接的路径可以将低层特征直接传递到高层。这可能会导致信息的丢失或模糊化,使得网络难以捕捉不同层次的语义信息。
-
参数浪费:非残差网络中,由于特征无法直接传递,每一层都需要学习如何从前一层的输出中提取有用的特征。这可能导致参数的冗余和浪费,因为一些层可能会学习到与前一层类似的特征,从而增加了训练的复杂性和计算成本。
2.2梯度消失原因
梯度消失是深度神经网络训练过程中的一种常见问题,主要原因可以归结为以下几点:
-
激活函数的饱和性:深度神经网络通常使用的激活函数(如Sigmoid、Tanh)在输入值较大或较小时会饱和,导致梯度接近于零。在反向传播过程中,这些饱和的激活函数会使得梯度在传播过程中逐渐变小,最终消失。
-
网络结构和参数初始化:深度神经网络的结构和参数初始化也可能导致梯度消失。如果网络的权重初始化不合适,那么在反向传播过程中,梯度可能会在层与层之间逐渐减小,导致梯度消失。
-
链式求导的乘积效应:在深度网络中,梯度是通过链式求导来计算的。由于每个节点都涉及到梯度的乘积,这可能会导致乘积效应,使得梯度在传播过程中逐渐减小,最终消失。
-
不适当的优化器和学习率:使用不适当的优化器或学习率可能导致梯度消失。例如,如果学习率设置过大,可能会导致梯度爆炸;而如果学习率设置过小,可能会导致梯度消失。
-
长期依赖性问题:在循环神经网络(RNN)等网络中,长期依赖性问题也可能导致梯度消失。当网络需要学习长时间序列的依赖关系时,梯度在反向传播过程中可能会逐渐消失,导致网络难以捕捉到长期的依赖关系。
2.3残差网络的优势
- 残差网络通过引入残差连接,有效地解决了传统非残差网络在训练深度网络时所面临的梯度消失和梯度爆炸等问题,提高了网络的性能、泛化能力和训练效率。这些优势使得残差网络成为深度学习领域中广泛应用的重要模型之一。
- 解决梯度消失和梯度爆炸问题
- 通过引入残差连接(skip connections),残差网络允许信息在网络中跳跃传递。这样的设计使得梯度能够更轻松地反向传播到较浅的层,从而缓解了梯度消失和梯度爆炸问题,有助于训练更深的网络。
- 易于优化和训练
- 由于残差网络的梯度更容易传播,训练深度网络变得更加简单和高效。这使得可以更容易地训练出准确性能更好的模型,同时减少了调参的复杂性。
- 提高网络性能
- 通过增加网络的深度,残差网络能够提高网络的表征能力。相较于同样深度的非残差网络,残差网络能够更有效地提取和学习复杂的特征,从而提高了模型的性能和泛化能力。
- 减少参数数量
- 残差连接允许直接跳跃传递特征,这种机制减少了需要学习的参数数量。相对于非残差网络,残差网络通常具有更少的参数量,从而减少了过拟合的风险,并且使得训练和推理速度更快。
- 提高梯度传播的稳定性
- 残差连接允许梯度直接反向传播到浅层,使得梯度传播更加稳定。这有助于减少梯度在网络中的消失或爆炸,从而使得训练更加稳定和可靠。
2.4简单例子
- 这段代码实现了一个简化的 ResNet 模型,其中包含了基本的残差块,构建了一个包含5个阶段的网络。每个阶段包含若干个残差块,用于提取不同层次的特征。最后通过全局平均池化和全连接层进行分类。
python
import tensorflow as tf
from tensorflow.keras.layers import Input, Conv2D, BatchNormalization, Activation, Add, MaxPooling2D, AveragePooling2D, \
Flatten, Dense
from tensorflow.keras.models import Model
def residual_block(x, filters, kernel_size=(3, 3), strides=(1, 1), activation='relu'):
y = Conv2D(filters, kernel_size=kernel_size, strides=strides, padding='same')(x)
y = BatchNormalization()(y)
y = Activation(activation)(y)
y = Conv2D(filters, kernel_size=kernel_size, strides=(1, 1), padding='same')(y)
y = BatchNormalization()(y)
if strides != (1, 1) or x.shape[-1] != filters:
x = Conv2D(filters, kernel_size=(1, 1), strides=strides, padding='same')(x)
out = Add()([x, y])
out = Activation(activation)(out)
return out
def ResNet(input_shape=(224, 224, 3), num_classes=1000):
inputs = Input(shape=input_shape)
# Conv1
x = Conv2D(64, kernel_size=(7, 7), strides=(2, 2), padding='same')(inputs)
x = BatchNormalization()(x)
x = Activation('relu')(x)
x = MaxPooling2D(pool_size=(3, 3), strides=(2, 2), padding='same')(x)
# Conv2_x
x = residual_block(x, filters=64)
x = residual_block(x, filters=64)
# Conv3_x
x = residual_block(x, filters=128, strides=(2, 2))
x = residual_block(x, filters=128)
# Conv4_x
x = residual_block(x, filters=256, strides=(2, 2))
x = residual_block(x, filters=256)
# Conv5_x
x = residual_block(x, filters=512, strides=(2, 2))
x = residual_block(x, filters=512)
x = AveragePooling2D(pool_size=(7, 7))(x)
x = Flatten()(x)
outputs = Dense(num_classes, activation='softmax')(x)
model = Model(inputs, outputs, name='ResNet')
return model
# Create ResNet model
resnet_model = ResNet()
# Print model summary
resnet_model.summary()
- 输出结果
python
Model: "ResNet"
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_1 (InputLayer) [(None, 224, 224, 3)] 0 []
conv2d (Conv2D) (None, 112, 112, 64) 9472 ['input_1[0][0]']
batch_normalization (Batch (None, 112, 112, 64) 256 ['conv2d[0][0]']
Normalization)
activation (Activation) (None, 112, 112, 64) 0 ['batch_normalization[0][0]']
max_pooling2d (MaxPooling2 (None, 56, 56, 64) 0 ['activation[0][0]']
D)
conv2d_1 (Conv2D) (None, 56, 56, 64) 36928 ['max_pooling2d[0][0]']
batch_normalization_1 (Bat (None, 56, 56, 64) 256 ['conv2d_1[0][0]']
chNormalization)
activation_1 (Activation) (None, 56, 56, 64) 0 ['batch_normalization_1[0][0]'
]
conv2d_2 (Conv2D) (None, 56, 56, 64) 36928 ['activation_1[0][0]']
batch_normalization_2 (Bat (None, 56, 56, 64) 256 ['conv2d_2[0][0]']
chNormalization)
add (Add) (None, 56, 56, 64) 0 ['max_pooling2d[0][0]',
'batch_normalization_2[0][0]'
]
activation_2 (Activation) (None, 56, 56, 64) 0 ['add[0][0]']
conv2d_3 (Conv2D) (None, 56, 56, 64) 36928 ['activation_2[0][0]']
batch_normalization_3 (Bat (None, 56, 56, 64) 256 ['conv2d_3[0][0]']
chNormalization)
activation_3 (Activation) (None, 56, 56, 64) 0 ['batch_normalization_3[0][0]'
]
conv2d_4 (Conv2D) (None, 56, 56, 64) 36928 ['activation_3[0][0]']
batch_normalization_4 (Bat (None, 56, 56, 64) 256 ['conv2d_4[0][0]']
chNormalization)
add_1 (Add) (None, 56, 56, 64) 0 ['activation_2[0][0]',
'batch_normalization_4[0][0]'
]
activation_4 (Activation) (None, 56, 56, 64) 0 ['add_1[0][0]']
conv2d_5 (Conv2D) (None, 28, 28, 128) 73856 ['activation_4[0][0]']
batch_normalization_5 (Bat (None, 28, 28, 128) 512 ['conv2d_5[0][0]']
chNormalization)
activation_5 (Activation) (None, 28, 28, 128) 0 ['batch_normalization_5[0][0]'
]
conv2d_6 (Conv2D) (None, 28, 28, 128) 147584 ['activation_5[0][0]']
conv2d_7 (Conv2D) (None, 28, 28, 128) 8320 ['activation_4[0][0]']
batch_normalization_6 (Bat (None, 28, 28, 128) 512 ['conv2d_6[0][0]']
chNormalization)
add_2 (Add) (None, 28, 28, 128) 0 ['conv2d_7[0][0]',
'batch_normalization_6[0][0]'
]
activation_6 (Activation) (None, 28, 28, 128) 0 ['add_2[0][0]']
conv2d_8 (Conv2D) (None, 28, 28, 128) 147584 ['activation_6[0][0]']
batch_normalization_7 (Bat (None, 28, 28, 128) 512 ['conv2d_8[0][0]']
chNormalization)
activation_7 (Activation) (None, 28, 28, 128) 0 ['batch_normalization_7[0][0]'
]
conv2d_9 (Conv2D) (None, 28, 28, 128) 147584 ['activation_7[0][0]']
batch_normalization_8 (Bat (None, 28, 28, 128) 512 ['conv2d_9[0][0]']
chNormalization)
add_3 (Add) (None, 28, 28, 128) 0 ['activation_6[0][0]',
'batch_normalization_8[0][0]'
]
activation_8 (Activation) (None, 28, 28, 128) 0 ['add_3[0][0]']
conv2d_10 (Conv2D) (None, 14, 14, 256) 295168 ['activation_8[0][0]']
batch_normalization_9 (Bat (None, 14, 14, 256) 1024 ['conv2d_10[0][0]']
chNormalization)
activation_9 (Activation) (None, 14, 14, 256) 0 ['batch_normalization_9[0][0]'
]
conv2d_11 (Conv2D) (None, 14, 14, 256) 590080 ['activation_9[0][0]']
conv2d_12 (Conv2D) (None, 14, 14, 256) 33024 ['activation_8[0][0]']
batch_normalization_10 (Ba (None, 14, 14, 256) 1024 ['conv2d_11[0][0]']
tchNormalization)
add_4 (Add) (None, 14, 14, 256) 0 ['conv2d_12[0][0]',
'batch_normalization_10[0][0]
']
activation_10 (Activation) (None, 14, 14, 256) 0 ['add_4[0][0]']
conv2d_13 (Conv2D) (None, 14, 14, 256) 590080 ['activation_10[0][0]']
batch_normalization_11 (Ba (None, 14, 14, 256) 1024 ['conv2d_13[0][0]']
tchNormalization)
activation_11 (Activation) (None, 14, 14, 256) 0 ['batch_normalization_11[0][0]
']
conv2d_14 (Conv2D) (None, 14, 14, 256) 590080 ['activation_11[0][0]']
batch_normalization_12 (Ba (None, 14, 14, 256) 1024 ['conv2d_14[0][0]']
tchNormalization)
add_5 (Add) (None, 14, 14, 256) 0 ['activation_10[0][0]',
'batch_normalization_12[0][0]
']
activation_12 (Activation) (None, 14, 14, 256) 0 ['add_5[0][0]']
conv2d_15 (Conv2D) (None, 7, 7, 512) 1180160 ['activation_12[0][0]']
batch_normalization_13 (Ba (None, 7, 7, 512) 2048 ['conv2d_15[0][0]']
tchNormalization)
activation_13 (Activation) (None, 7, 7, 512) 0 ['batch_normalization_13[0][0]
']
conv2d_16 (Conv2D) (None, 7, 7, 512) 2359808 ['activation_13[0][0]']
conv2d_17 (Conv2D) (None, 7, 7, 512) 131584 ['activation_12[0][0]']
batch_normalization_14 (Ba (None, 7, 7, 512) 2048 ['conv2d_16[0][0]']
tchNormalization)
add_6 (Add) (None, 7, 7, 512) 0 ['conv2d_17[0][0]',
'batch_normalization_14[0][0]
']
activation_14 (Activation) (None, 7, 7, 512) 0 ['add_6[0][0]']
conv2d_18 (Conv2D) (None, 7, 7, 512) 2359808 ['activation_14[0][0]']
batch_normalization_15 (Ba (None, 7, 7, 512) 2048 ['conv2d_18[0][0]']
tchNormalization)
activation_15 (Activation) (None, 7, 7, 512) 0 ['batch_normalization_15[0][0]
']
conv2d_19 (Conv2D) (None, 7, 7, 512) 2359808 ['activation_15[0][0]']
batch_normalization_16 (Ba (None, 7, 7, 512) 2048 ['conv2d_19[0][0]']
tchNormalization)
add_7 (Add) (None, 7, 7, 512) 0 ['activation_14[0][0]',
'batch_normalization_16[0][0]
']
activation_16 (Activation) (None, 7, 7, 512) 0 ['add_7[0][0]']
average_pooling2d (Average (None, 1, 1, 512) 0 ['activation_16[0][0]']
Pooling2D)
flatten (Flatten) (None, 512) 0 ['average_pooling2d[0][0]']
dense (Dense) (None, 1000) 513000 ['flatten[0][0]']
==================================================================================================
Total params: 11700328 (44.63 MB)
Trainable params: 11692520 (44.60 MB)
Non-trainable params: 7808 (30.50 KB)
__________________________________________________________________________________________________
Process finished with exit code 0
三、常用数据集
3.1MNIST
-
MNIST数据集是一个常用的手写数字识别数据集,它包含了来自250个不同人手写的0到9的数字图片。每张图片都是灰度图像,尺寸为28x28像素。
-
原始的 MNIST 数据库一共包含下面 4 个文件
![[Pasted image 20240408171823.png]]
-
在Python中,可以使用TensorFlow或者其他深度学习框架来加载MNIST数据集。以下是使用TensorFlow加载MNIST数据集的示例代码
python
import tensorflow as tf
# 加载MNIST数据集
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
# 对数据进行归一化
x_train, x_test = x_train / 255.0, x_test / 255.0
# 输出训练集和测试集的大小
print("训练集大小:", x_train.shape, y_train.shape)
print("测试集大小:", x_test.shape, y_test.shape)
3.2Fashion-MNIST数据集
- FashionMNIST 是一个替代 MNIST 手写数字集 的图像数据集。 它是由 Zalando旗下的研究部门提供,涵盖了来自 10 种类别的 共 7 万个不同商品的正面图片。
- FashionMNIST 的大小、格式和训练集/测试集划分与原始的 MNIST 完全一致。60000/10000 的训练测试数据划分,28x28 的灰度图片。你可以直接用它来测试你的机器学习和深度学习 算法性能,且不需要改动任何的代码。
python
import tensorflow as tf
# 加载Fashion-MNIST数据集
fashion_mnist = tf.keras.datasets.fashion_mnist
(x_train, y_train), (x_test, y_test) = fashion_mnist.load_data()
# 对数据进行归一化
x_train, x_test = x_train / 255.0, x_test / 255.0
# 输出训练集和测试集的大小
print("训练集大小:", x_train.shape, y_train.shape)
print("测试集大小:", x_test.shape, y_test.shape)
3.3CIFAR 10数据集
- CIFAR-10数据集由10个类的60000个32x32彩色图像组成,每 个类有6000个图像。有50000个训练图像和10000个测试图像
- 数据集分为五个训练批次和一个测试批次,每个批次有10000 个图像。测试批次包含来自每个类别的恰好1000个随机选择的 图像
python
import tensorflow as tf
# 加载CIFAR-10数据集
cifar10 = tf.keras.datasets.cifar10
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
# 对数据进行归一化
x_train, x_test = x_train / 255.0, x_test / 255.0
# 输出训练集和测试集的大小
print("训练集大小:", x_train.shape, y_train.shape)
print("测试集大小:", x_test.shape, y_test.shape)
3.4PASCAL VOC数据集
- PASCAL VOC(Visual Object Classes)数据集是一个用于目标检测、图像分割和图像分类的经典数据集之一。它包含了大量的图像,每个图像都标注了多个对象的位置和类别信息。PASCAL VOC数据集最初用于PASCAL VOC挑战赛,该挑战赛旨在推动计算机视觉领域的发展。
- PASCAL VOC数据集包含了20个不同的类别,包括人、动物、车辆、家具等。每个图像都标注了对象的边界框和类别标签。该数据集通常用于训练和评估目标检测和图像分割模型。
python
import tensorflow as tf
import tensorflow_datasets as tfds
# 加载PASCAL VOC数据集
dataset, info = tfds.load('voc/2007', split='train', with_info=True)
# 打印数据集信息
print(info)
# 显示数据集中的前几个示例
for example in dataset.take(5):
image, label = example["image"], example["objects"]["label"]
print("Image shape:", image.shape)
print("Labels:", label)
3.5MS COCO数据集
-
PASCAL的全称是Microsoft Common Objects in Context,起源 于微软于2014年出资标注的Microsoft COCO数据集
-
数据集以scene understanding为目标,主要从复杂的日常场景中 截取
-
包含目标分类(识别)、检测、分割、语义标注等数据集
-
ImageNet竞赛停办后,COCO竞赛就成为是当前目标识别、检 测等领域的一个最权威、最重要的标杆
-
提供的标注类别有80 类,有超过33 万张图片,其中20 万张有 标注,整个数据集中个体的数目超过150 万个。
- 人:1类
- 交通工具:8类,自行车,汽车等
- 公路常见:5类,信号灯,停车标志等
- 动物:10类,猫狗等
- 携带物品:5类,背包,雨伞等
- 运动器材:10类,飞盘,滑雪板,网球拍等。
- 厨房餐具:7类,瓶子,勺子等
- 水果及食品:10类
- 家庭用品:7类,椅子、床,电视等
- 家庭常见物品:17类,笔记本,鼠标,遥控器等
3.6ImageNet数据集与ILSVRC
ImageNet数据集
- 始于2009年,李飞飞与Google的合作: "ImageNet: A Large-Scale Hierarchical Image Database"
- 总图像数据:14,197,122
- 总类别数:21841
- 带有标记框的图像数:1,034,908
ISLVRC 2012子数据集
- 训练集:1,281,167张图片+标签
- 类别数:1,000
- 验证集:50,000张图片+标签
- 测试集:100,000张图片
四、深度学习视觉应用
4.1评价指标
算法评估相关概念
TP: 被正确地划分为正例的个数,即实际为正例且被分类器划分为正例的实例数
FP: 被错误地划分为正例的个数,即实际为负例但被分类器划分为正例的实例数
FN:被错误地划分为负例的个数,即实际为正例但被分类器划分为负例的实例数
TN: 被正确地划分为负例的个数,即实际为负例且被分类器划分为负例的实例数
P(精确率): 𝑇𝑃/(𝑇𝑃 + 𝐹𝑃),标识"挑剔"的程度
R(召回率): 𝑇𝑃/(𝑇𝑃 + 𝐹𝑁)。召回率越高,准确度越低 标识"通过"的程度
精度(Accuracy): (𝑇𝑃 + 𝑇𝑁)/(𝑇𝑃 + 𝐹𝑃 + 𝑇𝑁 + 𝐹𝑁)
P-R的关系曲线图:
- 表示了召回率和准确率之间的关系,精度(准确率)越高,召回率越低。
置信度与准确率:
- 可以通过改变阈值(也可以看作上下移动蓝色的虚线),来选择 让系统识别能出多少个图片,当然阈值的变化会导致Precision与 Recall值发生变化。比如,把蓝色虚线放到第一张图片下面,也就 是说让系统只识别出最上面的那张飞机图片,那么Precision的值就 是100%,而Recall的值则是20%。如果把蓝色虚线放到第二张图片 下面,也就是说让系统只识别出最上面的前两张图片,那么 Precision的值还是100%,而Recall的值则增长到是40%。
AP计算:
- mAP:均值平均准确率
- AP(Average Precision)计算是机器学习领域,特别是在信息检索和推荐系统中常用的一个指标,用于衡量模型预测结果的质量。它结合了精确率(Precision)和召回率(Recall),能够更全面地评估模型在不同召回率水平下的性能。
- AP计算的基本步骤包括:
- 对于每个可能的类别或标签,计算精确率-召回率曲线(Precision-Recall Curve)。这通常涉及到对模型的预测结果进行排序,并计算在不同召回率水平下的精确率。
- 对于每个类别,计算该曲线下的面积(Area Under Curve, AUC),即AP值。这可以通过对精确率-召回率曲线进行积分来实现。
- 如果有多个类别,通常还会计算所有类别的平均AP值(mAP,mean Average Precision),以便对整个模型的性能进行总体评估。
- 理论上,可以使用积分的方法来计算AP,公式如下:
A P = ∫ 0 1 P ( r ) d r AP = ∫₀¹ P(r) dr AP=∫01P(r)dr
其中,P®表示召回率r处的精确率。然而,在实际应用中,由于数据点的离散性,通常使用近似或插值的方法来计算AP。
另外,在一些特定的场景下,AP也可以通过另一种方式计算,即计算每个位置的准确率,然后求取平均值。具体公式为:
A P = ( P 1 + P 2 + . . . + P n ) / n AP = (P₁ + P₂ + ... + Pₙ) / n AP=(P1+P2+...+Pn)/n
其中,Pᵢ表示在前i个位置的准确率,n表示搜索结果的总数。
mAP计算:
- mAP(mean Average Precision)是机器学习领域,特别是在目标检测和信息检索中常用的一个评估指标。它衡量的是模型在所有类别上的平均精确率-召回率曲线下的面积。
- mAP的计算过程通常包括以下几个步骤:
- 确定IOU阈值:在计算mAP之前,需要设定一个IOU(Intersection over Union)阈值,用于判断预测框与真实框之间的重叠程度。只有当预测框与真实框的IOU值大于或等于这个阈值时,才认为预测是正确的。
- 计算每一类的AP值:对于每个类别,首先计算其精确率-召回率曲线。这通常涉及到对模型预测结果进行排序,并计算在不同召回率水平下的精确率。然后,计算该曲线下的面积,即该类的AP值。AP值反映了该类平衡精确率和召回率的能力。
- 计算mAP:将所有类别的AP值进行平均,得到mAP。mAP是一个全局指标,用于衡量模型在所有类别上的平均性能。
- 需要注意的是,mAP的具体计算方法可能因不同的数据集和评估标准而有所差异。此外,在计算mAP时,还需要考虑一些其他因素,如正负样本的比例、模型的置信度阈值等。
- mAP在信息检索和推荐系统等领域也有广泛的应用。在推荐系统中,mAP考虑了推荐结果的排序准确性,对推荐结果的完整性要求较低,并且可以评估推荐结果的多样性。因此,mAP是一个非常有用的评估指标,可以帮助我们更全面地了解模型的性能。
4.2目标检测与YOLO
目标检测问题:
- 目标检测是计算机视觉领域的核心问题之一,其主要任务是找出图像中所有感兴趣的目标(物体),确定它们的类别和位置。由于各类物体有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具有挑战性的问题。
- 在目标检测中,常常会遇到数据不平衡问题,即某些类别的样本数量远远多于其他类别,这可能是由于数据采集过程中的偏差,或者是某些类别在实际场景中出现的频率较高所致。数据不平衡问题可能导致模型偏向常见类别,忽略罕见类别的检测,从而降低整体性能。
- 尺度变化也是目标检测中面临的一个挑战。小物体在图像中与较大物体相比呈现出较大的尺度变化,这可能导致模型在检测小物体时遇到困难。训练数据偏置也可能影响目标检测的性能,当数据集主要关注较大对象时,较小对象的检测精度可能会受到影响。
- 为了解决这些问题,研究者们提出了许多不同的目标检测算法,例如YOLO系列、Faster R-CNN等。这些算法通过改进模型结构、优化训练过程或使用更精细的数据标注技术等方式,提高了目标检测的准确性和效率。
目标检测问题的发展:
- 手工特征到深度学习特征的转变:早期的目标检测算法主要基于手工特征,如Viola-Jones检测器,通过设计复杂的特征提取方法来实现目标检测。然而,这种方法在特征表达能力上有限,且计算资源需求大。随着深度学习的兴起,目标检测算法开始利用神经网络自动学习图像特征,大大提高了特征表达的准确性和效率。
- 从两阶段到一阶段算法的发展:经典的目标检测算法,如Faster R-CNN,采用两阶段的方法,即先生成候选框,再进行分类和回归。这种方法精度高,但速度相对较慢。后来,一些一阶段的算法,如YOLO和SSD,通过直接对图像进行回归和分类,实现了更高的检测速度,同时保持了一定的准确性。
- 多尺度、多模态检测:随着研究的深入,目标检测算法开始关注多尺度目标检测,即能够同时检测不同大小的目标。此外,跨模态目标检测也逐渐成为研究热点,例如利用文本信息辅助图像中的目标检测。
- 与其他技术的融合:目标检测算法还与其他先进技术进行了融合,如强化学习和自然语言处理。这些技术的引入使得目标检测算法在准确性、速度和适用性上都有了质的飞跃,为各行各业带来了巨大的改变。
YOLO(You Only Look Once):
- 一种实时目标检测算法,由Joseph Redmon等人在2015年提出。YOLO的核心思想是将目标检测任务看作一个回归问题,从而实现了端到端的目标检测,极大地提高了检测速度。
- YOLO算法的主要特点包括:
- 快速性:YOLO将目标检测任务转换为单次前向传播,通过一次查看输入图像即可直接预测出目标的边界框和类别概率,从而实现了实时检测。这使得YOLO在检测速度上相较于传统方法有了显著的提升。
- 全局性:YOLO在训练时考虑了整幅图像的信息,因此在预测时可以利用全局上下文信息,有助于减少背景错误的预测。
- 易于优化:由于YOLO将检测任务转换为回归问题,因此可以使用常见的优化算法进行训练,使得模型更容易收敛。
- YOLO也存在一些局限性:
- 例如对于小目标的检测效果可能不佳,以及在密集场景中的检测精度可能受到影响。为了解决这些问题,后续的YOLO版本(如YOLOv2、YOLOv3和YOLOv4等)进行了改进和优化,提高了检测精度和性能。
4.3语义分割
- 语义分割是一种图像分割技术,其核心任务是对图像中的每个像素进行类别上的分类。与实例分割不同,语义分割并不区分同一类别的不同个体。在语义分割中,每个像素都被赋予一个特定的标签,如道路、车辆、行人等,从而实现对图像内容的精细化理解。
- 语义分割技术具有广泛的应用场景,包括但不限于:
- 自动驾驶汽车:语义分割技术可以帮助自动驾驶汽车识别道路、车辆、行人等物体,从而提高行驶的安全性和效率。
- 机器人视觉:通过语义分割,机器人可以更好地感知和识别周围环境,执行诸如智能导航和物品抓取等任务。
- 医学图像分析:语义分割能够高效分离医学图像中的像素,为医生提供更精准的诊断和治疗依据,如肿瘤位置的确定和器官结构的识别。
- 安防监控系统:利用语义分割技术,监控系统可以对视频画面进行实时识别与跟踪,实现更精细的行为分析和预测。
- 遥感影像分析:语义分割可以快速、准确地识别遥感影像中的不同地表覆盖,为城市规划、资源管理提供数据支持。
4.4风格迁移
- 风格迁移是一种深度学习技术,它能让一张图片的内容不发生改变,但样式改为另一张图片的效果。这种技术基于神经网络和深度学习算法,通常采用的是卷积神经网络(CNN)。通过层层堆叠的卷积和池化操作,神经网络能够提取图像的特征信息,并学习并理解图像的风格和内容。
- 在风格迁移技术中,图像的风格和内容分别由神经网络中的不同层次表示。风格表示捕捉了图像中的纹理、色彩等特征,而内容表示则关注于图像的物体形状和结构。通过对两种表示的提取和比较,可以将一个图像的风格应用到另一个图像的内容上。常见的损失函数包括风格损失和内容损失,它们基于风格表示和内容表示之间的距离计算。通过最小化损失函数,可以调整生成图像的像素值,逐渐接近目标图像的风格和内容,从而实现风格迁移的效果。
- 风格迁移技术为艺术家提供了一种新的创作思路和灵感来源,通过将不同风格的图像进行迁移和组合,获得全新的艺术效果和创意。此外,这项技术还为文化交流和跨界合作提供了契机,通过将不同国家、地区或时期的艺术风格进行迁移和融合,创造出独特的、具有文化多样性的艺术作品。在广告、设计和媒体等领域,风格迁移技术也可以应用于视觉增强和品牌塑造,通过将公司或产品的标志性风格应用到图像中,营造出独特的视觉效果,增强品牌识别度和吸引力。
4.5视觉应用展望
生成对抗网络:
- 生成对抗网络(GANs,Generative Adversarial Networks)是一种深度学习模型,其核心思想是通过对抗训练的方式来使得生成网络产生的样本服从真实数据分布。它由两个网络组成:生成器和判别器。生成器的任务是从随机噪声中生成尽可能真实的图像,而判别器的任务则是区分输入的图像是来自真实数据集还是生成器产生的。这两个网络在训练过程中相互对抗,生成器不断学习如何产生更加逼真的图像以欺骗判别器,而判别器则不断提高其识别真伪图像的能力。通过这种对抗训练,生成器最终能够生成高质量、高逼真度的图像。
- 自2014年由Ian Goodfellow及其同事首次提出以来,GANs以其独特的对抗性训练机制和卓越的图像生成能力,迅速成为计算机视觉和机器学习领域的研究热点。它不仅在图像生成方面取得了显著进展,还在图像翻译、视频生成、自然语言处理等多个领域得到了广泛应用。然而,GANs仍然面临着一些挑战,如训练不稳定、模型收敛慢等。
- 随着技术的不断发展,GANs的性能和稳定性得到了进一步的提升。研究者们通过改进网络结构、优化训练算法等方式,提高了GANs的生成质量和效率。同时,新的应用场景也不断涌现,如利用GANs进行艺术创作、虚拟现实、增强现实等,为人们的生活带来了更多的可能性和创意