《第九章》

9.1图像增广

为了在预测时得到确定的结果,通常只将图像增广应用在训练样本上,而不在预测时使用含随机操作的图像增广。

图像增广:将图片翻转,缩放扩大,随机截取,调整色调,明亮等操作以生成新的数据集。

import gc
gc.collect()  # 清理内存

练习

  • 不使用图像增广训练模型:train_with_data_aug(no_aug, no_aug)。比较有无图像增广时的训练准确率和测试准确率。该对比实验能否支持图像增广可以应对过拟合这一论断?为什么?

    答:支持,正如下述训练,训练集拟合程度提高更快,且测试集结果也不如有图像增广的高。

    train_with_data_aug(no_aug, no_aug)
    ——————————————————————————————结果——————————————————————
    training on [gpu(0)]
    epoch 1, loss 1.3485, train acc 0.522, test acc 0.556, time 62.9 sec
    epoch 2, loss 0.7872, train acc 0.722, test acc 0.705, time 65.0 sec
    epoch 3, loss 0.5654, train acc 0.802, test acc 0.738, time 67.0 sec
    epoch 4, loss 0.4175, train acc 0.853, test acc 0.777, time 67.9 sec
    epoch 5, loss 0.3043, train acc 0.895, test acc 0.789, time 67.8 sec
    epoch 6, loss 0.2183, train acc 0.923, test acc 0.799, time 68.2 sec
    epoch 7, loss 0.1547, train acc 0.946, test acc 0.810, time 68.5 sec
    epoch 8, loss 0.1150, train acc 0.960, test acc 0.799, time 68.9 sec
    epoch 9, loss 0.0814, train acc 0.972, test acc 0.809, time 69.1 sec
    epoch 10, loss 0.0725, train acc 0.974, test acc 0.806, time 70.2 sec
  • 在基于CIFAR-10数据集的模型训练中增加不同的图像增广方法。观察实现结果。

    答:每轮的耗时不变,测试集效率有提高,且测试集拟合的也比较慢。

    complex_aug = gdata.vision.transforms.Compose([
        gdata.vision.transforms.RandomFlipLeftRight(),
        gdata.vision.transforms.RandomHue(0.5),
        gdata.vision.transforms.ToTensor()])
    train_with_data_aug(complex_aug, no_aug)
    ————————————————————————————————结果————————————————————————
    training on [gpu(0)]
    epoch 1, loss 1.5822, train acc 0.446, test acc 0.496, time 69.3 sec
    epoch 2, loss 0.9240, train acc 0.673, test acc 0.676, time 68.4 sec
    epoch 3, loss 0.6791, train acc 0.764, test acc 0.739, time 68.6 sec
    epoch 4, loss 0.5490, train acc 0.810, test acc 0.728, time 69.8 sec
    epoch 5, loss 0.4555, train acc 0.842, test acc 0.777, time 70.5 sec
    epoch 6, loss 0.3836, train acc 0.868, test acc 0.762, time 70.2 sec
    epoch 7, loss 0.3227, train acc 0.889, test acc 0.795, time 69.8 sec
    epoch 8, loss 0.2728, train acc 0.906, test acc 0.807, time 70.0 sec
    epoch 9, loss 0.2392, train acc 0.918, test acc 0.823, time 70.8 sec
    epoch 10, loss 0.1931, train acc 0.934, test acc 0.820, time 70.1 sec
  • 查阅MXNet文档,Gluon的transforms模块还提供了哪些图像增广方法?

方法
涵义

Sequentially composes multiple transforms.

Cast inputs to a specific data type

transforms.ToTensor

Converts an image NDArray or batch of image NDArray to a tensor NDArray.

transforms.Normalize

Normalize an tensor of shape (C x H x W) or (N x C x H x W) with mean and standard deviation.

transforms.RandomResizedCrop

Crop the input image with random scale and aspect ratio.

transforms.CenterCrop

Crops the image src to the given size by trimming on all four sides and preserving the center of the image.

transforms.Resize

Resize an image or a batch of image NDArray to the given size.

transforms.RandomFlipLeftRight

Randomly flip the input image left to right with a probability of p(0.5 by default).

transforms.RandomFlipTopBottom

