前面我们完成了数据的下载和预处理,接下来就该搭建网络模型了,CNN网络的东西可以参考博主 zouxy09的系列文章Deep Learning (深度学习) 学习笔记整理系列之 (七)

  1. 加载包

  1. require 'torch' 
  2. require 'image' 
  3. require 'nn' 
  1. 函数运行参数的设置

  1. if not opt then 
  2. print "==> processing options" 
  3. cmd = torch.CmdLine() 
  4. cmd:text() 
  5. cmd:text('options:'
  6. -- 选择构建何种结构:线性|MLP|ConvNet。默认:convnet 
  7. cmd:option('-model','convnet','type of model to construct: linear | mlp | convnet'
  8. -- 是否需要可视化 
  9. cmd:option('-visualize',true,'visualize input data and weights during training'
  10. -- 参数 
  11. opt = cmd:parse(arg or {}) 
  12. end 
  1. 设置网络模型用到的一些参数

  1. -- 输出类别数,也就是输出节点个数 
  2. noutputs =10 
  3. -- 输入节点的个数 
  4. nfeats = 3 -- YUV三个通道,可以认为是3个features map 
  5. width =32 
  6. height =32 
  7. -- Linear 和 mlp model下的输入节点个数,就是将输入图像拉成列向量 
  8. ninputs = nfeats*width*height 
  9.  
  10. -- 为mlp定义隐层节点的个数 
  11. nhiddens = ninputs/2  
  12.  
  13. -- 为convnet定义隐层feature maps的个数以及滤波器的尺寸 
  14. nstates = {16,256,128} --第一个隐层有16个feature map,第二个隐层有256个特征图,第三个隐层有128个节点 
  15. fanin = {1,4} -- 定义了卷积层的输入和输出对应关系,以fanin[2]举例,表示该卷积层有16个map输入,256个map输出,每个输出map是有fanin[2]个输入map对应filters卷积得到的结果 
  16. filtsize =5 --滤波器的大小,方形滤波器 
  17. poolsize = 2 -- 池化池尺寸 
  18. normkernel = image.gaussian1D(7) --长度为7的一维高斯模板,用来local contrast normalization 
  1. 构建模型

  1. if opt.model == linear then  
  2. -- 线性模型 
  3. model = nn.Sequntial() 
  4. model:add(nn.Reshape(ninputs)) -- 输入层 
  5. model:add(nn.Linear(ninputs,noutputs)) -- 线性模型 y=Wx+b 
  6. elseif opt.model == mlp then  
  7. -- 多层感知器 
  8. model = nn.Sequential() 
  9. model:add(nn.Reshape(ninputs)) --输入层 
  10. model:add(nn.Linear(ninputs,nhiddens)) --线性层 
  11. model:add(nn.Tanh()) -- 非线性层 
  12. model:add(nn.Linear(nhiddens,noutputs)) -- 线性层 
  13. -- MLP 目标: `!$y=W_2 f(W_1X+b) + b $` 这里的激活函数采用的是Tanh(),MLP后面还可以接一层输出层Tanh() 
  14. elseif opt.model == convnet then 
  15. -- 卷积神经网络 
  16. model = nn.Sequential() 
  17. -- 第一阶段 
  18. model:add(nn.SpatialConvolutionMap(nn.tables.random(nfeats,nstates[1],fanin[1]),filtsize,filtsize)) 
  19. -- 这一步直接输入的是图像进行卷积,所以没有了 nn.Reshape(ninputs)输入层。 参数:nn.tables.random(nfeats,nstates[1],fanin[1])指定了卷积层中输入maps和输出maps之间的对应关系,这里表示bstates[1]个输出maps的每一map都是由fanin[1]个输入maps得到的。filtsize则是卷积算子的大小 
  20. -- 所以该层的连接个数为(filtsize*filtsize*fanin[1]+1)*nstates[1],1是偏置。这里的fanin[1]连接是随机的,也可以采用全连接 nn.tables.full(nfeats,nstates[1]), 当输入maps和输出maps个数相同时,还可以采用一对一连接 nn.tables.oneToOne(nfeats). 
  21. -- 参见解释文档 [Convolutional layers](https://github.com/torch/nn/blob/master/doc/concolution.md#nn.convlayers.dok) 
  22.  
  23. model:add(nn.Tanh()) --非线性变换层 
  24. model:SpatialLPPooling(nstates[1],2,poolsize,poolsize,poolsize,poolsize) 
  25. -- 参数(feature maps个数,Lp范数,池化尺寸大小(w,h), 滑动窗步长(dw,dh)) 
  26. model:SpatialSubtractiveNormalization(nstates[1],normalkernel) 
  27. -- local contrast normalization 
  28. -- 具体操作是先在每个map的local邻域进行减法归一化,然后在不同的feature map上进行除法归一化。类似与图像点的均值化和方差归一化。参考[1^x][Nonlinear Image Representation Using Divisive Normalization], [Gaussian Scale Mixtures](stats.stackexchange.com/174502/what-are gaussian-scale-mixtures-and-how-to-generate-samples-of-gaussian-scale),还有解释文档 [Convolutional layers](https://github.com/torch/nn/blob/master/doc/concolution.md#nn.convlayers.dok) 
  29.  
  30. --[[ 
  31. 这里需要说的一点是传统的CNN一般是先卷积再池化再非线性变换,但这两年CNN一般都是先非线性变换再池化了 
  32. --]] 
  33. -- 第二阶段 
  34. model:add(nn.SpatialConvolutionMap(nn.tables.random(nstates[1],nstates[2],fanin[2]),filtsize,filtsize)) 
  35. model:add(nn.Tanh()) 
  36. model:add(nn.SpatialLPPooling(nstates[2],2,poolsize,poolsize)) 
  37. model:add(nn.SpatialSubtractiveNormalization(nstates[2],kernel)) 
  38.  
  39. --第三阶段 
  40. model:add(nn.Reshape(nstates[2]*filtsize*filtsize)) --矢量化,全连接 
  41. model:add(nn.Linear(nstates[2]*filtsize*filtsize,nstates[3])) 
  42. model:add(nn.Tanh()) 
  43. model:add(nn.Linear(nstates[3],noutputs)) 
  44. else 
  45. error('unknown -model'
  46. end 
  1. 显示网络结构以及参数

  1. print('==> here is the model'
  2. print(model) 

结果如下图

 

torch 深度学习 (2)

model.png

 

可以发现,可训练参数分别在1,5部分,所以可以观察权重矩阵的大小

  1. print('==> 权重矩阵的大小 '
  2. print(model:get(1).weight:size()) 
  3. print('==> 偏置的大小'
  4. print(model:get(1).bias:numel()) 

 

torch 深度学习 (2)

weights numel.png

 

  1. 参数的可视化

  1. if opt.visualize then 
  2. image.display(image=model:get(1).weight, padding=2,zoom=4,legend='filters@ layer 1'
  3. image.diaplay(image=model:get(5).weight,padding=2,zoom=4,legend='filters @ layer 2'
  4. end 

 

torch 深度学习 (2)

weights visualization.png

 

相关文章: