注:本系列是基于参考文献中的内容,并对其进行整理,注释形成的一系列关于深度学习的基本理论与实践的材料,基本内容与参考文献保持一致,并对这个专题起名为“利用Theano理解深度学习”系列,若文中有任何问题欢迎咨询。本文提供PDF版本,欢迎索取。

“利用Theano理解深度学习”系列分为 4 4 4个部分,其中第一部分主要包括:

  • 利用Theano理解深度学习——Logistic Regression
  • 利用Theano理解深度学习——Multilayer perceptron
  • 利用Theano理解深度学习——Deep Convolutional Network

一、CNN概述

卷积神经网络(Convolutional Neural Networks, CNN)是多层感知机MLP模型的一个变种,主要是受到生物学的启发。从Hubel和Wiesel早期的有关猫的视觉皮层的工作中我们知道猫的视觉皮层包含了一个复杂的细胞排列。这些细胞对小范围的视觉区域敏感,这样的小范围的视觉区域称为一个感受野(receptive field)。这些小的区域平铺开来可以盖满整个视觉区域。这些细胞就像是一个个的局部过滤器,可以对输入空间的信息进行过滤,并且非常适合在自然图像中发觉在空间上存在极强的局部相关性。

两种基本类型的细胞已经被确认:1、简单的细胞。这些细胞在他们的感受野中最大化的响应特定的类似边缘的模式;2、复杂的细胞。这些细胞拥有较大的感受野,而且对于确切的位置模式是局部不变的。

在现实世界中,动物的视觉皮层是最强大的视觉处理系统,似乎模仿其行为也变得很自然。因此,许多受神经系统启发的模型被发现,如NeoCognitron,HMAX和LeNet-5。

二、CNN的特点

卷积神经网络CNN的特点主要有:1、稀疏连接(局部感受),2、共享权值,3、子采样。其中,稀疏连接主要是通过对数据中的局部区域进行建模以发现局部的一些特性;共享权值的目的为了简化计算的过程,使得需要优化的参数变少;子采样的目的是在解决图像中的平移不变性,即所要识别的内容与其在图像中的具体位置无关。

1、稀疏连接(Sparse Connectivity)

CNN通过在邻接层的神经元之间使用局部连接模式来发现输入特征在空间上存在的局部相关性。如下图所示,第 m m m层的隐层节点的输入是第 m − 1 m-1 m−1层的神经单元的一个子集,这个子集中的神经单元在空间上是连续的,具有连续的感受野,如下图所示:

假设第 m − 1 m-1 m−1层是输入层。在上图中,第 m m m层的神经单元具有在输入层上宽度为 3 3 3的感受野,因此只连接输入层上的 3 3 3个邻接神经元。在 m + 1 m+1 m+1层的神经单元与第 m m m层的神经元之间具有相似的连接特性,即第 m + 1 m+1 m+1层的神经单元在第 m m m层上的感受野的宽度也是 3 3 3,但是他们关于输入层 m − 1 m-1 m−1层的感受野却变大了,如上图中为 5 5 5。每一个单元对于感受野范围之外的其他的神经单元是没有反应的。这样的设计架构就保证了学习到的“过滤器”能够对局部空间上的输入产生最强烈的反应。

然而,正如上面所示,堆叠如此多的层导致这些非线性的“过滤器”变得急剧的“全局化”,例如,对更大的像素空间区域产生响应。在 m + 1 m+1 m+1个隐含层单元上可以对宽度为 5 5 5的非线性特征进行编码。

2、共享权值(Shared Weights)

在CNN中,每一个过滤器 h i h_i hi​在整个感受野中重复。这些重复的单元共享同样的参数(权重向量和偏置),然后形成一个特征映射。

在上图中有 3 3 3个隐含层单元,这些隐含层单元都隶属于同样的特征映射。在上图中,对于同样颜色的特征映射的权重是共享的。梯度下降同样可以被应用于求解这些共享的参数,只是需要对原始的算法进行稍微的修改。共享的权重的梯度只是简单的将每一个共享的权重的梯度相加。

