Part 3.2

Part 3.2: image preprocessing
在我们尝试训练CNN之前,对图像进行预处理以去除其平均值。 它也通过应用标准偏差3个像素的高斯核进行平滑:

% Pre-smooth the image
im = vl_imsmooth(im,3) ;

% Subtract median value
im = im - median(im(:)) ;

我们稍后将回到这个预处理步骤。

Part 3.3: learning with gradient descent
这里写图片描述

Questions:
What can you say about the score of each pixel if λ=0 and E(\bw,b)=0 ?
Note that the objective enforces a margin between the scores of the positive and negative pixels. How much is this margin?

We can now train the CNN by minimising the objective function with respect to \bw and b . We do so by using an algorithm called gradient descent with momentum. Given the current solution (\bwt,bt), this is updated to (\bwt+1,bt+1) by following the direction of fastest descent of the objective E(\bwt,bt) as given by the negative gradient E . However, gradient updates are smoothed by considering a momentum term (\bw¯t,μ¯t) , yielding the update equations and similarly for the bias term. Here μ is the momentum rate and η the learning rate.

问题:
解释为什么动量率必须小于1.动量率接近1的效应是什么?
学习速率确定算法将如何快速地尝试最小化目标函数。 你能看到大的学习率的任何存在问题吗?
算法的参数设置如下:

numIterations = 500 ;
rate = 5 ;
momentum = 0.9 ;
shrinkRate = 0.0001 ;
plotPeriod = 10 ;

任务:
检查文件exercise3.m中的代码。 确保代码正在实现上述算法。 特别注意前向和后向通过以及如何计算目标函数及其导数。

运行算法并观察结果。 然后回答以下问题:
学习的滤波器应该类似于众所周知的微分算子的离散化。 哪一个?
与绝对值的平均值相比,过滤器值的平均值是多少?

再次运行算法,观察相对于值0和1的正像素和负像素的得分的直方图的演变。回答以下问题:
目标函数是否单调减少?
随着直方图的演变,您可以在优化中识别至少两个“阶段”?
一旦收敛,分数是否按你期望的方式分布?
提示:plotPeriod选项可以更改为绘制具有更高或更低频率的诊断图; 这可以显着影响算法的速度。

Part 3.4: experimenting with the tiny CNN
在这部分,我们将实验刚刚学习的网络的几个变种。 首先,我们研究图像平滑的效果:
任务:在预处理中再次训练微小的CNN而不平滑输入图像。 回答下列问题:
学习的过滤器与之前学到的过滤器有很大的不同吗?
如果是,你能找出什么“出了问题”吗?
仔细观察第一层的输出,用放大镜工具放大。 在每个blob的中间是否达到最大滤波器响应?

提示:高斯算子的拉普拉斯算子只有在色块中心与色块大小匹配时才最大程度地响应。 将此事实与预平滑图像和应用学习的 3 times3 filter的组合相关。

现在恢复平滑,但关闭减去输入图像中的中位数。

任务:再次训练微小的CNN,而不减去预处理中的中值。 回答下列问题:
算法是否收敛?
减少一百倍的学习,并增加最大迭代次数等量。 它会变得更好吗?
解释为什么向输入图像添加常数会对优化的性能产生如此巨大的影响。

提示:当(i)输入图像为零或(ii)输入图像是大常量时,如果滤波器输出应为零,则滤波器  bw 应满足什么约束? 你认为梯度下降很容易强制执行(ii)吗?

你刚刚见证的实际上是一个相当一般的原则:数据中心通常使学习问题更好的条件。

任务:恢复实验4.m中给出的预处理。 尝试以下操作:
尝试提高学习率eta。 你能在500次迭代中实现更好的能量价值吗?
通过设置动量= 0来禁用动量。现在尝试通过选择eta击败上面获得的结果。 你能成功吗?
最后,考虑收缩的正则化效应:
任务:恢复学习速率和动量,如实验4。 然后增加收缩系数十倍和一百倍。
对收敛速度有什么影响?
对总目标函数的最终值和它的平均损失部分有什么影响?

