




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、卷积神经网络全面解析 之代码详解本文介绍多层感知机算法,特殊是具体解读其代码实现,基于python theano ,代码来自: convolutional neural networks lenet;一、cnn 卷积神经网络原理简介要讲明白卷积神经网络,估量得长篇大论,网上有许多博文已经写得很好了,所以本文就不重复了,假如你明白cnn ,那可以往下看,本文主要是具体地解读cnn的实现代码;cnn 的最大特点就是稀疏连接(局部感受)和权值共享,如下面两图所示,左为稀疏连接,右为权值共享;稀疏连接和权值共享可以削减所要训练的参数,削减运算复杂度;至于 cnn 的结构,以经典的 lenet5来说明:
2、这个图真是无处不在,一谈 cnn ,必说 lenet5 ,这图来自于这篇论文: gradient- based learning applied to document recognition,论文很长,第 7 页那里开头讲lenet5 这个结构,建议看看那部分;我这里简洁说一下, lenet5这张图从左到右,先是 input ,这是输入层,即输入的图片; input-layer到 c1 这部分就是一个卷积层( convolution运算), c1 到s2 是一个子采样层( pooling运算),关于卷积和子采样的具体过程可以参考下图:34 /19然后, s2 到 c3 又是卷积, c3 到
3、s4 又是子采样,可以发觉,卷积和子采样都是成对显现的,卷积后面一般跟着子采样;s4 到 c5 之间是全连接的,这就相当于一个 mlp 的隐含层了(假如你不清晰mlp ,参考 deeplearning tutorial( 3 ) mlp 多层感知机原理简介 + 代码详解 ); c5 到 f6 同样是全连接,也是相当于一个mlp 的隐含层;最终从 f6 到输出 output,其实就是一个分类器,这一层就叫分类层;ok ,cnn 的基本结构大致就是这样,由输入、卷积层、子采样层、全连接层、分类层、输出这些基本 “构件 ”组成,一般依据具体的应用或者问题,去确定要多少卷积层和子采样层、采纳什么分类器
4、;当确定好了结构以后,如何求解层与层之间的连接参数?一般采纳向前传播( fp)+ 向后传播( bp)的方法来训练;具体可参考上面给出的链接;二、cnn 卷积神经网络代码具体解读(基于 python+theano )代码来自于深度学习教程: convolutional neural networks lenet,这个代码实现的是一个简化了的 lenet5 ,具体如下:.没有实现 location-specific gain and bias parameters.用的是 maxpooling,而不是 average_pooling.分类器用的是 softmax, lenet5用的是 rbf.le
5、net5其次层并不是全连接的,本程序实现的是全连接另外,代码里将卷积层和子采纳层合在一起,定义为“lenetconvpoollayer “ (卷积采样层),这好懂得,由于它们总是成对显现;但是有个地方需要留意,代码中将卷积后的输出直接作为子采样层的输入,而没有加偏置b 再通过 sigmoid函数进行映射,即没有了下图中 fx 后面的 bx 以及 sigmoid映射,也即直接由 fx 得到cx ;最终,代码中第一个卷积层用的卷积核有20 个,其次个卷积层用 50 个,而不是上面那张 lenet5图中所示的 6 个和 16 个;明白了这些,下面看代码:(1 )导入必要的模块import cpick
6、le import gzip import os import sys import timeimport numpyimport theanoimport theano.tensor as tfrom theano.tensor.signal import downsample from theano.tensor.nnet import conv(2 )定义 cnn的基本 构件cnn 的基本构件包括卷积采样层、隐含层、分类器,如下.定义 lenetconvpoollayer (卷积+采样层) 见代码注释:卷积+下采样合成一个层 lenetconvpoollayer rng: 随机数生成器,
7、用于初始化 winput:4维的向量, theano.tensor.dtensor4filter_shape:number of filters, num input feature maps,filter height, filter widthimage_shape:batch size, num input feature maps,image height, image width poolsize: #rows, #colsclass lenetconvpoollayerobject:definitself, rng, input, filter_shape, image_shape
8、, poolsize=2, 2:#assert condition,condition为 true,就连续往下执行, condition为 false ,中断程序#image_shape1 和 filter_shape1都是 num input feature maps,它们必需是一样的;assert image_shape1 = filter_shape1 self.input = input#每个隐层神经元(即像素)与上一层的连接数为num input feature maps * filter height* filter width;#可以用 dfilter_shap
9、e1:来求得fan_in = dfilter_shape1:#lower layer上每个神经元获得的梯度来自于: num output feature maps * filter height* filter width /pooling sizefan_out = filter_shape0 * dfilter_shape2: / dpoolsize#以上求得 fan_in 、fan_out,将它们代入公式,以此来随机初始化w,w就是线性卷积核w_bound = numpy.sqrt6. / fan_in + fan_outself.w
10、 = theano.shared numpy.asarrayrng.uniformlow=-w_bound, high=w_bound, size=filter_shape,dtype=theano.config.floatx,borrow=true# the bias is a 1d tensor - one bias per output feature map #偏置 b 是一维向量,每个输出图的特点图都对应一个偏置,#而输出的特点图的个数由filter个数打算,因此用 filter_shape0即 number of filters来初始化b_values = numpy.zerosf
11、ilter_shape0, dtype=theano.config.floatx self.b = theano.sharedvalue=b_values, borrow=true#将输入图像与 filter卷积, conv.conv2d 函数#卷积完没有加 b 再通过 sigmoid ,这里是一处简化;conv_out = conv.conv2d input=input, filters=self.w, filter_shape=filter_shape,image_shape=image_shape#maxpooling ,最大子采样过程pooled_out = downsample.ma
12、x_pool_2d input=conv_out,ds=poolsize,ignore_border=true#加偏置,再通过 tanh 映射,得到卷积 +子采样层的最终输出#由于 b 是一维向量,这里用维度转换函数dimshuffle将其 reshape ;比如 b 是10, ,#就 b.dimshufflex, 0, x, x将其 reshape 为1,10,1,1 self.output = t.tanhpooled_out + self.b.dimshufflex, 0, x, x#卷积+采样层的参数 self.params = self.w, self.b.定义隐含层 hiddenl
13、ayer这个跟上一篇文章 deeplearning tutorial(3 )mlp 多层感知机原理简介 + 代码详解 中的 hiddenlayer是一样的,直接拿过来:注释:这是定义隐匿层的类,第一明确:隐匿层的输入即input ,输出即隐匿层的神经元个数;输入层与隐匿层是全连接的;假设输入是 n_in 维的向量(也可以说时 n_in 个神经元),隐匿层有n_out 个神经元,就由于是全连接,一共有 n_in*n_out个权重,故 w大小时 n_in,n_out,n_in行 n_out 列,每一列对应隐匿层的每一个神经元的连接权重;b 是偏置,隐匿层有 n_out 个神经元,故 b 时 n_o
14、ut 维向量;rng 即随机数生成器, numpy.random.randomstate,用于初始化 w;input训练模型所用到的全部输入,并不是mlp的输入层, mlp的输入层的神经元个数时n_in ,而这里的参数 input大小是( n_example,n_in ), 每一行一个样本,即每一行作为mlp的输入层;activation:激活函数 , 这里定义为函数 tanh class hiddenlayerobject:definitself, rng, input, n_in, n_out, w=none, b=none, activation=t.tanh:self.input =
15、input#类 hiddenlayer 的 input即所传递进来的 input注释:代码要兼容 gpu,就必需使用 dtype=theano.config.floatx,并且定义为theano.shared另外, w的初始化有个规章:假如使用 tanh 函数,就在 -sqrt6./n_in+n_hidden到 sqrt6./n_in+n_hidden之间匀称抽取数值来初始化 w,如时 sigmoid 函数,就以上再乘 4 倍;#假如 w未初始化,就依据上述方法初始化;加入这个判定的缘由是:有时候我们可以用训练好的参数来初始化w,见我的上一篇文章;if w is none:w_values =
16、 numpy.asarrayrng.uniformlow=-numpy.sqrt6. / n_in + n_out, high=numpy.sqrt6. / n_in + n_out, size=n_in, n_out,dtype=theano.config.floatxif activation = theano.tensor.nnet.sigmoid: w_values *= 4w = theano.sharedvalue=w_values, name=w, borrow=trueif b is none:b_values = numpy.zerosn_out, dtype=theano.
17、config.floatx b = theano.sharedvalue=b_values, name=b, borrow=true#用上面定义的 w、b 来初始化类 hiddenlayer 的 w、b self.w = wself.b = b#隐含层的输出lin_output = t.dotinput, self.w + self.b self.output = lin_output if activation is none else activationlin_output#隐含层的参数self.params = self.w, self.b.定义分类器 (softmax 回来)采纳 s
18、oftmax,这跟 deeplearning tutorial(1 )softmax回来原理简介 + 代码详解中的 logisticregression是一样的,直接拿过来:定义分类层 logisticregression,也即 softmax 回来在 deeplearning tutorial中,直接将 logisticregression视为 softmax, 而我们所熟悉的二类别的规律回来就是当n_out=2 时的 logisticregression #参数说明:#input ,大小就是 n_example,n_in,其中 n_example 是一个 batch 的大小,#由于我们训练
19、时用的是 minibatch sgd ,因此 input这样定义#n_in, 即上一层 隐含层 的输出#n_out, 输出的类别数class logisticregressionobject:definitself, input, n_in, n_out:#w大小是 n_in 行 n_out 列, b 为 n_out 维向量;即:每个输出对应 w的一列以及 b 的一个元素;self.w = theano.shared value=numpy.zerosn_in, n_out, dtype=theano.config.floatx,name=w, borrow=trueself.b = thea
20、no.shared value=numpy.zerosn_out,dtype=theano.config.floatx,name=b, borrow=true#input是n_example,n_in,w是( n_in,n_out ), 点乘得到 n_example,n_out,加上偏置b,#再作为 t.nnet.softmax的输入,得到 p_y_given_x#故 p_y_given_x 每一行代表每一个样本被估量为各类别的概率#ps:b 是 n_out 维向量,与 n_example,n_out矩阵相加,内部其实是先复制n_example 个b,#然后n_example,n_out矩阵的
21、每一行都加 bself.p_y_given_x = t.nnet.softmaxt.dotinput, self.w + self.b#argmax 返回最大值下标,由于本例数据集是mnist,下标刚好就是类别; axis=1 表示按行操作;self.y_pred = t.argmaxself.p_y_given_x, axis=1#params,logisticregression的参数self.params = self.w, self.b到这里, cnn 的基本 ”构件 “都有了,下面要用这些 ”构件“组装成 lenet5 (当然, 是简化的,上面已经说了),具体来说,就是组装成:len
22、et5=input+lenetconvpoollayer_1+lenetconvpoollayer_2+hiddenl ayer+logisticregression+output;然后将其应用于 mnist数据集,用 bp 算法去解这个模型,得到最优的参数;(3 )加载 mnist数据集( mnist.pkl.gz)加载 mnist数据集 load_data def load_datadataset:# dataset是数据集的路径,程序第一检测该路径下有没有mnist数据集,没有的话就下载mnist数据集#这一部分就不说明了,与softmax回来算法无关;data_dir, data_fi
23、le = os.path.splitdataset if data_dir = and not os.path.is:# check if dataset is in the data directory. new_path = os.path.joinos.path.splitfile0,.,data, datasetif os.path.is or data_ mnist.pkl.gz: dataset = new_pathif not os.path.is and data_ mnist.pkl.gz: import urlliborigin = print downloading da
24、ta from %s % origin urllib.urlretrieveorigin, datasetprint . loading data#以上是检测并下载数据集mnist.pkl.gz,不是本文重点;下面才是load_data的开头#从 mnist.pkl.gz里加载 train_set, valid_set, test_set,它们都是包括 label的#主要用到 python里的 gzip.open函数, 以及 cpickle.load;#rb 表示以二进制可读的方式打开文件f = gzip.opendataset, rbtrain_set, valid_set, test_se
25、t = cpickle.loadf f.close#将数据设置成 shared variables,主要时为了gpu加速,只有 shared variables才能存到 gpu memory中#gpu里数据类型只能是float;而 data_y 是类别,所以最终又转换为int返回def shared_datasetdata_xy, borrow=true: data_x, data_y = data_xyshared_x = theano.sharednumpy.asarraydata_x,dtype=theano.config.floatx, borrow=borrowshared_y =
26、theano.sharednumpy.asarraydata_y,dtype=theano.config.floatx, borrow=borrowreturn shared_x, t.castshared_y, int32test_set_x, test_set_y = shared_datasettest_set valid_set_x, valid_set_y = shared_datasetvalid_set train_set_x, train_set_y = shared_datasettrain_setrval = train_set_x, train_set_y, valid_
27、set_x, valid_set_y, test_set_x, test_set_yreturn rval(4 )实现 lenet5并测试实现 lenet5lenet5 有两个卷积层,第一个卷积层有20 个卷积核,其次个卷积层有 50 个卷积核def evaluate_lenet5learning_rate=0.1, n_epochs=200, dataset=mnist.pkl.gz,nkerns=20, 50, batch_size=500:learning_rate:学习速率,随机梯度前的系数;n_epochs 训练步数,每一步都会遍历全部batch ,即全部样本batch_size,这
28、里设置为 500,即每遍历完 500 个样本,才运算梯度并更新参数nkerns=20, 50,每一个 lenetconvpoollayer 卷积核的个数,第一个lenetconvpoollayer有20 个卷积核,其次个有 50 个rng = numpy.random.randomstate23455#加载数据datasets = load_datadataset train_set_x, train_set_y = datasets0 valid_set_x, valid_set_y = datasets1 test_set_x, test_set_y = datasets2#运算 batc
29、h 的个数n_train_batches = train_set_x.get_valueborrow=true.shape0 n_valid_batches = valid_set_x.get_valueborrow=true.shape0 n_test_batches = test_set_x.get_valueborrow=true.shape0 n_train_batches /= batch_sizen_valid_batches /= batch_sizen_test_batches /= batch_size#定义几个变量, index 表示 batch 下标, x 表示输入的训练
30、数据, y 对应其标签index = t.lscalar x = t.matrixxy = t.ivectory# # build actual model #print . building the model#我们加载进来的 batch 大小的数据是 batch_size, 28 * 28,但是 lenetconvpoollayer 的输入是四维的,所以要 reshapelayer0_input = x.reshapebatch_size, 1, 28, 28# layer0即第一个 lenetconvpoollayer 层#输入的单张图片 28,28 ,经过 conv 得到28-5+1
31、, 28-5+1 = 24, 24,#经过 maxpooling 得到24/2, 24/2 = 12, 12#由于每个 batch 有 batch_size张图,第一个 lenetconvpoollayer 层有 nkerns0 个卷积核,#故 layer0输出为batch_size, nkerns0, 12, 12 layer0 = lenetconvpoollayerrng, input=layer0_input,image_shape=batch_size, 1, 28, 28,filter_shape=nkerns0, 1, 5, 5,poolsize=2, 2#layer1即其次个
32、lenetconvpoollayer 层#输入是 layer0的输出,每张特点图为 12,12,经过 conv 得到12-5+1, 12-5+1 = 8, 8, #经过 maxpooling 得到8/2, 8/2 = 4, 4#由于每个 batch 有 batch_size张图(特点图),其次个 lenetconvpoollayer 层有 nkerns1个卷积核#,故 layer1输出为 batch_size, nkerns1, 4, 4 layer1 = lenetconvpoollayerrng,input=layer0.output,image_shape=batch_size, nke
33、rns0, 12, 12,#输入 nkerns0 张特点图,即layer0输出 nkerns0张特点图filter_shape=nkerns1, nkerns0, 5, 5,poolsize=2, 2#前面定义好了两个 lenetconvpoollayer (layer0和 layer1 ), layer1后面接 layer2 ,这是一个全连接层,相当于 mlp里面的隐含层#故可以用 mlp中定义的 hiddenlayer 来初始化 layer2 ,layer2的输入是二维的 batch_size, num_pixels,#故要将上层中同一张图经不同卷积核卷积出来的特点图合并为一维向量,#也就
34、是将 layer1的输出 batch_size, nkerns1, 4, 4flatten为batch_size, nkerns1*4*4=500, 800, 作为 layer2的输入;#500 , 800 表示有 500 个样本,每一行代表一个样本;layer2的输出大小是batch_size,n_out=500,500 layer2_input = layer1.output.flatten2 layer2 = hiddenlayerrng, input=layer2_input, n_in=nkerns1 * 4 * 4, n_out=500, activation=t.tanh#最终一
35、层 layer3是分类层,用的是规律回来中定义的logisticregression,#layer3的输入是 layer2的输出 500,500 , layer3的输出就是batch_size,n_out=500,10layer3 = logisticregressioninput=layer2.output, n_in=500, n_out=10#代价函数 nllcost = layer3.negative_log_likelihoody# test_model运算测试误差, x、y 依据给定的 index 具体化,然后调用 layer3 ,#layer3又会逐层地调用 layer2 、la
36、yer1 、layer0 ,故 test_model其实就是整个 cnn结构, #test_model 的输入是 x、y,输出是 layer3.errorsy的输出,即误差;test_model = theano.function index,layer3.errorsy, givens=x: test_set_xindex * batch_size: index + 1 * batch_size,y: test_set_yindex * batch_size: index + 1 * batch_size#validate_model,验证模型,分析同上;validate_model = t
37、heano.function index,layer3.errorsy, givens=x: valid_set_xindex * batch_size: index + 1 * batch_size, y: valid_set_yindex * batch_size: index + 1 * batch_size#下面是 train_model ,涉及到优化算法即 sgd,需要运算梯度、更新参数 #参数集params = layer3.params + layer2.params + layer1.params + layer0.params#对各个参数的梯度grads = t.gradco
38、st, params#由于参数太多,在 updates 规章里面一个一个具体地写出来是很麻烦的,所以下面用了一个for.in.,自动生成规章对 param_i, param_i - learning_rate * grad_i updates = param_i, param_i - learning_rate * grad_i for param_i, grad_i in zipparams, grads#train_model,代码分析同 test_model ;train_model里比 test_model、validation_model多出 updates规章train_model
39、 = theano.function index,cost, updates=updates, givens=x: train_set_xindex * batch_size: index + 1 * batch_size, y: train_set_yindex * batch_size: index + 1 * batch_size#开头训练 # #print . training patience = 10000patience_increase = 2improvement_threshold = 0.995validation_frequency = minn_train_batch
40、es, patience / 2# 这样设置 validation_frequency可以保证每一次 epoch 都会在验证集上测试;best_validation_loss = numpy.inf#最好的验证集上的 loss ,最好即最小best_iter = 0#最好的迭代次数,以 batch 为单位;比如best_iter=10000,说明在训练完第 10000 个 batch 时,达到 best_validation_loss test_score = 0.start_time = time.clockepoch = 0 done_looping = false#下面就是训练过程了,
41、while 循环掌握的时步数 epoch,一个 epoch 会遍历全部的 batch ,即全部的图片;#for 循环是遍历一个个 batch ,一次一个 batch 地训练; for 循环体里会用train_modelminibatch_index去训练模型,#train_model里面的 updatas 会更新各个参数;#for 循环里面会累加训练过的 batch 数 iter,当 iter是 validation_frequency倍数时就会在验证集上测试,#假如验证集的缺失 this_validation_loss小于之前正确的缺失 best_validation_loss,#就更新 best_validation_loss和 best_iter,同时在 test
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 临汾市大宁县2024-2025学年数学三下期末经典模拟试题含解析
- 辽宁省新宾县联考2024-2025学年初三四模英语试题试卷含答案
- 西藏省重点中学2025年中考语文试题5月冲刺题含解析
- 江西应用工程职业学院《医疗器械注册与质量管理》2023-2024学年第一学期期末试卷
- 吉林工程技术师范学院《医学昆虫学》2023-2024学年第一学期期末试卷
- 江西2025年数学三下期末达标检测模拟试题含解析
- 四川西南航空职业学院《家具展示设计》2023-2024学年第二学期期末试卷
- 昆山登云科技职业学院《冶金学术基础英语》2023-2024学年第一学期期末试卷
- 郑州旅游职业学院《通信工程专业导论》2023-2024学年第一学期期末试卷
- 开封大学《学前儿童社会活动设计与指导》2023-2024学年第二学期期末试卷
- 《民航重大安全隐患判定标准(2024 年修订版)》知识培训
- 国家安全你我有责-2025全民国家安全教育日主题宣教课件
- 楼梯 栏杆 栏板(一)22J403-1
- 合同工期延期补充协议书
- 幼儿园绘本故事《三只小猪盖房子》教学课件全文
- JBT 7387-2014 工业过程控制系统用电动控制阀
- 2024年河南省水务规划设计研究有限公司人才招聘笔试参考题库附带答案详解
- 【基于STM32智能门锁系统的设计10000字(论文)】
- 音调控制电路模拟部分
- 会计制度设计教案
- 灯具产品合格证
评论
0/150
提交评论