每一个单元重复这样的方法。此外,权值共享可以极大的缩减需要学习的参数的数量,这样就可以加速学习的速度。在模型上的这个约束可以使得CNN在视觉问题上可以获得更好的泛化能力。

3、池化(pooling)

在CNN中,另一个比较重要的概念是池化,在这里使用的是最大池化max-pooling,这是非线性下采样的一种形式。max-pooling将输入图像划分成为一系列的不重叠的正方形区域,然后对于每一个子区域,输出其中的最大值。

对于机器视觉而言,max-pooling的策略是非常有效的,主要有两个原因:

  1. 降低计算量。通过消除非最大值(选择最大值的操作),为上层降低了计算量。
  2. 解决了平移不变性。max-pooling提供了一种变换不变性的形式。假设在卷积层的后面串联一个max-pooling层,对于输入图像中的每一个像素点的位置,与其邻接的有 8 8 8个方向可以变换,如果max-pooling采用的是 2 × 2 2\times 2 2×2大小的正方形区域,在这 8 8 8种可能的结构中,只要有 3 3 3种就能产生与卷积层的输出一样的结果,如果在max-pooling层使用 3 × 3 3\times 3 3×3大小的正方形区域,则只需要 5 5 5种就能产生于卷积层的输出一样的结果。因为在max-pooling层对位置信息提供了额外的鲁棒性,max-pooling的方法是在中间表示的过程中降低维度的一种极其有效的方法。

三、CNN的详细说明和符号描述

特征映射的过程是通过对整个图像的局部区域重复应用一个函数得到的,即对于一个输入图像进行卷积操作指的是利用一个线性过滤器,加上一个偏置项,之后再利用一个非线性函数。

假设 h k h^k hk为某一层上的第 k k k个特征映射,这个特征映射 h k h^k hk由权重 W k W^k Wk和偏置 b k b_k bk​唯一决定,则特征映射 h k h^k hk可以表示为(其中,非线性映射为tanh):

h i , j k = t a n h ( ( W k ∗ x ) i j + b k ) h^k_{i,j}=tanh\left ( \left ( W^k*x \right )_{ij}+b_k \right ) hi,jk​=tanh((Wk∗x)ij​+bk​)

对于一维信号,有以下的卷积定义:

o [ n ] = f [ n ] ∗ g [ n ] = ∑ u = − ∞ ∞ f [ u ] g [ n − u ] = ∑ u = − ∞ ∞ f [ n − u ] g [ u ] o\left [ n \right ]=f\left [ n \right ]\ast g\left [ n \right ]=\sum_{u=-\infty }^{\infty }f\left [ u \right ]g\left [ n-u \right ]=\sum_{u=-\infty }^{\infty }f\left [ n-u \right ]g\left [ u \right ] o[n]=f[n]∗g[n]=u=−∞∑∞​f[u]g[n−u]=u=−∞∑∞​f[n−u]g[u]

推广到二维的形式:

o [ m , n ] = f [ m , n ] ∗ g [ m , n ] = ∑ u = − ∞ ∞ ∑ v = − ∞ ∞ f [ u , v ] g [ m − u , n − v ] o\left [ m,n \right ]=f\left [ m,n \right ]\ast g\left [ m,n \right ]=\sum_{u=-\infty }^{\infty }\sum_{v=-\infty }^{\infty }f\left [ u,v \right ]g\left [ m-u,n-v \right ] o[m,n]=f[m,n]∗g[m,n]=u=−∞∑∞​v=−∞∑∞​f[u,v]g[m−u,n−v]

为了能够对数据进行更丰富的表示,每一个隐含层都由多个特征映射组成,如 { h ( k ) , k = 0 , ⋯ K } \left \{ h^{\left ( k \right )},k=0,\cdots K \right \} {h(k),k=0,⋯K}。隐含层的权重 W W W可以被表示成一个 4 4 4维的张量形式,这个 4 4 4维的张量包含了目标特征映射,源特征映射,源垂直位置和源水平位置的组合。偏置 b b b对每一个目标特征映射可以表示成一个包含一个元素的向量,卷积操作的过程可以通过下图表示:

上图是一个卷积神经网络中的两层。第 m − 1 m-1 m−1层包含了 4 4 4个特征映射,隐含层 m m m包含了两个特征映射,即 h 0 h^0 h0和 h 1 h^1 h1。在 h 0 h^0 h0和 h 1 h^1 h1(图中的蓝色和红色的正方形)中的像素点(神经元的输出)是从第 m − 1 m-1 m−1层的像素点计算得来的。感受野的大小为 2 × 2 2\times 2 2×2。注意:感受野是如何旋转所有的输入特征映射。 h 0 h^0 h0和 h 1 h^1 h1中的权重 W 0 W^0 W0和 W 1 W^1 W1因此是 3 3 3维的权重张量。主要的维表示的是输入特征映射,然而另外两个表示的是像素点的坐标。

将他们放在一起, W i j k l W_{ij}^{kl} Wijkl​表示的连接第 m m m层的第 k k k个特征映射的像素点和第 m − 1 m-1 m−1层的第 l l l个特征映射的坐标为 ( i , j ) (i,j) (i,j)的像素点之间的权重。

四、LeNet

稀疏连接,卷积操作和最大池化是LeNet型的卷积神经网络模型的关键,然而,对于模型的具体细节会差别很大。下图展示的是LeNet模型:

下层主要是由卷积层和最大池化层交替形成的。上层是全连接的,对应为传统的MLP(即隐含层+Logistic回归)。第一个全连接层的输入是所有特征平铺后组成的,这些特征有下层映射得到。

从实现的角度来看,这就意味着哎下层操作的是是 4 4 4维的张量,为了使得这些张量能够被后续的MLP处理,故徐将其按照指定的大小平铺称为 2 2 2维的矩阵形式。

五、Tips和Tricks

1、超参数的选择

CNN的训练是比较棘手的问题,因为相比较于MLP来说,CNN比标准的MLP有更多的超参数。一个经验的法则是:对于学习率和正则化参数通常选择常数,这在优化CNN的过程中要记住。

2、卷积层的过滤器的个数

当需要确定每一层过滤器的个数的时候,记住计算单个卷积过滤器的激活函数时的代价要远比传统的MLP的代价要高。

假设 l − 1 l-1 l−1层包含 K l − 1 K^{l-1} Kl−1个特征映射,每个特征映射的输出大小为 M × N M\times N M×N,假设在第 l l l层存在 K l K^l Kl个大小为 m × n m\times n m×n的过滤器,在计算特征映射时,需要的计算量为:

( M − m ) × ( N − n ) × m × n × K l − 1 × K l \left ( M-m \right )\times \left ( N-n \right )\times m\times n\times K^{l-1}\times K^l (M−m)×(N−n)×m×n×Kl−1×Kl

然而对于标准的MLP,计算量为: K l − 1 × K l K^{l-1}\times K^l Kl−1×Kl。

特征映射的大小会随着深度减少,越靠近输入层,卷积层的过滤器个数越少。

3、卷积层的过滤器的大小

对于卷积层的过滤器的大小,一般取决于具体的数据集。对于数据集MNIST,其大小为 28 × 28 28\times 28 28×28,在该数据集上的最好的结果的过滤器大小为:第一层是 5 × 5 5\times 5 5×5,然而对于自然图像,这些图像的像素点的维度要高于数据集MNIST的图像的大小,一般更趋向于在第一层取更大的过滤器大小,如 12 × 12 12\times 12 12×12或者 15 × 15 15\times 15 15×15。

因此,对于卷积层的过滤器的大小的选择一般是根据给定的数据集中图像的大小而决定的。

4、池化层的最大池化的大小