Part 4: learning a character CNN
在这部分,我们将学习一个CNN来识别字符的图像。
Part 4.1: prepare the data
打开exercise4.m并执行第4.1部分。 代码加载结构imdb,其中包含使用从Google Fonts项目下载的大约931种字体渲染的字符a,b,…,z的图像。 看看imdb.images子结构:

% Load character dataset
imdb = load('data/charsdb.mat') ;

% Visualize some of the data
figure(10) ; clf ; colormap gray ;
subplot(1,2,1) ;
vl_imarraysc(imdb.images.data(:,:,imdb.images.label==1 & imdb.images.set==1)) ;
axis image off ;
title('training chars for ''a''') ;

subplot(1,2,2) ;
vl_imarraysc(imdb.images.data(:,:,imdb.images.label==1 & imdb.images.set==2)) ;
axis image off ;
title('validation chars for ''a''') ;
>> imdb.images
ans = 
       id: [1x24206 double]
     data: [32x32x24206 single]
    label: [1x24206 double]
      set: [1x24206 double]

These are stored as the array imdb.images.id is a 29,198-dimensional vector of numeric IDs for each of the 29,198 character images in the dataset. imdb.images.data contains a 32×32 image for each character, stored as a slide of a 32×32×29,!198 -dimensional array. imdb.images.label is a vector of image labels, denoting which one of the 26 possible characters it is. imdb.images.set is equal to 1 for each image that should be used to train the CNN and to 2 for each image that should be used for validation.

这里写图片描述
任务:看看图1生成的代码和代码本身,并确保你明白你在看什么。

Part 4.2: intialize a CNN architecture
initializeCharacterCNN.m创建一个带有随机权重的CNN初始化,将被训练来识别字符图像

function net = initializeCharacterCNN()

f=1/100 ;
net.layers = {} ;
net.layers{end+1} = struct('type', 'conv', ...
                           'weights', {{f*randn(5,5,1,20, 'single'), zeros(1, 20, 'single')}}, ...
                           'stride', 1, ...
                           'pad', 0) ;
net.layers{end+1} = struct('type', 'pool', ...
                           'method', 'max', ...
                           'pool', [2 2], ...
                           'stride', 2, ...
                           'pad', 0) ;
net.layers{end+1} = struct('type', 'conv', ...
                           'weights', {{f*randn(5,5,20,50, 'single'), zeros(1,50,'single')}}, ...
                           'stride', 1, ...
                           'pad', 0) ;
net.layers{end+1} = struct('type', 'pool', ...
                           'method', 'max', ...
                           'pool', [2 2], ...
                           'stride', 2, ...
                           'pad', 0) ;
net.layers{end+1} = struct('type', 'conv', ...
                           'weights', {{f*randn(4,4,50,500, 'single'), zeros(1,500,'single')}}, ...
                           'stride', 1, ...
                           'pad', 0) ;
net.layers{end+1} = struct('type', 'relu') ;
net.layers{end+1} = struct('type', 'conv', ...
                           'weights', {{f*randn(2,2,500,26, 'single'), zeros(1,26,'single')}}, ...
                           'stride', 1, ...
                           'pad', 0) ;
net.layers{end+1} = struct('type', 'softmaxloss') ;

net = vl_simplenn_tidy(net) ;

任务:

通过检查initializeCharacterCNN.m获得将被训练的架构的感觉。 有多少层? 过滤器有多大?
使用函数vl_simplenn_display产生一个概括架构的表。

% -------------------------------------------------------------------------
% Part 4.2: initialize a CNN architecture
% -------------------------------------------------------------------------

net = initializeCharacterCNN() ;

请注意,倒数第二层有26个输出尺寸,每个字符一个。 字符识别查看最大输出以识别网络处理哪个字符。
However, the last network layer is vl_nnsoftmaxloss, which in turn is a combination of the vl_nnsoftmax function and of the classification log-loss vl_nnloss. The softmax operator is given by whereas the log-loss is given by where cij is the index of the ground-truth class at spatial location (i,j) .
Remark: While in MatConvNet all operators are convolutional, in this case the network is configured such that the output of the classification layer is a 1×1×26 -dimensional feature map, i.e. there remains only one spatial location.
注意:在MatConvNet中,所有运算符都是卷积的,在这种情况下,网络被配置为使得分类层的输出是$ 1 \乘以1/6乘以2维的特征映射,即只剩下一个空间位置。