Randomly flip the input image top to bottom with a probability of p(0.5 by default).

transforms.RandomBrightness

Randomly jitters image brightness with a factor chosen from [max(0, 1 - brightness), 1 + brightness].

transforms.RandomContrast

Randomly jitters image contrast with a factor chosen from [max(0, 1 - contrast), 1 + contrast].

transforms.RandomSaturation

Randomly jitters image saturation with a factor chosen from [max(0, 1 - saturation), 1 + saturation].

transforms.RandomHue

Randomly jitters image hue with a factor chosen from [max(0, 1 - hue), 1 + hue].

transforms.RandomColorJitter

Randomly jitters the brightness, contrast, saturation, and hue of an image.

transforms.RandomLighting

Add AlexNet-style PCA-based noise to an image.

9.2微调

微调

迁移学习:下载预训练过的模型参数,而后以较小的学习率微调隐藏层,以较大的学习率从头学习输出层。

Gluon的model_zoo包提供了常用的预训练模型。

GluonCV工具包有更多计算机视觉的预训练模型。

微调步骤:

  1. 加载预训练模型

  2. 定义微调模型,features直接套用预加载的,output重新初始化,并设置多倍学习率。

  3. 训练函数,记得设置本机的ctx。

练习

  • 不断增大finetune_net的学习率。准确率会有什么变化?

    答:学习率调到0.05,准确率显著降低,且提高的也很慢。说明较大程度改变了原来的模型参数,可能会造成糟糕的结果。

  • 进一步调节对比试验中finetune_netscratch_net的超参数。它们的精度是不是依然有区别?

    答:增加了scratch_netnum_epochs为10,后面周期的准确率增加还是没有赶上finetune_net。说明两者还是有很多不同的,不仅仅在迭代周期上。题目中的精度不是很明白在问什么。

  • finetune_net.features中的参数固定为源模型的参数而不在训练中迭代,结果会怎样?你可能会用到以下代码。

    答:结果训练集的准确率提高不多,甚至还有时下降了,测试的准确率也基本上不变。

9.3目标检测和边界框

目标检测:辨认出目标所在的位置

边界框:给目标加上一个方框

练习

  • 找一些图像,尝试标注其中目标的边界框。比较标注边界框与标注类别所花时间的差异。

    答:手动标注的肯定很慢,自动标注的还没学到。

9.4锚框

锚框:以每个像素为中心生成多个大小和宽高比(aspect ratio)不同的边界框。

生成锚框:设定大小s_1——s_n,宽高比r_1——r_n.我们通常只对包含s_1或r_1的组合感兴趣。

(s1,r1),(s1,r2),,(s1,rm),(s2,r1),(s3,r1),,(sn,r1).(s_1, r_1), (s_1, r_2), \ldots, (s_1, r_m), (s_2, r_1), (s_3, r_1), \ldots, (s_n, r_1).

以相同像素为中心的锚框的数量为n+m−1。对于整个输入图像有wh(n+m-1)个锚框。

交并比:也叫Jaccard系数,衡量两个集合的相似度。

J(A,B)=ABAB.J(\mathcal{A},\mathcal{B}) = \frac{\left|\mathcal{A} \cap \mathcal{B}\right|}{\left| \mathcal{A} \cup \mathcal{B}\right|}.

标注训练集的锚框的类别和偏移值:为每个锚框标注两类标签:一是锚框所含目标的类别,简称类别;二是真实边界框相对锚框的偏移量,简称偏移量(offset)。每次取相似度矩阵X中的最大值(且大于阈值),并将所在行和列丢弃。

为锚框分配真实边界框

非极大值抑制:先为图像生成多个锚框,并为这些锚框一一预测类别和偏移量。随后,我们根据锚框及其预测偏移量得到预测边界框。移除相似的预测边界框。常用的方法叫作非极大值抑制(non-maximum suppression,NMS)。

np.set_printoptions(2):设置NDArray小数点后只打印2位。

numpy中的expand_dims(axis=0):在第'axis'维,加一个维度出来,原先的维度向’右边‘推。