在池化层,池化的目的是利用图像数据固有的特点,在计算的中间过程中降低数据的维度,一般比较常用的最大池化的大小为 2 × 2 2\times 2 2×2或者不采用最大池化,即设置为 0 0 0,对于特别大的输入图像,在低层,可采用 4 × 4 4\times 4 4×4的池化大小,但是过大的池化大小会在计算过程中丢弃过多的信息,对模型的准确性会造成影响。

六、Theano实现CNN的代码解析

1、导入数据集

导入数据集的过程与Logistic回归中使用的一致。前面已经比较细致的描述 。代码如下:

def load_data(dataset):
'''导入数据
:type dataset: string
:param dataset: MNIST数据集
'''#1、处理文件目录data_dir, data_file = os.path.split(dataset)#把路径分割成dirname和basename,返回一个元组if data_dir == "" and not os.path.isfile(dataset):new_path = os.path.join(os.path.split(__file__)[0],#__file__表示的是当前的路径".","data",dataset)if os.path.isfile(new_path) or data_file == 'mnist.pkl.gz':dataset = new_path#文件所在的目录if (not os.path.isfile(dataset)) and data_file == 'mnist.pkl.gz':import urlliborigin = ('http://www.iro.umontreal.ca/~lisa/deep/data/mnist/mnist.pkl.gz')print 'Downloading data from %s' % originurllib.urlretrieve(origin, dataset)print '... loading data'# 2、打开文件f = gzip.open(dataset, 'rb')# 打开一个gzip已经压缩好的gzip格式的文件,并返回一个文件对象:file object.train_set, valid_set, test_set = cPickle.load(f)#载入本地的文件f.close()'''训练集train_set,验证集valid_set和测试集test_set的格式:元组(input, target)其中,input是一个矩阵(numpy.ndarray),每一行代表一个样本;target是一个向量(numpy.ndarray),大小与input的行数对应'''def shared_dataset(data_xy, borrow=True):data_x, data_y = data_xyshared_x = theano.shared(numpy.asarray(data_x, dtype=theano.config.floatX), borrow=borrow)shared_y = theano.shared(numpy.asarray(data_y, dtype=theano.config.floatX), borrow=borrow)return shared_x, T.cast(shared_y, 'int32')#将shared_y转换成整型#3、将数据处理成需要的形式test_set_x, test_set_y = shared_dataset(test_set)valid_set_x, valid_set_y = shared_dataset(valid_set)train_set_x, train_set_y = shared_dataset(train_set)#4、返回数据集rval = [(train_set_x, train_set_y), (valid_set_x, valid_set_y), (test_set_x, test_set_y)]return rval

2、建立模型

建立模型阶段主要是定义一个卷积+池化的过程,具体代码如下:

class LeNetConvPoolLayer(object):def __init__(self, rng, input, filter_shape, image_shape, poolsize=(2, 2)):""":type rng: numpy.random.RandomState:param rng:用于随机数生成权重 :type input: theano.tensor.dtensor4:param input:卷积+池化层的输入,是一个4维的张量:type filter_shape: tuple or list of length 4:param filter_shape: 卷积层过滤器的大小(number of filters, num input feature maps,filter height, filter width):type image_shape: tuple or list of length 4:param image_shape: 图像的大小(batch size, num input feature maps,image height, image width):type poolsize: tuple or list of length 2:param poolsize: 池化的参数(#rows, #cols)"""assert image_shape[1] == filter_shape[1]self.input = input#fan_in和fan_out主要用于初始化权重参数#卷积层的输入的大小 "num input feature maps * filter height * filter width"fan_in = numpy.prod(filter_shape[1:])#池化层的输出的大小 "num output feature maps * filter height * filter width" /pooling sizefan_out = (filter_shape[0] * numpy.prod(filter_shape[2:]) /numpy.prod(poolsize))#初始化权重W_bound = numpy.sqrt(6. / (fan_in + fan_out))self.W = theano.shared(numpy.asarray(rng.uniform(low=-W_bound, high=W_bound, size=filter_shape),dtype=theano.config.floatX),borrow=True)#初始化偏置b_values = numpy.zeros((filter_shape[0],), dtype=theano.config.floatX)self.b = theano.shared(value=b_values, borrow=True)#定义卷积层conv_out = conv.conv2d(input=input,#卷积层的输入filters=self.W,#卷积层使用的权重filter_shape=filter_shape,#每个过滤器的大小image_shape=image_shape)#定义下采样层pooled_out = downsample.max_pool_2d(input=conv_out,#池化层的输出ds=poolsize,#最大池化的大小ignore_border=True)#加上偏置的过程,最终计算非线性映射self.output = T.tanh(pooled_out + self.b.dimshuffle('x', 0, 'x', 'x'))#模型中的参数,权重和偏置self.params = [self.W, self.b]# keep track of model inputself.input = input