任务:
了解softmax操作符。 提示:要使用log-loss,数据必须在(0,1]间隔。
了解什么是最小化对数损失的影响。 哪个神经反应应该变大?
为什么你认为MatConvNet提供了第三个函数vl_nnsoftmaxloss将这两个函数组合到一个单一的层?

Part 4.3: train and evaluate the CNN
我们现在准备训练CNN。 为此,我们使用MatConvNet中的示例SGD实现(examples / cnn_train.m)。 此功能需要一些选项:

trainOpts.batchSize = 100 ;
trainOpts.numEpochs = 100 ;
trainOpts.continue = true ;
trainOpts.useGpu = false ;
trainOpts.learningRate = 0.001 ;
trainOpts.numEpochs = 15 ;
trainOpts.expDir = 'data/chars-experiment' ;

这说明该函数将在100个元素的SGD小批量上操作,它将运行15个历元(通过数据),如果中断,它将从上一个历元继续,如果不使用GPU,则将使用 学习率为0.001,它会将任何文件保存在data / chars-experiment子目录中。
在训练开始之前,减去平均图像值:

% Take the average image out
imageMean = mean(imdb.images.data(:)) ;
imdb.images.data = imdb.images.data - imageMean ;

这与我们在第3部分中所做的类似。
训练代码调用如下:

% Call training function in MatConvNet
[net,info] = cnn_train(net, imdb, @getBatch, trainOpts) ;

这里的关键,除了trainOpts结构,是@getBatch函数句柄。 这就是cnn_train如何获取要操作的数据的副本。 检查此函数(请参阅exercise4.m文件的底部):

function [im, labels] = getBatch(imdb, batch)
im = imdb.images.data(:,:,batch) ;
im = 256 * reshape(im, 32, 32, 1, []) ;
labels = imdb.images.label(1,batch) ;

该函数提取对应于索引批处理向量的 m images。 它还将它们重塑为 32 times32 times1 timesm array(因为这是MatConvNet函数期望的格式),并将值乘以256(结果值与网络初始化和学习参数匹配)。 最后,它还返回一个标签向量,一个批处理中的每个图像。

任务:运行学习代码并检查生成的绘图。 培训完成后回答以下问题:
您可以每秒处理多少图片? (看看MATLAB屏幕中的输出)
有两组曲线:能量和预测误差。 你认为是什么区别? 什么是“能量”?
一些曲线标记为“train”和一些其他“val”。 他们应该平等吗? 哪一个应该比另一个低?
绘制了前1和前5的预测误差。 他们的意思是什么? 有什么不同?

一旦训练完成,模型将保存回来:

% Save the result for later use
net.layers(end) = [] ;
net.imageMean = imageMean ;
save('data/chars-experiment/charscnn.mat', '-struct', 'net') ;

注意,我们记住imageMean以供以后使用。 还要注意,softmaxloss层在保存之前从网络中删除。

Part 4.4: visualise the learned filters
第4.4部分:可视化学习的过滤器
下一步是浏览已经学习的过滤器:

figure(2) ; clf ; colormap gray ;
vl_imarraysc(squeeze(net.layers{1}.weights{1}),'spacing',2)
axis equal ;
title('filters in the first layer') ;

这里写图片描述
Task: what can you say about the filters?

Part 4.5: apply the model
第4.5部分:应用模型
我们现在将模型应用于整个字符序列。 这是图像 data/ sentence-lato.png:
这里写图片描述

% Load the CNN learned before
net = load('data/chars-experiment/charscnn.mat') ;

% Load the sentence
im = im2single(imread('data/sentence-lato.png')) ;
im = 256 * (im - net.imageMean) ;

% Apply the CNN to the larger image
res = vl_simplenn(net, im) ;