练习

  • 改变MultiBoxPrior函数中sizesratios的取值,观察生成的锚框的变化。

    答:修改后,以相同像素为中心的锚框个数记得修改。

  • 构造交并比为0.5的两个边界框,观察它们的重合度。

    答:重合度占两个边框之和的一半。

  • 按本节定义的为锚框标注偏移量的方法(常数采用默认值),验证偏移量labels[0]的输出结果。

    答:没错。

    (xbxawaμxσx,ybyahaμyσy,logwbwaμwσw,loghbhaμhσh)μx=μy=μw=μh=0,σx=σy=0.1,σw=σh=0.2\left( \frac{ \frac{x_b - x_a}{w_a} - \mu_x }{\sigma_x}, \frac{ \frac{y_b - y_a}{h_a} - \mu_y }{\sigma_y}, \frac{ \log \frac{w_b}{w_a} - \mu_w }{\sigma_w}, \frac{ \log \frac{h_b}{h_a} - \mu_h }{\sigma_h}\right)\\ \mu_x = \mu_y = \mu_w = \mu_h = 0, \sigma_x=\sigma_y=0.1, \sigma_w=\sigma_h=0.2
  • 修改“标注训练集的锚框”与“输出预测边界框”两小节中的变量anchors,结果有什么变化?

    答:锚框发生改变。根据坐标位置而改变。

9.5多尺度目标检测

减少锚框:在输入图像中均匀采样一小部分像素,并以采样的像素为中心生成锚框。

可以在多个尺度下生成不同数量和不同大小的锚框,从而在多个尺度下检测不同大小的目标。

用输入图像在某个感受野区域内的信息来预测输入图像上与该区域相近的锚框的类别和偏移量。

练习

  • 给定一张输入图像,设特征图变量的形状为1×ci×h×w,其中ci、h和w分别为特征图的个数、高和宽。你能想到哪些将该变量变换为锚框的类别和偏移量的方法?输出的形状分别是什么?

    答:卷积?形状不知。我们可以将特征图在相同空间位置的ci个单元变换为以该位置为中心生成的a个锚框的类别和偏移量。本质上,我们用输入图像在某个感受野区域内的信息来预测输入图像上与该区域位置相近的锚框的类别和偏移量。

9.6目标检测数据集(皮卡丘)

numpy的transpose():将维度进行置换,两维的为转置矩阵。