在代码中,注意在卷积层的输出阶段只是将权重乘以输入,然后计算池化,在最终的结果上加上偏置,并进行非线性函数的映射,即利用tanh函数对其进行非线性的映射,这样的操作,主要是因为可以省去很多的计算。

3、训练模型

在模型的训练阶段,主要是将数据通过两个卷积+池化层,最终用过一个MLP计算其分类,并通过梯度下降法对其模型中的参数进行调整,具体的代码如下:

# 三、训练模型
##############################################################################
print '... training'# early-stopping参数
patience = 10000
patience_increase = 2improvement_threshold = 0.995validation_frequency = min(n_train_batches, patience / 2)best_validation_loss = numpy.inf
best_iter = 0
test_score = 0.
start_time = timeit.default_timer()epoch = 0
done_looping = False# 循环训练
while (epoch < n_epochs) and (not done_looping):epoch = epoch + 1# 针对每一批样本for minibatch_index in xrange(n_train_batches):iter = (epoch - 1) * n_train_batches + minibatch_indexif iter % 100 == 0:print 'training @ iter = ', iter# 计算训练的误差cost_ij = train_model(minibatch_index)if (iter + 1) % validation_frequency == 0:# 在验证集上计算误差validation_losses = [validate_model(i) for iin xrange(n_valid_batches)]this_validation_loss = numpy.mean(validation_losses)print('epoch %i, minibatch %i/%i, validation error %f %%' %(epoch, minibatch_index + 1, n_train_batches,this_validation_loss * 100.))# 记录最优的模型if this_validation_loss < best_validation_loss:#improve patience if loss improvement is good enoughif this_validation_loss < best_validation_loss *  \improvement_threshold:patience = max(patience, iter * patience_increase)# save best validation score and iteration numberbest_validation_loss = this_validation_lossbest_iter = itertest_losses = [test_model(i)for i in xrange(n_test_batches)]test_score = numpy.mean(test_losses)print(('     epoch %i, minibatch %i/%i, test error of ''best model %f %%') %(epoch, minibatch_index + 1, n_train_batches,test_score * 100.))if patience <= iter:done_looping = Truebreakend_time = timeit.default_timer()
print('Optimization complete.')
print('Best validation score of %f %% obtained at iteration %i, ''with test performance %f %%' %(best_validation_loss * 100., best_iter + 1, test_score * 100.))
print >> sys.stderr, ('The code for file ' +os.path.split(__file__)[1] +' ran for %.2fm' % ((end_time - start_time) / 60.))

七、实验的结果

部分实验的结果如下:

参考文献

[1] Convolutional Neural Networks (LeNet)http://www.deeplearning.net/tutorial/lenet.html#tips-and-tricks