问题:图像比32像素宽得多。 你为什么可以应用CNN之前学习的 32 times32 补丁?
任务:使用大小(res(end).x)检查CNN输出的大小。 这是否符合您的期望?

现在使用decodeCharacters()函数可视化结果:

% Visualize the results
figure(3) ; clf ;
decodeCharacters(net, imdb, im, res) ;

这里写图片描述
任务:检查decodeCharacters()函数的输出并回答以下问题:
质量的认可是否好?
这是否符合您的验证集中的识别率(在训练期间由cnn_train报告)的期望?

Part 4.6: training with jitter
以前的CNN的一个关键问题是它没有被训练来识别在其他字符的上下文中的字符。 此外,字符在补丁中完全居中。 我们可以通过使训练数据“更现实”来放松这些假设。 在这部分,我们将训练第二个应用数据抖动的网络:

随机添加一个字符到左边和右边的一个识别和随机将字符向水平移动 pm 5 \ pm 2 $ 像素。
这是由getBatchWithJitter()函数实现的(注意,抖动应用在飞行中,因为它是如此之快)
任务:
使用抖动数据训练第二个模型。
看看训练和验证错误。 他们的差距是否和以前一样宽?
使用新模型通过重复上一部分来识别句子中的字符。 它工作更好吗?
还有什么可以改变,使性能更好?

Part 5: using pretrained models
第5部分:使用预训练模型
深度学习的特点是它构造数据的表示。 这些表示倾向于具有普遍价值,或者至少适用于超越模型被训练的特定任务的一系列问题。 这是幸运的,因为训练复杂模型需要几个星期的工作在一个或多个GPU或数百个CPU; 这些模型然后可以被冻结和重用于许多附加应用,没有或最少额外的工作。
在这部分中,我们将看到如何使用MatConvNet下载和运行高性能的CNN模型进行图像分类。 这些模型从ImageNet数据集中的1.2M图像训练,以区分1,000个不同的对象类别。
可以从MatConvNet网站下载几个相关模型,包括使用其他CNN实现(如Caffe)的几个培训。 一个这样的模型包括在data/ imagenet-vgg-verydeep-16.mat文件中。 这是ImageNet ILSVCR挑战赛2014最好的模特之一。

Part 5.1: load a pre-trained model
第一步是加载模型本身。 这是vl_simplenn CNN包装器的格式,并作为MATLAB .mat文件发布:

net = load('data/imagenet-vgg-verydeep-16.mat') ;
vl_simplenn_display(net) ;

任务:

查看vl_simplenn_display的输出并了解模型的结构。 你能理解为什么它被称为“非常深”?
看看文件数据/ imagenet-vgg-verydeep-16.mat在磁盘上的大小。 这只是模型。

Part 5.2: use the model to classify an image
我们现在可以使用模型来分类图像。 我们从peppers.png开始,一个MATLAB库存图像:

% obtain and preprocess an image
im = imread('peppers.png') ;
im_ = single(im) ; % note: 255 range
im_ = imresize(im_, net.normalization.imageSize(1:2)) ;
im_ = im_ - net.normalization.averageImage ;

代码以与模型网兼容的格式使图像规格化。 这相当于:将图像转换为单一格式(但是范围为0,…,255,而不是MATLAB中典型的[0,1]),将图像调整为固定大小,然后减去平均图像。
现在可以调用CNN:

% run the CNN
res = vl_simplenn(net, im_) ;

像往常一样,res包含计算的结果,包括所有中间层。 最后一个可用于执行分类:

% show the classification result
scores = squeeze(gather(res(end).x)) ;
[bestScore, best] = max(scores) ;

figure(1) ; clf ; imagesc(im) ;
title(sprintf('%s (%d), score %.3f',...
  net.classes.description{best}, best, bestScore)) ;

That completes this practical.
链接和进一步的工作
这个实用的代码是使用软件包MatConvNet编写的。 这是一个用MATLAB,C ++和CUDA编写的软件库,可以免费获得源代码和二进制。
ImageNet模型是Karen Simonyan和Andrew Zisserman的VGG非常深的16。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值