深度学习系列(九) 计算机视觉之模型泛化能力(图像增广和微调) 2020.6.26

前言

前面学习了深度学习的经典模型和一些优化
本节开始学习深度学习在计算机视觉领域的应用
本节先学习两个提升模型泛化能力的方法

  • 图像增广
  • 微调

1、图像增广

图像增广

  • 对训练图像做⼀系列随机改变
  • 产⽣相似但⼜不同的训练样本
  • 扩⼤训练数据集的规模

实现

import d2lzh as d2l
import mxnet as mx
from mxnet import autograd, gluon, image, init, nd
from mxnet.gluon import data as gdata, loss as gloss, utils as gutils
import sys
import time

"""实现图像增广"""
# 读取一张形状为高和宽分别为400像素和500像素的图像作为实验的样例
d2l.set_figsize()
img = image.imread('../img/cat1.jpg')
d2l.plt.imshow(img.asnumpy())

# 绘图函数
def show_images(imgs, num_rows, num_cols, scale=2):
    figsize = (num_cols * scale, num_rows * scale)
    _, axes = d2l.plt.subplots(num_rows, num_cols, figsize=figsize)
    for i in range(num_rows):
        for j in range(num_cols):
            axes[i][j].imshow(imgs[i * num_cols + j].asnumpy())
            axes[i][j].axes.get_xaxis().set_visible(False)
            axes[i][j].axes.get_yaxis().set_visible(False)
    return axes
# 观察图像增⼴效果的辅助函数
def apply(img, aug, num_rows=2, num_cols=4, scale=1.5):
    Y = [aug(img) for _ in range(num_rows * num_cols)]
    show_images(Y, num_rows, num_cols, scale)

# 翻转
apply(img, gdata.vision.transforms.RandomFlipLeftRight()) #左右翻转
apply(img, gdata.vision.transforms.RandomFlipTopBottom()) #上下翻转

# 裁剪
shape_aug = gdata.vision.transforms.RandomResizedCrop((200, 200), scale=(0.1, 1), ratio=(0.5, 2)) #⾯积为原⾯积10%-100%的区域,且该区域的宽和⾼之⽐随机取⾃0.5-2,然后再将该区域的宽和⾼分别缩放到200像素
apply(img, shape_aug)

# 变化颜色
apply(img, gdata.vision.transforms.RandomBrightness(0.5)) #亮度
apply(img, gdata.vision.transforms.RandomHue(0.5)) #色调
color_aug = gdata.vision.transforms.RandomColorJitter(brightness=0.5, contrast=0.5, saturation=0.5, hue=0.5) #还有饱和度和对比度
apply(img, color_aug)

# 上面几个叠加
augs = gdata.vision.transforms.Compose([gdata.vision.transforms.RandomFlipLeftRight(), color_aug, shape_aug])
apply(img, augs)

效果

原图
深度学习系列(九) 计算机视觉之模型泛化能力(图像增广和微调) 2020.6.26_第1张图片
翻转
深度学习系列(九) 计算机视觉之模型泛化能力(图像增广和微调) 2020.6.26_第2张图片
裁剪
深度学习系列(九) 计算机视觉之模型泛化能力(图像增广和微调) 2020.6.26_第3张图片
色调
深度学习系列(九) 计算机视觉之模型泛化能力(图像增广和微调) 2020.6.26_第4张图片
几种效果叠加
深度学习系列(九) 计算机视觉之模型泛化能力(图像增广和微调) 2020.6.26_第5张图片

2、微调

微调是迁移学习的一种常用技术

  • 在源数据集(如ImageNet数据集)上预训练一个神经网络模型,即源模型。
  • 创建一个新的神经网络模型,即目标模型。它复制了源模型上除了输出层外的所有模型设计及其参数。我们假设这些模型参数包含了源数据集上学习到的知识,且这些知识同样适用于目标数据集。我们还假设源模型的输出层跟源数据集的标签紧密相关,因此在目标模型中不予采用。
  • 为目标模型添加一个输出大小为目标数据集类别个数的输出层,并随机初始化该层的模型参数。
  • 在目标数据集(如椅子数据集)上训练目标模型。我们将从头训练输出层,而其余层的参数都是基于源模型的参数微调得到的。