利用Theano理解深度学习——Convolutional Neural Networks相关推荐

  1. 利用Theano理解深度学习——Logistic Regression

    一.Logistic Regression 1.LR模型 Logistic回归是广义线性模型的一种,属于线性的分类模型,在其模型中主要有两个参数,即:权重矩阵 W W W和偏置向量 b b b.在Lo ...

  2. 吴恩达深度学习笔记——神经网络与深度学习(Neural Networks and Deep Learning)

    文章目录 前言 传送门 神经网络与深度学习(Neural Networks and Deep Learning) 绪论 梯度下降法与二分逻辑回归(Gradient Descend and Logist ...

  3. 深度学习-Non-local Neural Networks非局部神经网络

    Non-local Neural Networks非局部神经网络 0.概述 1.相关工作 1.1.Non-local image processing.(非局部影像处理) 1.2.Graphical ...

  4. 吴恩达深度学习笔记——卷积神经网络(Convolutional Neural Networks)

    深度学习笔记导航 前言 传送门 卷积神经网络(Convolutional Neural Networks) 卷积神经网络基础(Foundations of Convolutional Neural N ...

  5. 论文阅读2018-Deep Convolutional Neural Networks for breast cancer screening 重点:利用迁移学习三个网络常规化进行分类

    论文阅读2018-Deep Convolutional Neural Networks for breast cancer screening 摘要:我们探讨了迁移学习的重要性,并通过实验确定了在训练 ...

  6. 深度学习之卷积神经网络(Convolutional Neural Networks, CNN)(二)

    前面我们说了CNN的一般层次结构, 每个层的作用及其参数的优缺点等内容.深度学习之卷积神经网络(Convolutional Neural Networks, CNN)_fenglepeng的博客-CS ...

  7. 深度学习之卷积神经网络(Convolutional Neural Networks, CNN)

    前面, 介绍了DNN及其参数求解的方法(深度学习之 BP 算法),我们知道DNN仍然存在很多的问题,其中最主要的就是BP求解可能造成的梯度消失和梯度爆炸.那么,人们又是怎么解决这个问题的呢?本节的卷积 ...

  8. 10.深度学习练习:Convolutional Neural Networks: Step by Step(强烈推荐)

    本文节选自吴恩达老师<深度学习专项课程>编程作业,在此表示感谢. 课程链接:https://www.deeplearning.ai/deep-learning-specialization ...

  9. 吴恩达深度学习课程deeplearning.ai课程作业:Class 4 Week 1 Convolutional Neural Networks: Step by Step

    吴恩达deeplearning.ai课程作业,自己写的答案. 补充说明: 1. 评论中总有人问为什么直接复制这些notebook运行不了?请不要直接复制粘贴,不可能运行通过的,这个只是notebook ...

最新文章

  1. 代码注入之远程线程篇
  2. MFC窗口位置和大小的获取
  3. eclipse svn插件安装_Visual SVN和Tortoise SVN的安装简单使用汉化
  4. android视频闪退,安卓 app 视频闪退问题
  5. 如何提升github的clone速度(简单粗暴,亲测有效)
  6. Python实战应用-Clumper库函数全解析
  7. iPhone UITableViewCell如何滚动到视图顶端。
  8. c语言case key pres,C#程序设计B-中国大学mooc-题库零氪
  9. 《统计学习方法》—— 朴素贝叶斯方法、详细推导及其python3实现(二)
  10. 想成为架构师,你必须掌握的CAP细节
  11. Swift 反射 API 及用法
  12. 微信小程序分享/转发功能方法
  13. 揭秘世界最大对撞机:将破解五大科学谜团(图)
  14. Small RNA测序
  15. 【毕业设计】基于大数据的电影数据爬取分析可视化系统
  16. android,adb相关
  17. 连载 北漂十二年祭 3 --Leo第二次面试,无意中的霸王面
  18. Pomelo MMORPG
  19. 嵌入式是什么 ?为什么要学好嵌入式呢?
  20. Android Market api

热门文章

  1. 在解决计算机主机,开机之后显示器黑屏无信号输入,但电脑主机一直在运行的解决方法...
  2. 教师综合素质7--文学常识
  3. 如何在Mac上查看隐藏文件,四个方法
  4. 【C语言初阶】C语句成员1:分支语句
  5. 一个微信小程序的诞生,来自一个互联网新生儿的探索
  6. CKA考试真题-20190714
  7. go 实现微信公众号接口
  8. ubuntu虚拟机VmWare与主机共享文件夹设置
  9. DESeq2包的安装
  10. 学农夏令营活动管理系统