CNN 卷积神经网络

卷积神经网络简介

卷积神经网络主要层次

  • 数据输入层:Input layer
  • 卷积计算层:CONV layer
  • ReLU激活层:ReLU layer
  • 池化层:Pooling layer
  • 全连接层:FC layer

激活层建议:

  • CNN尽量不要使用Sigmoid,如果要使用,建议只在全连接层使用
  • 首先使用ReLU,因为迭代速度快,但有可能效果不佳
  • 如果使用ReLU失效,考虑使用Leaky ReLU或者Maxout,一般都能解决的
  • tanh激活函数在某些情况下有比较好的效果,但是应用场景比较少

池化层: 在池化层中,进行压缩减小特征数量时常用两种策略:

  • Max Pooling:最大池化,一般采用这种方式
  • Average Pooling:平均池化

全连接层: 两层之间所有神经元都有权重连接;通常情况下,在CNN中,FC层只有在尾部出现

CNN结构: 一般为:

  • Input
  • [[CONV ——> ReLU] N ——>Pooling?] M
  • [FC——>ReLU] * K
  • FC

数据预处理

与神经网络/机器学习一样,需要对输入的数据进行预处理操作,主要原因是:

  • 输入数据单位不一样,可能会导致神经网络收敛速度慢,训练时间长
  • 数据范围大的输入在模式分类中的作用可能偏大,而数据范围小的作用可能就偏小
  • 由于神经网络中存在的激活函数是由值域限制的,因此需要将网络训练的目标数据映射到激活函数的值域
  • Sigmoid型激活函数在(0,1)区间以外区域很平缓,区分度太小

常见的3种数据预处理方式:

  • 去均值
    • 将输入数据的各个维度中心化到0
  • 归一化
    • 将输入数据的各个维度的幅度归一化到同样的范围
  • PCA/白化
    • PCA降维
    • 白化是对数据的每个特征轴上的幅度归一化

白化使得学习算法的输入具有如下性质:

  • 特征之间相关性较低
  • 所有特征具有相同的方差

卷积神经网络优缺点

优点

  • 共享卷积核(共享参数),对高维数据的处理没有压力
  • 无需选择特征属性,只要训练好权重,即可得到特征值
  • 深层次的网络抽取图像信息比较丰富,表达效果好

缺点

  • 需要调参,需要大量样本,训练迭代次数比较多,最好使用GPU训练
  • 物理含义不明确,从每层输出中很难看出含义

卷积神经网络正则化和Dropout

神经网络的学习能力受神经元数目以及神经网络层次的影响,神经元数目越大,神经网络层次越高,那么神经网络的学习能力越强,那么就有可能出现过拟合的问题。正则化通过给cost函数添加正则项的方式来解决overfitting,Dropout是通过直接修改神经网络的结构来解决overfitting。

Regulation

正则化的目的是降低模型复杂度,通过在cost函数上添加一个正则项的方式来降低overfitting,主要有L1和L2两种方式

  • L1:若希望知道哪个特征对最后结果产生了比较大的影响则使用之
  • L2:不在意对特征的分析

Dropout

通过随即删除神经网络中的神经元来解决overfitting的问题,在每次迭代的时候,只使用部分神经元训练模型获取W和d的值,其目的是:

  • 不要CNN具有太多的泛化能力(不能依赖某几个神经元)
  • 多次迭代结果的合并可以增加模型的准确,多个不同模型的合并可以提高其准确率

一般情况下,对于同一组训练数据,利用不同的神经网络训练后,求其输出的平均值可以减少overfitting,Dropout就是利用这个原理,每次丢掉一半左右的隐藏神经元,相当于在不同的神经网络上训练,这样就减少了神经元之间的依赖性,即每个神经元不能依赖于某几个其他的神经元(指层与层之间相连接的神经元),使神经网络更加能学习到与其他神经元之间的更加robost的特征,另外Dropout不仅减少overfitting,还能提高准确率

实现卷积神经网络

参数表:

  • W1:是Layer1到Layer2的权重
  • b1:是Layer1到Layer2转换的截距
  • W2:是Layer2到Layer3的权重
  • b2:是Layer2到Layer3转换的截距
  • W3:是Layer3到Layer4的权重
  • b3:是Layer3到Layer4转换的截距
  • Dropout的概率为 p=0.5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import numpy as np
p = 0.5

def train_step(X):
H1 = np.maximum(0, np.dot(W1, X) + b1)
U1 = (np.random.rand(*H1.shape) < p) / p
H1 *= U1
H2 = np.maximum(0, np.dot(W2, H1) + b2)
U1 = (np.random.rand(*H2.shape) < p) / p
H2 *= U2
out = np.dot(W3, H2) + b3
# BP操作,计算梯度(省略)
# 参数更新(省略)

def predict(X):
H1 = np.maximum(0, np.dot(W1, X) + b1)
H2 = np.maximum(0, np.dot(W2, H1) + b2)
out = np.dot(W3, H2) + b3

