卷积神经网络CNN代码实现MNIST解析摘要.docx
- 文档编号:11820439
- 上传时间:2023-06-02
- 格式:DOCX
- 页数:47
- 大小:25.36KB
卷积神经网络CNN代码实现MNIST解析摘要.docx
《卷积神经网络CNN代码实现MNIST解析摘要.docx》由会员分享,可在线阅读,更多相关《卷积神经网络CNN代码实现MNIST解析摘要.docx(47页珍藏版)》请在冰点文库上搜索。
卷积神经网络CNN代码实现MNIST解析摘要
卷积神经网络(CNN)代码实现(MNIST)解析
共7层:
依次为输入层、C1层、S2层、C3层、S4层、C5层、输出层,C代表卷积层(特征提取),S代表降采样层或池化层(Pooling),输出层为全连接层。
1.各层权值、偏置(阈值)初始化:
各层权值、偏置个数计算如下:
(1)、输入层:
预处理后的32*32图像数据,无权值和偏置;
(2)、C1层:
卷积窗大小5*5,输出特征图数量6,卷积窗种类1*6=6,输出特征图大小28*28,因此可训练参数(权值+偏置):
(5*5*1)*6+6=150+6;
(3)、S2层:
卷积窗大小2*2,输出下采样图数量6,卷积窗种类6,输出下采样图大小14*14,因此可训练参数(权值+偏置):
1*6+6=6+6;
(4)、C3层:
卷积窗大小5*5,输出特征图数量16,卷积窗种类6*16=96,输出特征图大小10*10,因此可训练参数(权值+偏置):
(5*5*6)*16+16=2400+16;
(5)、S4层:
卷积窗大小2*2,输出下采样图数量16,卷积窗种类16,输出下采样图大小5*5,因此可训练参数(权值+偏置):
1*16+16=16+16;
(6)、C5层:
卷积窗大小5*5,输出特征图数量120,卷积窗种类16*120=1920,输出特征图大小1*1,因此可训练参数(权值+偏置):
(5*5*16)*120+120=48000+120;
(7)、输出层:
卷积窗大小1*1,输出特征图数量10,卷积窗种类120*10=1200,输出特征图大小1*1,因此可训练参数(权值+偏置):
(1*120)*10+10=1200+10.
代码段如下:
[cpp]viewplaincopy
#definenum_map_input_CNN1//输入层map个数
#definenum_map_C1_CNN6//C1层map个数
#definenum_map_S2_CNN6//S2层map个数
#definenum_map_C3_CNN16//C3层map个数
#definenum_map_S4_CNN16//S4层map个数
#definenum_map_C5_CNN120//C5层map个数
#definenum_map_output_CNN10//输出层map个数
#definelen_weight_C1_CNN150//C1层权值数,(5*5*1)*6=150
#definelen_bias_C1_CNN6//C1层阈值数,6
#definelen_weight_S2_CNN6//S2层权值数,1*6=6
#definelen_bias_S2_CNN6//S2层阈值数,6
#definelen_weight_C3_CNN2400//C3层权值数,(5*5*6)*16=2400
#definelen_bias_C3_CNN16//C3层阈值数,16
#definelen_weight_S4_CNN16//S4层权值数,1*16=16
#definelen_bias_S4_CNN16//S4层阈值数,16
#definelen_weight_C5_CNN48000//C5层权值数,(5*5*16)*120=48000
#definelen_bias_C5_CNN120//C5层阈值数,120
#definelen_weight_output_CNN1200//输出层权值数,(1*120)*10=1200
#definelen_bias_output_CNN10//输出层阈值数,10
#definenum_neuron_input_CNN1024//输入层神经元数,(32*32)*1=1024
#definenum_neuron_C1_CNN4704//C1层神经元数,(28*28)*6=4704
#definenum_neuron_S2_CNN1176//S2层神经元数,(14*14)*6=1176
#definenum_neuron_C3_CNN1600//C3层神经元数,(10*10)*16=1600
#definenum_neuron_S4_CNN400//S4层神经元数,(5*5)*16=400
#definenum_neuron_C5_CNN120//C5层神经元数,(1*1)*120=120
#definenum_neuron_output_CNN10//输出层神经元数,(1*1)*10=10
权值、偏置初始化:
(1)、权值使用函数uniform_real_distribution均匀分布初始化,tiny-cnn中每次初始化权值数值都相同,这里作了调整,使每次初始化的权值均不同。
每层权值初始化大小范围都不一样;
(2)、所有层的偏置均初始化为0.
代码段如下:
[cpp]viewplaincopy
doubleCNN:
:
uniform_rand(doublemin,doublemax)
{
//staticstd:
:
mt19937gen
(1);
std:
:
random_devicerd;
std:
:
mt19937gen(rd());
std:
:
uniform_real_distribution
returndst(gen);
}
boolCNN:
:
uniform_rand(double*src,intlen,doublemin,doublemax)
{
for(inti=0;i src[i]=uniform_rand(min,max); } returntrue; } boolCNN: : initWeightThreshold() { srand(time(0)+rand()); constdoublescale=6.0; doublemin_=-std: : sqrt(scale/(25.0+150.0)); doublemax_=std: : sqrt(scale/(25.0+150.0)); uniform_rand(weight_C1,len_weight_C1_CNN,min_,max_); for(inti=0;i bias_C1[i]=0.0; } min_=-std: : sqrt(scale/(4.0+1.0)); max_=std: : sqrt(scale/(4.0+1.0)); uniform_rand(weight_S2,len_weight_S2_CNN,min_,max_); for(inti=0;i bias_S2[i]=0.0; } min_=-std: : sqrt(scale/(150.0+400.0)); max_=std: : sqrt(scale/(150.0+400.0)); uniform_rand(weight_C3,len_weight_C3_CNN,min_,max_); for(inti=0;i bias_C3[i]=0.0; } min_=-std: : sqrt(scale/(4.0+1.0)); max_=std: : sqrt(scale/(4.0+1.0)); uniform_rand(weight_S4,len_weight_S4_CNN,min_,max_); for(inti=0;i bias_S4[i]=0.0; } min_=-std: : sqrt(scale/(400.0+3000.0)); max_=std: : sqrt(scale/(400.0+3000.0)); uniform_rand(weight_C5,len_weight_C5_CNN,min_,max_); for(inti=0;i bias_C5[i]=0.0; } min_=-std: : sqrt(scale/(120.0+10.0)); max_=std: : sqrt(scale/(120.0+10.0)); uniform_rand(weight_output,len_weight_output_CNN,min_,max_); for(inti=0;i bias_output[i]=0.0; } returntrue; } 2.加载MNIST数据: 关于MNIST的介绍可以参考: 使用MNIST库作为训练集和测试集,训练样本集为60000个,测试样本集为10000个。 (1)、MNIST库中图像原始大小为28*28,这里缩放为32*32,数据取值范围为[-1,1],扩充值均取-1,作为输入层输入数据。 代码段如下: [cpp]viewplaincopy staticvoidreadMnistImages(std: : stringfilename,double*data_dst,intnum_image) { constintwidth_src_image=28; constintheight_src_image=28; constintx_padding=2; constinty_padding=2; constdoublescale_min=-1; constdoublescale_max=1; std: : ifstreamfile(filename,std: : ios: : binary); assert(file.is_open()); intmagic_number=0; intnumber_of_images=0; intn_rows=0; intn_cols=0; file.read((char*)&magic_number,sizeof(magic_number)); magic_number=reverseInt(magic_number); file.read((char*)&number_of_images,sizeof(number_of_images)); number_of_images=reverseInt(number_of_images); assert(number_of_images==num_image); file.read((char*)&n_rows,sizeof(n_rows)); n_rows=reverseInt(n_rows); file.read((char*)&n_cols,sizeof(n_cols)); n_cols=reverseInt(n_cols); assert(n_rows==height_src_image&&n_cols==width_src_image); intsize_single_image=width_image_input_CNN*height_image_input_CNN; for(inti=0;i intaddr=size_single_image*i; for(intr=0;r for(intc=0;c unsignedchartemp=0; file.read((char*)&temp,sizeof(temp)); data_dst[addr+width_image_input_CNN*(r+y_padding)+c+x_padding]=(temp/255.0)*(scale_max-scale_min)+scale_min; } } } } (2)、对于Label,输出层有10个节点,对应位置的节点值设为0.8,其它节点设为-0.8,作为输出层数据。 代码段如下: [cpp]viewplaincopy在CODE上查看代码片派生到我的代码片 staticvoidreadMnistLabels(std: : stringfilename,double*data_dst,intnum_image) { constdoublescale_max=0.8; std: : ifstreamfile(filename,std: : ios: : binary); assert(file.is_open()); intmagic_number=0; intnumber_of_images=0; file.read((char*)&magic_number,sizeof(magic_number)); magic_number=reverseInt(magic_number); file.read((char*)&number_of_images,sizeof(number_of_images)); number_of_images=reverseInt(number_of_images); assert(number_of_images==num_image); for(inti=0;i unsignedchartemp=0; file.read((char*)&temp,sizeof(temp)); data_dst[i*num_map_output_CNN+temp]=scale_max; } }staticvoidreadMnistLabels(std: : stringfilename,double*data_dst,intnum_image) { constdoublescale_max=0.8; std: : ifstreamfile(filename,std: : ios: : binary); assert(file.is_open()); intmagic_number=0; intnumber_of_images=0; file.read((char*)&magic_number,sizeof(magic_number)); magic_number=reverseInt(magic_number); file.read((char*)&number_of_images,sizeof(number_of_images)); number_of_images=reverseInt(number_of_images); assert(number_of_images==num_image); for(inti=0;i unsignedchartemp=0; file.read((char*)&temp,sizeof(temp)); data_dst[i*num_map_output_CNN+temp]=scale_max; } } 3.前向传播: 主要计算每层的神经元值;其中C1层、C3层、C5层操作过程相同;S2层、S4层操作过程相同。 (1)、输入层: 神经元数为(32*32)*1=1024。 (2)、C1层: 神经元数为(28*28)*6=4704,分别用每一个5*5的卷积图像去乘以32*32的图像,获得一个28*28的图像,即对应位置相加再求和,stride长度为1;一共6个5*5的卷积图像,然后对每一个神经元加上一个阈值,最后再通过tanh激活函数对每一神经元进行运算得到最终每一个神经元的结果。 激活函数的作用: 它是用来加入非线性因素的,解决线性模型所不能解决的问题,提供网络的非线性建模能力。 如果没有激活函数,那么该网络仅能够表达线性映射,此时即便有再多的隐藏层,其整个网络跟单层神经网络也是等价的。 因此也可以认为,只有加入了激活函数之后,深度神经网络才具备了分层的非线性映射学习能力。 代码段如下: [cpp]viewplaincopy在CODE上查看代码片派生到我的代码片 doubleCNN: : activation_function_tanh(doublex) { doubleep=std: : exp(x); doubleem=std: : exp(-x); return(ep-em)/(ep+em); } boolCNN: : Forward_C1() { init_variable(neuron_C1,0.0,num_neuron_C1_CNN); for(into=0;o for(intinc=0;inc intaddr1=get_index(0,0,num_map_input_CNN*o+inc,width_kernel_conv_CNN,height_kernel_conv_CNN,num_map_C1_CNN*num_map_input_CNN); intaddr2=get_index(0,0,inc,width_image_input_CNN,height_image_input_CNN,num_map_input_CNN); intaddr3=get_index(0,0,o,width_image_C1_CNN,height_image_C1_CNN,num_map_C1_CNN); constdouble*pw=&weight_C1[0]+addr1; constdouble*pi=data_single_image+addr2; double*pa=&neuron_C1[0]+addr3; for(inty=0;y for(intx=0;x constdouble*ppw=pw; constdouble*ppi=pi+y*width_image_input_CNN+x; doublesum=0.0; for(intwy=0;wy for(intwx=0;wx sum+=*ppw++*ppi[wy*width_image_input_CNN+wx]; } } pa[y*width_image_C1_CNN+x]+=sum; } } } intaddr3=get_index(0,0,o,width_image_C1_CNN,height_image_C1_CNN,num_map_C1_CNN); double*pa=&neuron_C1[0]+addr3; doubleb=bias_C1[o]; for(inty=0;y for(intx=0;x pa[y*width_image_C1_CNN+x]+=b; } } } for(inti=0;i neuron_C1[i]=activation_function_tanh(neuron_C1[i]); } returntrue; } (3)、S2层: 神经元数为(14*14)*6=1176,对C1中6个28*28的特征图生成6个14*14的下采样图,相邻四个神经元分别乘以同一个权值再进行相加求和,再求均值即除以4,然后再加上一个阈值,最后再通过tanh激活函数对每一神经元进行运算得到最终每一个神经元的结果。 代码段如下: [cpp]viewplaincopy在CODE上查看代码片派生到我的代码片 boolCNN: : Forward_S2() { init_variable(neuron_S2,0.0,num_neuron_S2_CNN); doublescale_factor=1.0/(width_kernel_pooling_CNN*height_kernel_pooling_CNN); assert(out2wi_S2.size()==num_neuron_S2_CNN); assert(out2bias_S2.size()==num_neuron_S2_CNN); for(inti=0;i constwi_connections&connections=out2wi_S2[
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 卷积 神经网络 CNN 代码 实现 MNIST 解析 摘要