길쌈 신경망과 신경 네트워크는 일반적인 매우 유사하다 : 그들은이 학습 무게와 바이어스 뉴런으로 구성합니다. 각 뉴런 내적을 수행하는, 어떤 입력을 수신하고, 선택적으로 비선형 그것을 따른다.
전체 네트워크는 여전히 하나의 차등 점수를 나타낼 수있다 :
다른 클래스의 점수를 원래 이미지에서 픽셀의 한쪽 끝.
그리고 (완전히 연결) 마지막에 그들은 여전히 기능의 손실이 레이어, 우리는 여전히 적용 정상적인 신경 네트워크 개발 /의 모든 트릭을 배우고있다.
CNN의 각 층 미분 함수 다른으로 활성 값 일반적 CNN을 갖는 컨볼 루션 층 , 전지 층 과 완전히 연결 층은 FC (종래 신경망에서 볼 때)를 풀 일반적인 층의 활성화 기능이되기 전에, 우리는 전체 구조를 형성하는 층을 적층한다. 우리는 아마지도를 보면 :
신경 네트워크의 개발에 회선 모양 :
오류 속도 업그레이드 :
컨볼 루션 네트워킹은 여러 가지가 있습니다 아키텍처, 이름의 종류. 가장 흔한은 다음과 같습니다 :
-
LeNet. 1990 년대에 개발 된 얀 레컨에 의해 회선 네트워크의 첫 번째 성공적인 응용 프로그램입니다. 가장 유명한 중 하나는 등등 우편 번호, 숫자를 읽기위한 LeNet 아키텍처입니다.
-
AlexNet. 회선 첫 작품을 촉진 할 수있는 네트워크 컴퓨터 비전 알렉스 케리 Wieruszewski, 일리아 Sacijifu 제프 힌튼에 의해 개발, AlexNet입니다. AlexNet는 2012 년 ImageNet ILSVRC 도전에 제출, 두 번째보다 훨씬 더 나은 (입상자에 비해 전 다섯 오차는 16 %, 26 % 오차이었다). 네트워크 LeNet 매우 유사한 구조를 가지고 있지만, 더 깊은, 더 많은 기능 회선 서로 (레이어 풀과 보통 하나의 이전 CONV 꽉 층) 위에 쌓인.
-
ZFNet。ILSVRC 2013获奖者是Matthew Zeiler和Rob Fergus的卷积网络。它被称为ZFNet(Zeiler&Fergus Net的缩写)。通过调整架构超参数,特别是通过扩展中间卷积层的大小,使第一层的步幅和过滤器尺寸更小,这是对AlexNet的改进。
-
GoogleNet。ILSVRC 2014获奖者是Szegedy等人的卷积网络。来自Google。其主要贡献是开发一个初始模块,大大减少了网络中的参数数量(4M,与AlexNet的60M相比)。此外,本文使用ConvNet顶部的“平均池”而不是“完全连接”层,从而消除了大量似乎并不重要的参数。GoogLeNet还有几个后续版本,最近的是Inception-v4。
-
VGGNet。2011年ILSVRC的亚军是来自Karen Simonyan和Andrew Zisserman的网络,被称为VGGNet。它的主要贡献在于表明网络的深度是良好性能的关键组成部分。他们最终的最佳网络包含16个CONV / FC层,并且吸引人的是,具有非常均匀的架构,从始至终只能执行3x3卷积和2x2池。他们预先训练的模型可用于Caffe的即插即用。VGGNet的缺点是评估和使用更多的内存和参数(140M)是更昂贵的。这些参数中的大多数都在第一个完全连接的层中,因此发现这些FC层可以在没有性能降级的情况下被去除,
-
ResNet。Kaiming He等人开发的残留网络 是ILSVRC 2015的获胜者。它具有特殊的跳过连接和批量归一化的大量使用。该架构在网络末端也缺少完全连接的层。读者也参考了凯明的演讲(视频,幻灯片),以及一些最近在火炬中复制这些网络的实验。ResNets目前是迄今为止最先进的卷积神经网络模型,并且是实际使用ConvNets的默认选择(截至2016年5月10日)。特别是,也看到最近从Kaiming He等人调整原有架构的发展。
然后介绍一下卷积神经网络的组件:
卷积层:
通过在原始图像上平移来提取特征,每一个特征就是一个特征映射:
就比如黄色的图片就是过滤器,我们利用它去卷积,过程如下:
外围补充与多Filter(P)
我们前面还曾提到,每个卷积层可以有多个filter。每个filter和原始图像进行卷积后,都可以得到一个Feature Map。因此,卷积后Feature Map的深度(个数)和卷积层的filter个数是相同的。
如果我们的步长移动与filter的大小不适合,导致不能正好移动到边缘怎么办?
这里就出现了零填充的大小P
下图就是卷积层的计算方法。这里面体现了局部连接和权值共享:每层神经元只和上一层部分神经元相连(卷积计算规则),且filter的权值对于上一层所有神经元都是一样的。
卷积层过滤器:
-
个数 数量K :比如上图就是1个 大小 大小F: 比如上图就是filter:3*3 步长 步长S:比如上图就是1 零填充大小P
•卷积层输出深度、输出宽度
总结输出大小
-
输入体积大小H1∗W1∗D1
-
四个超参数:
-
Filter数量K
-
Filter大小F
-
步长S
-
零填充大小P
-
-
输出体积大小H2∗W2∗D2
-
H_2 = (H_1 - F + 2P)/S + 1
-
W_2 = (W_1 - F + 2P)/S + 1
-
D_2 = K
-
激活函数:
一般在进行卷积之后就会提供给激活函数得到一个输出值。我们不使用sigmoid,softmax,而使用Relu。该激活函数的定义是:
f(x)= max(0,x)
Relu函数如下:
特点
-
速度快 和sigmoid函数需要计算指数和倒数相比,relu函数其实就是一个max(0,x),计算代价小很多
-
稀疏性 通过对大脑的研究发现,大脑在工作的时候只有大约5%的神经元是激活的,而采用sigmoid激活函数的人工神经网络,其激活率大约是50%。有论文声称人工神经网络在15%-30%的激活率时是比较理想的。因为relu函数在输入小于0时是完全不激活的,因此可以获得一个更低的激活率。
池化层:
通过特征后稀疏参数来减少学习的参数,降低网络的复杂度,(最大池化和平均池化)
Pooling层主要的作用是下采样,通过去掉Feature Map中不重要的样本,进一步减少参数数量。Pooling的方法很多,最常用的是Max Pooling。Max Pooling实际上就是在nn的样本中取最大值,作为采样后的样本值。
除了Max Pooing之外,常用的还有Mean Pooling——取各样本的平均值。对于深度为D的Feature Map,各层独立做Pooling,因此Pooling后的深度仍然为D。
全连接层:
那么在卷积网络当中,为什么需要加上FC层呢?
前面的卷积和池化相当于做特征工程,后面的全连接相当于做特征加权。最后的全连接层在整个卷积神经网络中起到“分类器”的作用
过拟合解决办法
Dropout(失活)
为了减少过拟合,我们在输出层之前加入dropout。我们用一个placeholder来代表一个神经元的输出在dropout中保持不变的概率。这样我们可以在训练过程中启用dropout,在测试过程中关闭dropout。 TensorFlow的tf.nn.dropout操作除了可以屏蔽神经元的输出外,还会自动处理神经元输出值的scale。所以用dropout的时候可以不用考虑scale。一般在全连接层之后进行Dropout
卷积神经网络的构建
一层卷积
卷积:32个filter,5*5,strides 1,padding="SAME"
输入:[None,28,28,1] 输出[None,28,28,32]
激活:[None,28,28,32]
池化:2*2,strides=2,padding="SAME"
输入:[None,28,28,32] 输出:[None,14,14,32]
偏置项:bias = 32
二层卷积
卷积:64个filter,5*5,strides=1,padding="SAME"
输入:[None,14,14,32] 输出[None,14,14,64]
激活:[None,14,14,64]
池化:2*2,strides=2,padding="SAME"
输入:[None,14,14,64] 输出:[None,7,7,64]
偏置项:bias = 64
全连接层FC:
输入:[None,7,7,64]-->[None,7*7*64]
权重:[None,7*7*64,10]
输出:[None,10]
偏置项:bias=10
import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data def weight_init(shape): w = tf.Variable(tf.random_normal(shape=shape,mean=0.0,stddev=1.0)) return w def bias_init(shape): b = tf.Variable(tf.constant(0.0,shape=shape)) return b def cnn(): # 1,初始化数据 mnist = input_data.read_data_sets("data/mnist/input_data/",one_hot=True) with tf.variable_scope("data"): x = tf.placeholder(tf.float32,[None,784]) y_true = tf.placeholder(tf.float32,[None,10]) # 2,第一层卷积 [None,784]-->[None,28,28,1] 5*5*1*32 strides=1-->[None,14,14,32] with tf.variable_scope("conv1"): x_reshape = tf.reshape(x,[-1,28,28,1]) w1 = weight_init([5,5,1,32]) b1 = bias_init([32]) # 卷积,激活,池化 x_relu1 = tf.nn.relu(tf.nn.conv2d(x_reshape,filter=w1,strides=[1,1,1,1],padding="SAME")+b1) x_poo11 =tf.nn.max_pool(x_relu1,ksize=[1,2,2,1],strides=[1,2,2,1],padding="SAME") # 3,第二层卷积 [None,14,14,32]--> 5*5*32*64 strides=1-->[None,7,7,64] with tf.variable_scope("conv2"): w2 = weight_init([5,5,32,64]) b2 = bias_init([64]) # 卷积,激活,池化 x_relu2 = tf.nn.relu(tf.nn.conv2d(x_poo11,filter=w2,strides=[1,1,1,1],padding="SAME")+b2) x_poo12 =tf.nn.max_pool(x_relu2,ksize=[1,2,2,1],strides=[1,2,2,1],padding="SAME") # 4,全连接层 [None,7,7,64]->[-1,7*7*64] w [7*7*64,10] b [10] with tf.variable_scope("full_connect"): w = weight_init([7*7*64,10]) b = bias_init([10]) x_fc_reshape = tf.reshape(x_poo12,shape=[-1,7*7*64]) y_predict = tf.matmul(x_fc_reshape,w)+b # 5,损失函数,梯度下降,模型评估 # 建立损失函数 with tf.variable_scope("soft_cross"): loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_true, logits=y_predict)) # 梯度下降 with tf.variable_scope("optimizer"): train_op = tf.train.GradientDescentOptimizer(0.001).minimize(loss) # 模型评估 with tf.variable_scope("acc"): eq = tf.equal(tf.argmax(y_true, 1), tf.argmax(y_predict, 1)) accuracy = tf.reduce_mean(tf.cast(eq, tf.float32)) with tf.Session() as sess: tf.global_variables_initializer().run() for i in range(1000): x_mnist, y_mnist = mnist.train.next_batch(50) sess.run([train_op], feed_dict={x: x_mnist, y_true: y_mnist}) print("训练第%d步,准确率为:%f" % (i, sess.run(accuracy, feed_dict={x: x_mnist, y_true: y_mnist}))) return None if __name__ == '__main__': cnn()