深度学习系列(九) 计算机视觉之模型泛化能力(图像增广和微调) 2020.6.26_第6张图片

实现

import d2lzh as d2l
from mxnet import gluon, init, nd
from mxnet.gluon import data as gdata, loss as gloss, model_zoo
from mxnet.gluon import utils as gutils
import os
import zipfile

"""用热狗图数据集实现微调"""
# 数据
data_dir = '../data'
base_url = 'https://apache-mxnet.s3-accelerate.amazonaws.com/'
fname = gutils.download(
    base_url + 'gluon/dataset/hotdog.zip',
    path=data_dir, sha1_hash='fba480ffa8aa7e0febbb511d181409f899b9baa5')
with zipfile.ZipFile(fname, 'r') as z:
    z.extractall(data_dir)
train_imgs = gdata.vision.ImageFolderDataset(os.path.join(data_dir, 'hotdog/train'))
test_imgs = gdata.vision.ImageFolderDataset(os.path.join(data_dir, 'hotdog/test'))

"""在训练时,我们先从图像中裁剪出随机大小和随机高宽比的一块随机区域
然后将该区域缩放为高和宽均为224像素的输入
测试时,我们将图像的高和宽均缩放为256像素
然后从中裁剪出高和宽均为224像素的中心区域作为输入
此外,我们对RGB(红、绿、蓝)三个颜色通道的数值做标准化
每个数值减去该通道所有数值的平均值,再除以该通道所有数值的标准差作为输出"""
# 指定RGB三个通道的均值和方差来将图像通道归一化
normalize = gdata.vision.transforms.Normalize(
    [0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
train_augs = gdata.vision.transforms.Compose([
    gdata.vision.transforms.RandomResizedCrop(224),
    gdata.vision.transforms.RandomFlipLeftRight(),
    gdata.vision.transforms.ToTensor(),
    normalize])
test_augs = gdata.vision.transforms.Compose([
    gdata.vision.transforms.Resize(256),
    gdata.vision.transforms.CenterCrop(224),
    gdata.vision.transforms.ToTensor(),
    normalize])

# 模型
pretrained_net = model_zoo.vision.resnet18_v2(pretrained=True) #ResNet18作为源模型
finetune_net = model_zoo.vision.resnet18_v2(classes=2)
finetune_net.features = pretrained_net.features #⽬标模型实例finetune_net的成员变量features中的模型参数被初始化为源模型相应层的模型参数
finetune_net.output.initialize(init.Xavier())
finetune_net.output.collect_params().setattr('lr_mult', 10) #output中的模型参数将在迭代中使用10倍大的学习率

# 微调
def train_fine_tuning(net, learning_rate, batch_size=128, num_epochs=5):
    train_iter = gdata.DataLoader(train_imgs.transform_first(train_augs), batch_size, shuffle=True)
    test_iter = gdata.DataLoader(test_imgs.transform_first(test_augs), batch_size)
    ctx = d2l.try_all_gpus()
    net.collect_params().reset_ctx(ctx)
    net.hybridize()
    loss = gloss.SoftmaxCrossEntropyLoss()
    trainer = gluon.Trainer(net.collect_params(), 'sgd', {'learning_rate': learning_rate, 'wd': 0.001})
    d2l.train(train_iter, test_iter, net, loss, trainer, ctx, num_epochs)

train_fine_tuning(finetune_net, 0.01) #将Trainer实例中的学习率设得小⼀点,如0.01
# 定义⼀个相同的模型,但将它的所有模型参数都初始化为随机值作为对比
scratch_net = model_zoo.vision.resnet18_v2(classes=2)
scratch_net.initialize(init=init.Xavier())
train_fine_tuning(scratch_net, 0.1)

结语

计算机视觉是个大领域
准备学个几天学个大概

你可能感兴趣的:(machine,learning,计算机视觉,深度学习,人工智能,神经网络,机器学习)