教程|从基本概念到实现,全卷积网络实现更简洁的图像识别
作者头像
  • 机器人之家
  • 2022-03-15 10:00:18 4

众所周知,图像本质上是由像素值构成的集合,这一观点对于计算机科学家和研究人员来说至关重要,因为它帮助他们构建出能够模拟人类大脑并具备特定功能的神经网络。有时,这样的神经网络甚至可以超越人类的表现。

上图很好地展示了图像由像素值构成的特性。这些小的像素块构成了最基本的卷积神经网络(Convolutional Neural Networks, CNNs)。

卷积神经网络与传统的神经网络有着很高的相似之处,它们都由可学习的权重和偏置项以及神经元组成。每个神经元接收一些输入,执行点积运算,然后可以选择性地执行非线性分类。整个网络仍然表示为一个单一可微的评估函数,输入原始图像像素,输出各类别的概率。网络中仍存在损失函数,因为损失函数可以在全连接层中计算相对概率(例如,通过支持向量机或Softmax函数),并且各种用于传统神经网络的技术也可以应用于损失函数。

卷积过程是通过用周围像素的加权和替代每个像素来实现的,神经网络会学习这些权重。近年来,随着数据量和计算能力的大幅提升,卷积神经网络在人脸识别、物体识别、交通标志识别、机器人和自动驾驶等领域表现出色。

下图展示了卷积神经网络中四种主要操作:

  1. 卷积
  2. 非线性处理(如ReLU激活函数)
  3. 池化或子采样
  4. 分类

一张汽车的图片经过卷积神经网络处理后,在全连接层输出类别为汽车的概率。

全卷积网络

大多数用于目标识别的现代卷积神经网络(CNN)都是基于相同的原则构建的:交替使用卷积层和最大池化层,中间穿插少量全连接层。之前的研究表明,最大池化层可以用一个步长大一点的卷积层轻松替换,而不会在图像识别基准测试中损失精度。另一项有趣的发现是,全连接层可以用全局平均池化层替换。

去掉全连接层并不是一个令人意外的事情,因为长期以来,人们很少使用它。前不久,Yann LeCun 曾在 Facebook 上表示,他从未使用过全连接层。

实际上,全连接层和卷积层的主要区别在于后者只与输入中的局部区域相连,并且在卷积空间中的许多神经元共享参数。尽管如此,全连接层和卷积层中的神经元仍然执行点积运算,它们的函数形式相同。因此,全连接层和卷积层之间的转换是可行的,有时甚至可以用卷积层替换全连接层。

正如前面所述,下一步是去除网络中的空间池化运算。虽然这可能引起一些困惑,但我们可以仔细探讨这个概念。

空间池化(也称为子采样或下采样)减少了每个特征映射的维度,但保留了最重要的信息。以最大池化为例,我们定义了一个空间窗口,并从特征映射中提取最大值。直观来看,步长大一点的卷积层可以作为子采样和下采样层,使输入表征更小且更容易控制。这样可以减少网络中的参数数量和计算量,从而控制过拟合的发生。

为了减小表征尺寸,有时在卷积层中使用更大的步长是许多情况下的最佳选择。在训练好的生成模型(如变分自编码器VAE或生成对抗网络GAN)中,放弃池化层也是非常重要的。未来,神经网络架构可能会包含非常少甚至没有池化层。

鉴于所有这些小技巧或微调都很重要,我们已经在 Github 上发布了使用Keras模型实现的全卷积神经网络:https://github.com/MateLabs/All-Conv-Keras

导入库和依赖项

python from __future__ import print_function

在多GPU上训练

对于模型的多GPU实现,我们有一个自定义函数,可以将训练数据分配给可用的GPU。

在GPU上完成计算,输出数据传输到CPU以完成模型。

python def make_parallel(model, gpu_count): # 将模型复制到每个GPU上,每个GPU处理一部分输入数据 for i in range(gpu_count): # 将每个输入分割成部分以在当前GPU上处理 for x in model.inputs: if not isinstance(outputs, list): # 保存所有输出以稍后合并 for l in range(len(outputs)): # 在CPU上合并输出 with tf.device('/cpu:0'): pass

配置批量大小、类别数量和迭代次数

由于我们使用的是包含10个类别的CIFAR-10数据集,因此类别数量为10,批量大小为32。迭代次数取决于您可用的时间和设备的计算能力。在这个例子中,我们迭代1000次。

图像尺寸为32x32,颜色通道为3(RGB)。

python batch_size = 32

将数据集分为“训练集”、“测试集”和“验证集”三部分

python (X_train, y_train), (X_test, y_test) = cifar10.load_data() Y_train = np_utils.to_categorical(y_train, nb_classes)

构建模型

```python model = Sequential() model.add(Convolution2D(96, 3, 3, bordermode='same', inputshape=(3, 32, 32)))

下一步是用步长大一点的卷积层代替最大池化层,以减少图像的维度

model.add(Convolution2D(96, 3, 3, border_mode='same', subsample=(2, 2)))

同样的,我们再次用步长大一点的卷积层代替最大池化层

model.add(Convolution2D(192, 3, 3, border_mode='same', subsample=(2, 2))) model.add(GlobalAveragePooling2D()) ```

打印模型。这将给出模型的概览,有助于可视化模型的维度和参数数量

python print(model.summary())

数据增强

python datagen = ImageDataGenerator( samplewise_center=False, featurewise_std_normalization=False, samplewise_std_normalization=False, zca_whitening=False, rotation_range=0, width_shift_range=0.1, height_shift_range=0.1, horizontal_flip=False, vertical_flip=False ) datagen.fit(X_train)

在模型中保存最佳权重并添加检查点

python filepath = "weights.{epoch:02d}-{val_loss:.2f}.hdf5" checkpoint = ModelCheckpoint(filepath, monitor='val_acc', verbose=1, save_best_only=True, save_weights_only=False, mode='max') callbacks_list = [checkpoint]

在您的模型中使用生成的数据进行训练

python history_callback = model.fit_generator( datagen.flow(X_train, Y_train, batch_size=batch_size), samples_per_epoch=X_train.shape[0], nb_epoch=nb_epoch, validation_data=(X_test, Y_test), callbacks=callbacks_list, verbose=0 )

最后,获取训练过程的日志并保存模型

python pandas.DataFrame(history_callback.history).to_csv("history.csv")

该模型在前350次迭代后很容易达到超过90%的准确率。如果您希望进一步提高准确率,可以通过增加计算时间来尝试使用更多的数据进行训练。

    本文来源:图灵汇
责任编辑: : 机器人之家
声明:本文系图灵汇原创稿件,版权属图灵汇所有,未经授权不得转载,已经协议授权的媒体下载使用时须注明"稿件来源:图灵汇",违者将依法追究责任。
    分享
卷积实现简洁识别图像概念基本教程网络
    下一篇