通信建设工程项目经理查询网站,网站不支持php,网页升级访问中新每天正常更新中,公司名字大全四个字上周我们用PaddlePaddle和Tensorflow实现了图像分类#xff0c;分别用自己手写的一个简单的CNN网络simple_cnn和LeNet-5的CNN网络识别cifar-10数据集。在上周的实验表现中#xff0c;经过200次迭代后的LeNet-5的准确率为60%左右#xff0c;这个结果差强人意#xff0c;毕竟… 上周我们用PaddlePaddle和Tensorflow实现了图像分类分别用自己手写的一个简单的CNN网络simple_cnn和LeNet-5的CNN网络识别cifar-10数据集。在上周的实验表现中经过200次迭代后的LeNet-5的准确率为60%左右这个结果差强人意毕竟是二十年前写的网络结构结果简单层数也很少这一节中我们讲讲在2012年的Image比赛中大放异彩的AlexNet并用AlexNet对cifar-10数据进行分类对比上周的LeNet-5的效果。 什么是AlexNet AlexNet在ILSVRC-2012的比赛中获得top5错误率15.3%的突破第二名为26.2%其原理来源于2012年Alex的论文《ImageNet Classification with Deep Convolutional Neural Networks》这篇论文是深度学习火爆发展的一个里程碑和分水岭加上硬件技术的发展深度学习还会继续火下去。 AlexNet网络结构 由于受限于当时的硬件设备AlexNet在GPU粒度都做了设计当时的GTX 580只有3G显存为了能让模型在大量数据上跑起来作者使用了两个GPU并行并对网络结构做了切分如下 网络结构 Input输入层 输入为224×224×3的三通道RGB图像为方便后续计算实际操作中通过padding做预处理把图像变成227×227×3。 C1卷积层 该层由卷积操作 Max Pooling LRN后面详细介绍它组成。 卷积层由96个feature map组成每个feature map由11×11卷积核在stride4下生成输出feature map为55×55×48×2其中55(227-11)/4148为分在每个GPU上的feature map数2为GPU个数 激活函数采用ReLU Max Pooling采用stride2且核大小为3×3文中实验表明采用2×2的非重叠模式的Max Pooling相对更容易过拟合在top 1和top 5下的错误率分别高0.4%和0.3%输出feature map为27×27×48×2其中27(55-3)/2148为分在每个GPU上的feature map数2为GPU个数 LRN邻居数设置为5做归一化。 最终输出数据为归一化后的27×27×48×2。 C2卷积层 该层由卷积操作 Max Pooling LRN组成 卷积层由256个feature map组成每个feature map由5×5卷积核在stride1下生成为使输入和卷积输出大小一致需要做参数为2的padding输出feature map为27×27×128×2其中27(27-52×2)/11128为分在每个GPU上的feature map数2为GPU个数 激活函数采用ReLU Max Pooling采用stride2且核大小为3×3输出feature map为13×13×128×2其中13(27-3)/21128为分在每个GPU上的feature map数2为GPU个数 LRN邻居数设置为5做归一化。 最终输出数据为归一化后的13×13×128×2。 C3卷积层 该层由卷积操作 LRN组成注意没有Pooling层 输入为13×13×256因为这一层两个GPU会做通信途中虚线交叉部分 卷积层之后由384个feature map组成每个feature map由3×3卷积核在stride1下生成为使输入和卷积输出大小一致需要做参数为1的padding输出feature map为13×13×192×2其中13(13-32×1)/11192为分在每个GPU上的feature map数2为GPU个数 激活函数采用ReLU 最终输出数据为归一化后的13×13×192×2。 C4卷积层 该层由卷积操作 LRN组成注意没有Pooling层 卷积层由384个feature map组成每个feature map由3×3卷积核在stride1下生成为使输入和卷积输出大小一致需要做参数为1的padding输出feature map为13×13×192×2其中13(13-32×1)/11192为分在每个GPU上的feature map数2为GPU个数 激活函数采用ReLU 最终输出数据为归一化后的13×13×192×2。 C5卷积层 该层由卷积操作 Max Pooling组成 卷积层由256个feature map组成每个feature map由3×3卷积核在stride1下生成为使输入和卷积输出大小一致需要做参数为1的padding输出feature map为13×13×128×2其中13(13-32×1)/11128为分在每个GPU上的feature map数2为GPU个数 激活函数采用ReLU Max Pooling采用stride2且核大小为3×3输出feature map为6×6×128×2其中6(13-3)/21128为分在每个GPU上的feature map数2为GPU个数. 最终输出数据为归一化后的6×6×128×2。 F6全连接层 该层为全连接层 Dropout 使用4096个节点 激活函数采用ReLU 采用参数为0.5的Dropout操作 最终输出数据为4096个神经元节点。 F7全连接层 该层为全连接层 Dropout 使用4096个节点 激活函数采用ReLU 采用参数为0.5的Dropout操作 最终输出为4096个神经元节点。 输出层 该层为全连接层 Softmax 使用1000个输出的Softmax 最终输出为1000个分类。 AlexNet的优势 1.使用了ReLu激活函数 ----原始Relu----- AlexNet引入了ReLU激活函数这个函数是神经科学家Dayan、Abott在《Theoretical Neuroscience》一书中提出的更精确的激活模型。原始的Relu激活函数可参见 Hinton论文《Rectified Linear Units Improve Restricted Boltzmann Machines》我们比较熟悉即$max(0,x)$这个激活函数把负激活全部清零模拟上面提到的稀疏性这种做法在实践中即保留了神经网络的非线性能力又加快了训练速度。 但是这个函数也有缺点 在原点不可微 反向传播的梯度计算中会带来麻烦所以Charles Dugas等人又提出Softplus来模拟上述ReLu函数可视作其平滑版 $$f(x)log(1e^x)$$ 实际上它的导数就是一个 \begin{equation}f(x)\frac{1}{1e^{-x}}\end{equation} 过稀疏性 当学习率设置不合理时即使是一个很大的梯度在经过ReLu单元并更新参数后该神经元可能永不被激活。 ----Leaky ReLu---- 为了解决上述过稀疏性导致的大量神经元不被激活的问题Leaky ReLu被提了出来 \begin{equation}f(x)\left\{\begin{aligned}ax(x0) \\x(x0)\end{aligned}\right.\end{equation} 其中$\alpha$是人工制定的较小值如0.1它一定程度保留了负激活信息。 还有很多其他的对于ReLu函数的改进如Parametric ReLuRandomized ReLu等此处就不再展开讲了。 2.Local Response Normalization 局部响应均值 LRN利用相邻feature map做特征显著化文中实验表明可以降低错误率公式如下 $$b^i_{x,y}\frac{a^i_{x,y}}{(k\alpha \cdot \sum^{min(N-1,in/2)}_{jmax(0,i-n/2)}(a^i_{x,y})^2)^\beta}$$ 公式的直观解释如下 由于 $\alpha$都是经过了RELU的输出所以一定是大于0的函数$\frac{1}{(k\alpha \sum x^2)^\beta}$取文中参数的图像如下横坐标为$\sum x^2$: 当$\sum x^2$值较小时即当前节点和其邻居节点输出值差距不明显且大家的输出值都不太大可以认为此时特征间竞争激烈该函数可以使原本差距不大的输出产生显著性差异且此时函数输出不饱和当$\sum x^2$ 值较大时说明特征本身有显著性差别但输出值太大容易过拟合该函数可以令最终输出接近0从而缓解过拟合提高了模型泛化性。 3.Dropout Dropout是文章亮点之一属于提高模型泛化性的方法操作比较简单以一定概率随机让某些神经元输出设置为0既不参与前向传播也不参与反向传播也可以从正则化角度去看待它。(关于深度学习的正则化年初的时候在公司做过一个分享下次直接把pdf放出来) 从模型集成的角度来看 无Dropout网络 $$Y^nW^nX^{n-1}$$$$X^nF(Y^n)$$ 有Dropout网络 $$Y^nW^nX^{n-1}$$$$d^{n-1}\sim Bernoulli(p)$$$$X^n d^{n-1} \odot F(Y^n)$$ 其中$p$为Dropout的概率如p0.5即让50%的神经元随机失活$n$为所在的层。 它是极端情况下的Bagging由于在每步训练中神经元会以某种概率随机被置为无效相当于是参数共享的新网络结构每个模型为了使损失降低会尽可能学最“本质”的特征“本质”可以理解为由更加独立的、和其他神经元相关性弱的、泛化能力强的神经元提取出来的特征而如果采用类似SGD的方式训练每步迭代都会选取不同的数据集这样整个网络相当于是用不同数据集学习的多个模型的集成组合。 用PaddlePaddle实现AlexNet 1.网络结构(alexnet.py) 这次我写了两个alextnet一个加上了局部均值归一化LRN一个没有加LRN对比效果如何 1 #coding:utf-82 3 Created by huxiaoman 2017.12.54 alexnet.py:alexnet网络结构5 6 7 import paddle.v2 as paddle8 import os9
10 with_gpu os.getenv(WITH_GPU, 0) ! 1
11
12 def alexnet_lrn(img):
13 conv1 paddle.layer.img_conv(
14 inputimg,
15 filter_size11,
16 num_channels3,
17 num_filters96,
18 stride4,
19 padding1)
20 cmrnorm1 paddle.layer.img_cmrnorm(
21 inputconv1, size5, scale0.0001, power0.75)
22 pool1 paddle.layer.img_pool(inputcmrnorm1, pool_size3, stride2)
23
24 conv2 paddle.layer.img_conv(
25 inputpool1,
26 filter_size5,
27 num_filters256,
28 stride1,
29 padding2,
30 groups1)
31 cmrnorm2 paddle.layer.img_cmrnorm(
32 inputconv2, size5, scale0.0001, power0.75)
33 pool2 paddle.layer.img_pool(inputcmrnorm2, pool_size3, stride2)
34
35 pool3 paddle.networks.img_conv_group(
36 inputpool2,
37 pool_size3,
38 pool_stride2,
39 conv_num_filter[384, 384, 256],
40 conv_filter_size3,
41 pool_typepaddle.pooling.Max())
42
43 fc1 paddle.layer.fc(
44 inputpool3,
45 size4096,
46 actpaddle.activation.Relu(),
47 layer_attrpaddle.attr.Extra(drop_rate0.5))
48 fc2 paddle.layer.fc(
49 inputfc1,
50 size4096,
51 actpaddle.activation.Relu(),
52 layer_attrpaddle.attr.Extra(drop_rate0.5))
53 return fc2
54
55 def alexnet(img):
56 conv1 paddle.layer.img_conv(
57 inputimg,
58 filter_size11,
59 num_channels3,
60 num_filters96,
61 stride4,
62 padding1)
63 cmrnorm1 paddle.layer.img_cmrnorm(
64 inputconv1, size5, scale0.0001, power0.75)
65 pool1 paddle.layer.img_pool(inputcmrnorm1, pool_size3, stride2)
66
67 conv2 paddle.layer.img_conv(
68 inputpool1,
69 filter_size5,
70 num_filters256,
71 stride1,
72 padding2,
73 groups1)
74 cmrnorm2 paddle.layer.img_cmrnorm(
75 inputconv2, size5, scale0.0001, power0.75)
76 pool2 paddle.layer.img_pool(inputcmrnorm2, pool_size3, stride2)
77
78 pool3 paddle.networks.img_conv_group(
79 inputpool2,
80 pool_size3,
81 pool_stride2,
82 conv_num_filter[384, 384, 256],
83 conv_filter_size3,
84 pool_typepaddle.pooling.Max())
85
86 fc1 paddle.layer.fc(
87 inputpool3,
88 size4096,
89 actpaddle.activation.Relu(),
90 layer_attrpaddle.attr.Extra(drop_rate0.5))
91 fc2 paddle.layer.fc(
92 inputfc1,
93 size4096,
94 actpaddle.activation.Relu(),
95 layer_attrpaddle.attr.Extra(drop_rate0.5))
96 return fc3 2.训练代码train_alexnet.py 1 #coding:utf-82 3 Created by huxiaoman 2017.12.54 train_alexnet.py:训练alexnet对cifar10数据集进行分类5 6 7 import sys, os8 import paddle.v2 as paddle9 10 #alex模型为不带LRN的11 from alexnet import alexnet12 #alexnet_lrn为带有lrn的13 #from alextnet import alexnet_lrn14 with_gpu os.getenv(WITH_GPU, 0) ! 115 16 17 def main():18 datadim 3 * 32 * 3219 classdim 1020 21 # PaddlePaddle init22 paddle.init(use_gpuwith_gpu, trainer_count7)23 24 image paddle.layer.data(25 nameimage, typepaddle.data_type.dense_vector(datadim))26 27 # Add neural network config28 # option 1. resnet29 # net resnet_cifar10(image, depth32)30 # option 2. vgg31 #net alexnet_lrn(image)32 net alexnet(image)33 out paddle.layer.fc(34 inputnet, sizeclassdim, actpaddle.activation.Softmax())35 36 lbl paddle.layer.data(37 namelabel, typepaddle.data_type.integer_value(classdim))38 cost paddle.layer.classification_cost(inputout, labellbl)39 40 # Create parameters41 parameters paddle.parameters.create(cost)42 43 # Create optimizer44 momentum_optimizer paddle.optimizer.Momentum(45 momentum0.9,46 regularizationpaddle.optimizer.L2Regularization(rate0.0002 * 128),47 learning_rate0.1 / 128.0,48 learning_rate_decay_a0.1,49 learning_rate_decay_b50000 * 100,50 learning_rate_schedulediscexp)51 52 # End batch and end pass event handler53 def event_handler(event):54 if isinstance(event, paddle.event.EndIteration):55 if event.batch_id % 100 0:56 print \nPass %d, Batch %d, Cost %f, %s % (57 event.pass_id, event.batch_id, event.cost, event.metrics)58 else:59 sys.stdout.write(.)60 sys.stdout.flush()61 if isinstance(event, paddle.event.EndPass):62 # save parameters63 with open(params_pass_%d.tar % event.pass_id, w) as f:64 parameters.to_tar(f)65 66 result trainer.test(67 readerpaddle.batch(68 paddle.dataset.cifar.test10(), batch_size128),69 feeding{image: 0,70 label: 1})71 print \nTest with Pass %d, %s % (event.pass_id, result.metrics)72 73 # Create trainer74 trainer paddle.trainer.SGD(75 costcost, parametersparameters, update_equationmomentum_optimizer)76 77 # Save the inference topology to protobuf.78 inference_topology paddle.topology.Topology(layersout)79 with open(inference_topology.pkl, wb) as f:80 inference_topology.serialize_for_inference(f)81 82 trainer.train(83 readerpaddle.batch(84 paddle.reader.shuffle(85 paddle.dataset.cifar.train10(), buf_size50000),86 batch_size128),87 num_passes200,88 event_handlerevent_handler,89 feeding{image: 0,90 label: 1})91 92 # inference93 from PIL import Image94 import numpy as np95 import os96 97 def load_image(file):98 im Image.open(file)99 im im.resize((32, 32), Image.ANTIALIAS)
100 im np.array(im).astype(np.float32)
101 im im.transpose((2, 0, 1)) # CHW
102 im im[(2, 1, 0), :, :] # BGR
103 im im.flatten()
104 im im / 255.0
105 return im
106
107 test_data []
108 cur_dir os.path.dirname(os.path.realpath(__file__))
109 test_data.append((load_image(cur_dir /image/dog.png), ))
110
111 probs paddle.infer(
112 output_layerout, parametersparameters, inputtest_data)
113 lab np.argsort(-probs) # probs and lab are the results of one batch data
114 print Label of image/dog.png is: %d % lab[0][0]
115
116
117 if __name__ __main__:
118 main() 用Tensorflow实现AlexNet 1.网络结构 1 def inference(images):2 3 Alexnet模型4 输入images的tensor5 返回Alexnet的最后一层卷积层6 7 parameters []8 # conv19 with tf.name_scope(conv1) as scope:10 kernel tf.Variable(tf.truncated_normal([11, 11, 3, 64], dtypetf.float32,11 stddev1e-1), nameweights)12 conv tf.nn.conv2d(images, kernel, [1, 4, 4, 1], paddingSAME)13 biases tf.Variable(tf.constant(0.0, shape[64], dtypetf.float32),14 trainableTrue, namebiases)15 bias tf.nn.bias_add(conv, biases)16 conv1 tf.nn.relu(bias, namescope)17 print_activations(conv1)18 parameters [kernel, biases]19 20 # lrn121 with tf.name_scope(lrn1) as scope:22 lrn1 tf.nn.local_response_normalization(conv1,23 alpha1e-4,24 beta0.75,25 depth_radius2,26 bias2.0)27 28 # pool129 pool1 tf.nn.max_pool(lrn1,30 ksize[1, 3, 3, 1],31 strides[1, 2, 2, 1],32 paddingVALID,33 namepool1)34 print_activations(pool1)35 36 # conv237 with tf.name_scope(conv2) as scope:38 kernel tf.Variable(tf.truncated_normal([5, 5, 64, 192], dtypetf.float32,39 stddev1e-1), nameweights)40 conv tf.nn.conv2d(pool1, kernel, [1, 1, 1, 1], paddingSAME)41 biases tf.Variable(tf.constant(0.0, shape[192], dtypetf.float32),42 trainableTrue, namebiases)43 bias tf.nn.bias_add(conv, biases)44 conv2 tf.nn.relu(bias, namescope)45 parameters [kernel, biases]46 print_activations(conv2)47 48 # lrn249 with tf.name_scope(lrn2) as scope:50 lrn2 tf.nn.local_response_normalization(conv2,51 alpha1e-4,52 beta0.75,53 depth_radius2,54 bias2.0)55 56 # pool257 pool2 tf.nn.max_pool(lrn2,58 ksize[1, 3, 3, 1],59 strides[1, 2, 2, 1],60 paddingVALID,61 namepool2)62 print_activations(pool2)63 64 # conv365 with tf.name_scope(conv3) as scope:66 kernel tf.Variable(tf.truncated_normal([3, 3, 192, 384],67 dtypetf.float32,68 stddev1e-1), nameweights)69 conv tf.nn.conv2d(pool2, kernel, [1, 1, 1, 1], paddingSAME)70 biases tf.Variable(tf.constant(0.0, shape[384], dtypetf.float32),71 trainableTrue, namebiases)72 bias tf.nn.bias_add(conv, biases)73 conv3 tf.nn.relu(bias, namescope)74 parameters [kernel, biases]75 print_activations(conv3)76 77 # conv478 with tf.name_scope(conv4) as scope:79 kernel tf.Variable(tf.truncated_normal([3, 3, 384, 256],80 dtypetf.float32,81 stddev1e-1), nameweights)82 conv tf.nn.conv2d(conv3, kernel, [1, 1, 1, 1], paddingSAME)83 biases tf.Variable(tf.constant(0.0, shape[256], dtypetf.float32),84 trainableTrue, namebiases)85 bias tf.nn.bias_add(conv, biases)86 conv4 tf.nn.relu(bias, namescope)87 parameters [kernel, biases]88 print_activations(conv4)89 90 # conv591 with tf.name_scope(conv5) as scope:92 kernel tf.Variable(tf.truncated_normal([3, 3, 256, 256],93 dtypetf.float32,94 stddev1e-1), nameweights)95 conv tf.nn.conv2d(conv4, kernel, [1, 1, 1, 1], paddingSAME)96 biases tf.Variable(tf.constant(0.0, shape[256], dtypetf.float32),97 trainableTrue, namebiases)98 bias tf.nn.bias_add(conv, biases)99 conv5 tf.nn.relu(bias, namescope)
100 parameters [kernel, biases]
101 print_activations(conv5)
102
103 # pool5
104 pool5 tf.nn.max_pool(conv5,
105 ksize[1, 3, 3, 1],
106 strides[1, 2, 2, 1],
107 paddingVALID,
108 namepool5)
109 print_activations(pool5)
110
111 return pool5, parameters 完整代码可见alexnet_tf.py 实验结果对比 三个代码跑完后对比了一下实验结果如图所示 可以看到在batch_sizenum_epochsdevices和thread数都相同的条件下加了LRN的paddlepaddle版的alexnet网络结果效果最好而时间最短的是不加LRN的alexnet在时间和精度上都比较平均的是tensorflow版的alexnet当然tf版的同样加了LRN所以LRN对于实验效果还是有一定提升的。 总结 AlexNet在图像分类中是一个比较重要的网络在学习的过程中不仅要学会写网络结构知道每一层的结构更重要的是得知道为什么要这样设计这样设计有什么好处如果对某些参数进行一些调整结果会有什么变化为什么会产生这样的变化。在实际应用中如果需要对网络结构做一些调整应该如何调整使得网络更适合我们的实际数据这些才是我们关心的。也是面试中常常会考察的点。昨天面试了一位工作五年的算法工程师问道他在项目中用的模型是alexnet对于alexnet的网络结构并不是非常清楚如果要改网络结构也不知道如何改这样其实不好仅仅把模型跑通只是第一步后续还有很多工作要做这也是作为算法工程师的价值体现之一。本文对于alexnet的网络结构参考我之前的领导写的文章如过有什么不懂的可以留言。 ps:为了方便大家及时看到我的更新我搞了一个公众号以后文章会同步发布与公众号和博客园这样大家就能及时收到通知啦有不懂的问题也可以在公众号留言这样我能够及时看到并回复。公众号刚开始做做的比较粗糙里面还没有东西 后期会慢慢完善~~ 可以通过扫下面的二维码或者直接搜公众号CharlotteDataMining 就可以了谢谢关注^_^ 参考文献 1.AlexNet: http://www.cs.toronto.edu/~fritz/absps/imagenet.pdf 我的博客即将同步至腾讯云社区邀请大家一同入驻。