CNN卷积神经网络

CNN卷积神经网络

1.层级结构

  传统神经网络相比于线性分类器具有强大的功能,线性分类器对不规则的分类情况不能很好的进行分类,而神经网络通过拟合多条线性结构,使用了and和or来实现最终分类。神经网络对训练物体空间表征方面没有要求。使用神经网络获取每个神经元的权重是重要。神经网络层之间是全连接结构。

  卷积神经网络保留了传统神经网络的层级结构,包括数据输入层、卷积层、激励层、池化层、全连接层。

  数据输入层:去均值(去训练集的均值)、归一化、PCA或者白化。CNN只做去均值。

  卷积层:是卷积神经网络的核心,概念包括步长、filter大小、padding size、deep size、权重共享机制。卷积即图片数据与filter的内积,通过filter可以将图片中的某些特征提取出来。

  激励层:激励用来以合适的方式向神经网络后面传递参数。激励函数有:sigmoid函数、ReLU、leaky ReLU、maxout。Sigmoid具有偏导为0的风险,当为0时,BP无意义。一般首先考虑ReLU,函数形式为:f(x)=max(0,x)。

  池化层:用来减小数据量,防止过拟合,下采样。一般常用max pooling。理论依据是图像在小范围下,像素突变小。 

  优点:共享权重参数,减少计算量。无需选择特征,只需训练卷积核,就可以抽取特征。

  缺点:使用GPU进行计算,需要样本量大。运行物理含义不明确。

  常用卷积神经网络model:LeNet,AlexNet,GooleNet,VGGNet

  常用框架:caffe,torch,tensorflow

神经网络训练

1.Min-batch SGD(随机梯度下降)

  采样一个batch的样本,向前计算cost,反向传播计算这个batch上的梯度,最后用这个梯度更新权重。SGD能够小概率的遇到局部最低点,达到较好的效果。

2.去均值

  两种去均值方式:第一种方式是对N个image的32*32*3的每个像素求均值,第二种方式是对image的RGB3个32*32求均值。

3.权重初始化

  权重初始化首先考虑都为0,但是造成了神经网络的对称性,使得最后的梯度一样,不能够学习特征性。之后考虑初始化为随机的比较小的值,对于浅层次的神经网络还可以,但是对于深层次的神经网络会发生激励函数后的输出也会变为0,这对神经网络的学习是没有意义的。2010年paper中出现选择randn(in,out)/np.sqrt(in)作为w的初始值,这有一定的数学推理。但是当出现Relu时,该值也不合适。2015年时有paper出现了调整,选择randn(in,out)/np.sqrt(in/2)作为w的初始值,又具有很大效果。

  由于CNN的脆弱性,Google设计出batch normalization的想法,让期望激励后,符合高斯分布。为了让CNN通过训练自己调整权重w参数,可以在CNN训练过程中添加BN层。由于经过FC层后,可能会有较大的波动,一般用于在FC层和激励层之间。BN层训练如下:

  输入:FC层的输出x,由网络学习的学习出的参数lambda和beta。BN层的优点:减少了对初始值的依赖,由神经网络动态调整。

  在训练中,可以先用小的训练集对其进行训练,看是否能达到1的准确率。并且在训练中要对loss函数进行监控,正常情况下是一个稳步震荡下降的曲线。当训练集和测试集的loss值都达到了很高的水平并且相差不大,则说明运行正常。

5.dropout

  在dropout层上关闭一些神经元,使其只学习部分特征,使用概率p来控制那些神经元被关闭,由于只会学习部分特征,所以抑制了过拟合。

6.其他

  了解了caffe和tensorflow,caffe的使用方式源于Google的json,通过使用prototxt文件定义层级和层级关系。Tensorflow是Google开发,社区比较活跃,其中tensorboard的可视化是非常直观的,对了解训练过程有很大帮助。

7.CNN的实现

安装环境:pycharm、tensorflow、sklearn、numpy

代码:附件1CNN.py