练习

  • 查阅MXNet文档,image.ImageDetIterimage.CreateDetAugmenter这两个类的构造函数有哪些参数?它们的意义是什么?

    • image.ImageDetIter的Parameters

      • batch_size**,** data_shape两个一定要指定。

      • aug_list (list or None) – Augmenter list for generating distorted images

      • batch_size (int) – Number of examples per batch.

      • data_shape (tuple) – Data shape in (channels, height, width) format. For now, only RGB image with 3 channels is supported.

      • path_imgrec (str) – Path to image record file (.rec). Created with tools/im2rec.py or bin/im2rec.

      • path_imglist (str) – Path to image list (.lst). Created with tools/im2rec.py or with custom script. Format: Tab separated record of index, one or more labels and relative_path_from_root.

      • imglist (list) – A list of images with the label(s). Each item is a list [imagelabel: float or list of float, imgpath].

      • path_root (str) – Root folder of image files.

      • path_imgidx (str) – Path to image index file. Needed for partition and shuffling when using .rec source.

      • shuffle (bool) – Whether to shuffle all images at the start of each iteration or not. Can be slow for HDD.

      • part_index (int) – Partition index.

      • num_parts (int) – Total number of partitions.

      • data_name (str) – Data name for provided symbols.

      • label_name (str) – Name for detection labels

      • last_batch_handle (str*,* optional) – How to handle the last batch. This parameter can be ‘pad’(default), ‘discard’ or ‘roll_over’. If ‘pad’, the last batch will be padded with data starting from the begining If ‘discard’, the last batch will be discarded If ‘roll_over’, the remaining elements will be rolled over to the next iteration

      • kwargs – More arguments for creating augmenter. See mx.image.CreateDetAugmenter.

    • image.CreateDetAugmenter的Parameters

      • data_shape (tuple of int) – Shape for output data

      • resize (int) – Resize shorter edge if larger than 0 at the begining

      • rand_crop (float) – [0, 1], probability to apply random cropping

      • rand_pad (float) – [0, 1], probability to apply random padding

      • rand_gray (float) – [0, 1], probability to convert to grayscale for all channels

      • rand_mirror (bool) – Whether to apply horizontal flip to image with probability 0.5

      • mean (np.ndarray or None) – Mean pixel values for [r, g, b]

      • std (np.ndarray or None) – Standard deviations for [r, g, b]

      • brightness (float) – Brightness jittering range (percent)

      • contrast (float) – Contrast jittering range (percent)

      • saturation (float) – Saturation jittering range (percent)

      • hue (float) – Hue jittering range (percent)

      • pca_noise (float) – Pca noise level (percent)

      • inter_method (int*,* default=2*(Area-based)*) –

        Interpolation method for all resizing operations

        Possible values: 0: Nearest Neighbors Interpolation. 1: Bilinear interpolation. 2: Area-based (resampling using pixel area relation). It may be a preferred method for image decimation, as it gives moire-free results. But when the image is zoomed, it is similar to the Nearest Neighbors method. (used by default). 3: Bicubic interpolation over 4x4 pixel neighborhood. 4: Lanczos interpolation over 8x8 pixel neighborhood. 9: Cubic for enlarge, area for shrink, bilinear for others 10: Random select from interpolation method metioned above. Note: When shrinking an image, it will generally look best with AREA-based interpolation, whereas, when enlarging an image, it will generally look best with Bicubic (slow) or Bilinear (faster but still looks OK).

      • min_object_covered (float) – The cropped area of the image must contain at least this fraction of any bounding box supplied. The value of this parameter should be non-negative. In the case of 0, the cropped area does not need to overlap any of the bounding boxes supplied.

      • min_eject_coverage (float) – The minimum coverage of cropped sample w.r.t its original size. With this constraint, objects that have marginal area after crop will be discarded.

      • aspect_ratio_range (tuple of floats) – The cropped area of the image must have an aspect ratio = width / height within this range.

      • area_range (tuple of floats) – The cropped area of the image must contain a fraction of the supplied image within in this range.

      • max_attempts (int) – Number of attempts at generating a cropped/padded region of the image of the specified constraints. After max_attempts failures, return the original image.

      • pad_val (float) – Pixel value to be filled when padding is enabled. pad_val will automatically be subtracted by mean and divided by std if applicable.

9.7单发多框检测

numpy的flatten():默认将数组按行变换展开。返回的是拷贝,而ravel()会修改数据。

填充为1的3×3卷积层不改变特征图的形状。

感受野计算公式:

这里写图片描述
这里写图片描述

单发多框检测模型(single shot multibox detection,SSD):一共包含5个模块,每个模块输出的特征图既用来生成锚框,又用来预测这些锚框的类别和偏移量。第一模块为基础网络块,第二模块至第四模块为高和宽减半块,第五模块使用全局最大池化层将高和宽降到1。

单发多框检测模型主要由一个基础网络块和若干多尺度特征块串联而成

单发多框检测在训练中根据类别和偏移量的预测和标注值分别计算损失函数,类别可以用交叉熵损失、焦点损失;偏移量可以用L1范数损失、平滑L1范数损失。

练习

  • 限于篇幅,实验中忽略了单发多框检测的一些实现细节。你能从以下几个方面进一步改进模型吗?

    偏移量预测改进平滑L1范数:

    类别预测改进为焦点损失:

9.8区域卷积神经网络(R-CNN)

R-CNN模型:

R-CNN模型

Fast R-CNN:

Fast R-CNN模型

Faster R-CNN:

  1. 使用填充为1的3×3卷积层变换卷积神经网络的输出,并将输出通道数记为c。这样,卷积神经网络为图像抽取的特征图中的每个单元均得到一个长度为cc的新特征。

  2. 以特征图每个单元为中心,生成多个不同大小和宽高比的锚框并标注它们。

  3. 用锚框中心单元长度为cc的特征分别预测该锚框的二元类别(含目标还是背景)和边界框。

  4. 使用非极大值抑制,从预测类别为目标的预测边界框中移除相似的结果。最终输出的预测边界框即兴趣区域池化层所需要的提议区域。

Faster R-CNN模型

Mask R-CNN:

Mask R-CNN模型

