• 实验内容和原理

卷积神经网络(Convolutional Neural Network,CNN)是一类包含卷积计算且具有深度结构的前馈神经网络。

CNN层 cnn层是由几个cnn模块组成_CNN层

CNN整体架构:卷积神经网络是一种多层的监督学习神经网络,隐含层的卷积层和池采样层是实现卷积神经网络特征提取功能的核心模块。该网络模型通过采用梯度下降法最小化损失函数对网络中的权重参数逐层反向调节,通过频繁的迭代训练提高网络的精度。卷积神经网络的低隐层是由卷积层和最大池采样层交替组成,高层是全连接层对应传统多层感知器的隐含层和逻辑回归分类器。第一个全连接层的输入是由卷积层和子采样层进行特征提取得到的特征图像。最后一层输出层是一个分类器,可以采用逻辑回归。

卷积神经网络CNN主要用来识别位移、缩放及其他形式扭曲不变性的二维图形。由于CNN的特征检测层通过训练数据进行学习,所以在使用CNN时,避免了显式的特征抽取,而隐式地从训练数据中进行学习;再者由于同一特征映射面上的神经元权值相同,所以网络可以并行学习,这也是卷积网络相对于神经元彼此相连网络的一大优势。卷积神经网络以其局部权值共享的特殊结构在语音识别和图像处理方面有着独特的优越性,其布局更接近于实际的生物神经网络,权值共享降低了网络的复杂性,特别是多维输入向量的图像可以直接输入网络这一特点避免了特征提取和分类过程中数据重建的复杂度。

  • 操作方法与实验步骤
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
import os
import warnings
warnings.filterwarnings("ignore")
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
def weight_variable(shape):
    # 产生随机变量
    # truncated_normal:选取位于正态分布均值=0.1附近的随机值
    initial = tf.truncated_normal(shape, stddev=0.1)
    return tf.Variable(initial)
def bias_variable(shape):
    initial = tf.constant(0.1, shape=shape)
    return tf.Variable(initial)
def conv2d(x, W):
    # stride = [1,水平移动步长,竖直移动步长,1]
    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
def max_pool_2x2(x):
    # stride = [1,水平移动步长,竖直移动步长,1]
    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
# 读取MNIST数据集
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
sess = tf.InteractiveSession()
# 预定义输入值X、输出真实值Y    placeholder为占位符
x = tf.placeholder(tf.float32, shape=[None, 784])
y_ = tf.placeholder(tf.float32, shape=[None, 10])
keep_prob = tf.placeholder(tf.float32)
x_image = tf.reshape(x, [-1, 28, 28, 1])
# print(x_image.shape)  #[n_samples,28,28,1]
# 卷积层1网络结构定义
# 卷积核1:patch=5×5;in size 1;out size 32;激活函数reLU非线性处理
W_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)  # output size 28*28*32
h_pool1 = max_pool_2x2(h_conv1)  # output size 14*14*32#卷积层2网络结构定义
# 卷积核2:patch=5×5;in size 32;out size 64;激活函数reLU非线性处理
W_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)  # output size 14*14*64
h_pool2 = max_pool_2x2(h_conv2)  # output size 7 *7 *64
# 全连接层1
W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])
h_pool2_flat = tf.reshape(h_pool2, [-1, 7 * 7 * 64])  # [n_samples,7,7,64]->>[n_samples,7*7*64]
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)  # 减少计算量dropout
# 全连接层2
W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])
prediction = tf.matmul(h_fc1_drop, W_fc2) + b_fc2
# prediction = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)
# 二次代价函数:预测值与真实值的误差
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=prediction))
# 梯度下降法:数据太庞大,选用AdamOptimizer优化器
train_step = tf.train.AdamOptimizer(1e-4).minimize(loss)
# 结果存放在一个布尔型列表中
correct_prediction = tf.equal(tf.argmax(prediction, 1), tf.argmax(y_, 1))
# 求准确率

import numpy as np  
import matplotlib.pyplot as plt
x_list=[]
y_list=[]
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
saver = tf.train.Saver()  # defaults to saving all variables
sess.run(tf.global_variables_initializer())
for i in range(1000):
    batch = mnist.train.next_batch(50)
    if i % 10 == 0:
        train_accuracy = accuracy.eval(feed_dict={x: batch[0], y_: batch[1], keep_prob: 1.0})
        print("step", i, "training accuracy", train_accuracy)
        x_list.append(i)
        y_list.append(train_accuracy)
    train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})
# 保存模型参数
saver.save(sess, './model2.ckpt')
print("2 level test accuracy %g" % sess.run(accuracy, feed_dict={
      x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))
plt.figure(figsize=(8,4)) #创建绘图对象  
plt.plot(x_list,y_list,"b-",linewidth=2)
print(x_list,y_list)
plt.xlabel("Step") #X轴标签  
plt.ylabel("training accuracy")  #Y轴标签  
plt.title("Trends in accuracy") #图标题  
plt.show()  #显示图  
plt.savefig("2_level.png") #保存图

 

 

 

 

  • 实验结果与分析

 

CNN层 cnn层是由几个cnn模块组成_神经网络_02

CNN层 cnn层是由几个cnn模块组成_卷积神经网络_03

 

观察上面的对比可看到:两层神经网络最终准确度结果比三层神经网络效果非常相似,三层神经网络迭代初期准确度较快达到0.9以上。由于迭代观察间隔大,上图看不出效果,故实验缩小到间隔为10。

CNN层 cnn层是由几个cnn模块组成_CNN层_04

 

从这张图来看,三层的神经网络收敛较快,收敛到0.9之后基本上维持在0.9以上,而两层的神经网络收敛稍慢,并且有少量数据仍下降到0.69及以下。综上,三层的神经网络效果比两层的神经网络效果稍微好一点,但是区别不大。

 

 

  • 问题与建议

对于神经网络各种参数的选择还是比较模糊不清楚的,理论上是要通过大量的实验对比来得出最优结果。由于能力有限,暂且不作深入研究。