实验结果:对于sklearn的手写数字集,最后训练准确度达到93%。搭建了一个简单的CNN,其中使用了很多tensorflow的函数,比较方便,但还有必要了解tensorflow的源代码设计。

 1 # encoding: utf-8
 2 '''
 3 @author: depchen
 4 
 5 @file: CNN.py.py
 6 
 7 @time: 2018/3/21 21:23
 8 
 9 @desc:
10 '''
11 import tensorflow as tf
12 import numpy as np
13 from sklearn.datasets import load_digits
14 from sklearn.preprocessing import MinMaxScaler
15 from sklearn.preprocessing import OneHotEncoder
16 
17 #加载数据
18 digits=load_digits() #sklearn的手写数字集
19 X_data=digits.data.astype(np.float32)#取出数字集的图片数据,类型为float32
20 Y_data=digits.target.astype(np.float32).reshape(-1,1)#取出数字集的图片结果,类型为float32,转换为一列
21 print(X_data.shape)
22 print(Y_data.shape)
23 #对数据进行处理
24 #对x数据进行标准化,对y进行one-hot编码
25 scaler=MinMaxScaler()#是将x固定一个小的特定区间,按比例缩放
26 X_data=scaler.fit_transform(X_data)
27 #print(X_data)
28 Y=OneHotEncoder().fit_transform(Y_data).todense()#one_hot编码
29 #print(Y)
30 #将原始数据重塑为8*8*1的图片数据矩阵,-1是指根据实际计算有多少batch
31 X=X_data.reshape(-1,8,8,1)
32 batch_size=8 #batch的大小,每个batch的图片张数
33 #使用MBGD算法,随机选出8个
34 #//是一个取整数操作,去小于等于的正整数
35 def generatebatch(X,Y,n_example,batch_size):
36     for batch_i in range(n_example//batch_size):
37         start=batch_i*batch_size
38         end=start+batch_size
39         batch_xs=X[start:end]
40         batch_ys=Y[start:end]
41         yield batch_xs,batch_ys
42 #清除默认图的堆栈
43 tf.reset_default_graph()
44 #CNN层级实现
45 #输入层
46 x_tf=tf.placeholder(tf.float32,[None,8,8,1])#用placeholder创建tensor
47 y_tf=tf.placeholder(tf.float32,[None,10])
48 #卷积层+激励层
49 conv_w1=tf.Variable(tf.random_normal([3,3,1,10]))#从正态集中选出10个3*3*1的卷积
50 conv_b1=tf.Variable(tf.random_normal([10]))#从正态集中选出10个偏执
51 #先使用2维卷积函数,再使用relu激励函数,
52 relu_feature_map=tf.nn.relu(tf.nn.conv2d(x_tf,conv_w1,strides=[1,1,1,1],padding="SAME")+conv_b1)
53 #池化层,使用maxpooling
54 max_pool1=tf.nn.max_pool(relu_feature_map,ksize=[1,3,3,1],strides=[1,2,2,1],padding="SAME")
55 print(max_pool1)   #池化后4*4*10
56 #卷积层2,同卷积层1
57 conv_w2=tf.Variable(tf.random_normal([3,3,10,5]))
58 conv_b2=tf.Variable(tf.random_normal([5]))
59 relu_feature_map2=tf.nn.conv2d(max_pool1,conv_w2,[1,2,2,1],padding="SAME")+conv_b2
60 print(relu_feature_map2)
61 #BN层+激励层
62 batch_mean,batch_var=tf.nn.moments(relu_feature_map2,[0,1,2],keep_dims=True)#使用moments计算均值和方差
63 shift=tf.Variable(tf.zeros([5]))
64 scale=tf.Variable(tf.ones([5]))
65 epsilon=1e-3
66 bn_out=tf.nn.batch_normalization(relu_feature_map2,batch_mean,batch_var,shift,scale,epsilon)
67 print(bn_out)
68 relu_feature_map3=tf.nn.relu(bn_out)
69 #池化层
70 max_pool2=tf.nn.max_pool(relu_feature_map3,[1,3,3,1],[1,2,2,1],"SAME")
71 print(max_pool2)
72 #将图片展开
73 plat=tf.reshape(max_pool2,[-1,1*1*5])
74 print(plat)
75 #全连接层
76 fc_w1=tf.Variable(tf.random_normal([1*1*5,50]))
77 fc_b1=tf.Variable(tf.random_normal([50]))
78 fc_out1=tf.nn.relu(tf.matmul(plat,fc_w1)+fc_b1)
79 #输出层
80 outw=tf.Variable(tf.random_normal([50,10]))
81 outb=tf.Variable(tf.random_normal([10]))
82 out=tf.nn.softmax(tf.matmul(fc_out1,outw)+outb)
83 print(out)
84 #训练
85 loss=-tf.reduce_mean(y_tf*tf.log(tf.clip_by_value(out,1e-11,1.0)))#损失函数
86 train_step=tf.train.AdamOptimizer(1e-3).minimize(loss)#最小化
87 y_out=tf.argmax(out,1)#选择概率最大的
88 bool=tf.equal(tf.argmax(y_tf,1),y_out)#预测与正确答案是否一致,用于计算准确率
89 print(bool)
90 accuracy=tf.reduce_mean(tf.cast(bool,tf.float32))#准确率
91 with tf.Session() as sess:
92     sess.run(tf.global_variables_initializer())#初始化所有variables
93     for epoch in range(100):#迭代100
94         for batch_x,batch_y in generatebatch(X,Y,Y.shape[0],batch_size):#每次产生一个8个图片数据进行训练
95             sess.run(train_step, feed_dict={x_tf: batch_x, y_tf: batch_y})
96         res = sess.run(accuracy, feed_dict={x_tf: X, y_tf: Y})
97         print(epoch, res) #打印每次迭代的准确率
98     res_ypred = y_out.eval(feed_dict={x_tf: X, y_tf: Y}).flatten()  # 只能预测一批样本,不能预测一个样本
99     print (res_ypred)

 

posted @ 2018-04-19 17:00  DevCh  阅读(396)  评论(0)    收藏  举报