练习

  • 了解GluonCV工具包中有关本节中各个模型的实现 [6]。

    答:详细教程:https://gluon-cv.mxnet.io/model_zoo/detection.html

9.9语义分割和数据集

练习

  • 回忆“图像增广”一节中的内容。哪些在图像分类中使用的图像增广方法难以用于语义分割?

    答:裁剪而没有放大到同样大小的不行。

9.10FCN全卷积网络

矩阵乘法实现卷积:看下方转置卷积教程。

转置卷积:可参考https://blog.csdn.net/tsyccnh/article/details/87357447,讲的更形象。转置卷积就是将卷积的结果乘以一个权重,而变回卷积之前的形状,不能恢复到原始数值。如果步幅为s、填充为s/2(假设s/2为整数)、卷积核的高和宽为2s,转置卷积核将输入的高和宽分别放大s倍。

上采样:放大。常用双线性插值的方法。

下采样:缩小。

FCN模型:全卷积网络先使用卷积神经网络抽取图像特征,然后通过1×1卷积层将通道数变换为类别个数,最后通过转置卷积层将特征图的高和宽变换为输入图像的尺寸。模型输出与输入图像的高和宽相同,并在空间位置上一一对应:最终输出的通道包含了该空间位置像素的类别预测。

全卷积网络

X[::3],从第0个开始,每隔三个显示。

练习

  • 用矩阵乘法来实现卷积运算是否高效?为什么?

    答:不高效,还要涉及矩阵的变换,

  • 如果将转置卷积层改用Xavier随机初始化,结果有什么变化?

    答:结果是准确率卡在了0.729左右,后续迭代,损失值下降,但是没有提高准确率。

  • 调节超参数,能进一步提升模型的精度吗?

    答:只提高学习率会导致overfit;只提高batch_size导致内存溢出。且由于占用内存和时间过大,调参显得很麻烦,考虑使用云计算平台。

  • 预测测试图像中所有像素的类别。

    答:预测像素的类别?不理解题意。如果是预测所有图像,提高n的值就可以了。

  • 全卷积网络的论文中还使用了卷积神经网络的某些中间层的输出 [1]。试着实现这个想法。

    答:第一次看此书,先不看论文。下次看pytorch实现的版本,再看论文。

9.11样式迁移

样式迁移(style transfer):使用卷积神经网络自动将某图像中的样式应用在另一图像之上。

内容损失(content loss)使合成图像与内容图像在内容特征上接近。

样式损失(style loss)令合成图像与样式图像在样式特征上接近

总变差损失(total variation loss)则有助于减少合成图像中的噪点。

基于卷积神经网络的样式迁移。实线箭头和虚线箭头分别表示正向传播和反向传播

卷积层参数使用预训练模型来提取特征。

第一和第三卷积层输出作为样式特征

第二卷积层输出作为内容特征。

模型参数为合成图像。

正向传播(实线)计算损失,反向传播(虚线)迭代模型参数。

拉姆矩阵:格拉姆矩阵(Gram matrix)XX⊤∈Rc×c中i行j列的元素xij即向量xi与xj的内积,它表达了通道i和通道j上样式特征的相关性。(假设该输出的样本数为1,通道数为c,高和宽分别为h和w,我们可以把输出变换成c行hw列的矩阵X。)

练习

  • 选择不同的内容和样式层,输出有什么变化?

    答:选择了最后一个卷积层[34]作为内容层,内容损失很快降低到0.86左右。输出图像肉眼看不出变换。样式和内容层使用了[2,7,12,14,16,21,23,25,28,30,32], [34],迭代后,样式层损失仅降低到7左右。输出图像还是肉眼看不出差距。

  • 调整损失函数中的权值超参数,输出是否保留更多内容或减少更多噪点?

    答:直觉上,提高内容损失的权值超参数,可以让他更容易被惩罚,所以内容损失降的更低,从而保留更多的内容。由于不清楚如何辨别内容和噪点的数量多少,故无实验。

  • 替换实验中的内容图像和样式图像,你能创作出更有趣的合成图像吗?

    答:选了两张动漫人物图,合成结果基本上保留内容图像,可能风格一致吧,损失也很低。

    选了一张动漫人物图和一张风景图,合成结果很多噪点,损失值很高。

最后更新于

这有帮助吗?