卷积神经网络典型CNN

  • LeNet:最早用于数字识别的CNN,主要用于字符识别
  • AlexNet:2012年ILSVRC比赛冠军,远超第二名的CNN,比LeNet更深,用多层小卷积叠加来替换单个的大卷积
  • ZF Net:2013 ILSVRC冠军
    • 基于AlexNet进行微调
    • Top5错误率11.2%
    • 使用ReLU激活函数和交叉熵损失函数
  • GoogleNet:2014 ILSVRC冠军(层次很深)

  • VGGNet:2014ILSVRC比赛中算法模型,效果略低于GoogleNet
  • ResNet:2015ILSVRC冠军,结构修正以适应更深层次的CNN训练(残差连接)
    • 允许模型存在一些shortcuts,可以让研究者成功地训练更深的神经网络,这样也能明显地优化Inception块

卷积神经网络案例

任务:CNN卷积神经网络手写数字

1
2
3
4
5
import warnings
import numpy as np
warnings.filterwarnings('ignore')
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
1
2
3
4
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
batch_size = 100
X_holder = tf.placeholder(tf.float32)
y_holder = tf.placeholder(tf.float32)
Extracting MNIST_data\train-images-idx3-ubyte.gz
Extracting MNIST_data\train-labels-idx1-ubyte.gz
Extracting MNIST_data\t10k-images-idx3-ubyte.gz
Extracting MNIST_data\t10k-labels-idx1-ubyte.gz
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
X_images = tf.reshape(X_holder, [-1, 28, 28, 1])
#convolutional layer 1
conv1_Weights = tf.Variable(tf.truncated_normal([5, 5, 1, 32], stddev=0.1))
conv1_biases = tf.Variable(tf.constant(0.1, shape=[32]))
conv1_conv2d = tf.nn.conv2d(X_images, conv1_Weights, strides=[1, 1, 1, 1], padding='SAME') + conv1_biases
conv1_activated = tf.nn.relu(conv1_conv2d)
conv1_pooled = tf.nn.max_pool(conv1_activated, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
#convolutional layer 2
conv2_Weights = tf.Variable(tf.truncated_normal([5, 5, 32, 64], stddev=0.1))
conv2_biases = tf.Variable(tf.constant(0.1, shape=[64]))
conv2_conv2d = tf.nn.conv2d(conv1_pooled, conv2_Weights, strides=[1, 1, 1, 1], padding='SAME') + conv2_biases
conv2_activated = tf.nn.relu(conv2_conv2d)
conv2_pooled = tf.nn.max_pool(conv2_activated, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
#full connected layer 1
connect1_flat = tf.reshape(conv2_pooled, [-1, 7 * 7 * 64])
connect1_Weights = tf.Variable(tf.truncated_normal([7 * 7 * 64, 1024], stddev=0.1))
connect1_biases = tf.Variable(tf.constant(0.1, shape=[1024]))
connect1_Wx_plus_b = tf.add(tf.matmul(connect1_flat, connect1_Weights), connect1_biases)
connect1_activated = tf.nn.relu(connect1_Wx_plus_b)
#full connected layer 2
connect2_Weights = tf.Variable(tf.truncated_normal([1024, 10], stddev=0.1))
connect2_biases = tf.Variable(tf.constant(0.1, shape=[10]))
connect2_Wx_plus_b = tf.add(tf.matmul(connect1_activated, connect2_Weights), connect2_biases)
predict_y = tf.nn.softmax(connect2_Wx_plus_b)
1
2
3
4
5
6
7
8
#loss and train
loss = tf.reduce_mean(-tf.reduce_sum(y_holder * tf.log(predict_y), 1))
optimizer = tf.train.AdamOptimizer(0.0001)
train = optimizer.minimize(loss)

init = tf.global_variables_initializer()
session = tf.Session()
session.run(init)
1
2
3
4
5
6
7
8
9
10
for i in range(1001):
train_images, train_labels = mnist.train.next_batch(200)
session.run(train, feed_dict={X_holder:train_images, y_holder:train_labels})
if i % 100 == 0:
correct_prediction = tf.equal(tf.argmax(predict_y, 1), tf.argmax(y_holder, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
test_images, test_labels = mnist.test.next_batch(2000)
train_accuracy = session.run(accuracy, feed_dict={X_holder:train_images, y_holder:train_labels})
test_accuracy = session.run(accuracy, feed_dict={X_holder:test_images, y_holder:test_labels})
print('step:%d train accuracy:%.4f test accuracy:%.4f' %(i, train_accuracy, test_accuracy))
step:0 train accuracy:0.0700 test accuracy:0.0685
step:100 train accuracy:0.8650 test accuracy:0.8935
step:200 train accuracy:0.9200 test accuracy:0.9255
step:300 train accuracy:0.9500 test accuracy:0.9460
step:400 train accuracy:0.9600 test accuracy:0.9595
step:500 train accuracy:0.9850 test accuracy:0.9715
step:600 train accuracy:0.9650 test accuracy:0.9680
step:700 train accuracy:0.9700 test accuracy:0.9690
step:800 train accuracy:0.9600 test accuracy:0.9760
step:900 train accuracy:0.9800 test accuracy:0.9765
step:1000 train accuracy:0.9850 test accuracy:0.9760
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!

扫一扫,分享到微信

微信分享二维码
  • Copyrights © 2020 chenk
  • 由 帅气的CK本尊 强力驱动
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信