计算机视觉基础——TensorFlow实经典LeNet网络

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_27825451/article/details/83302861

1537250305768859.png

一、LeNet网络简介

1.1 LeNet网络的背景

闪光点:定义了CNN的基本组件,是CNN的鼻祖。

LeNet是卷积神经网络的祖师爷LeCun在1998年提出,用于解决手写数字识别的视觉任务。自那时起,CNN的最基本的架构就定下来了:卷积层、池化层、全连接层。如今各大深度学习框架中所使用的LeNet都是简化改进过的LeNet-5(-5表示具有5个层),和原始的LeNet有些许不同,比如把激活函数改为了现在很常用的ReLu。

但是具体没一个网络层的参数设置会稍有不同。比如卷积层卷积核的大小,输出特征图的数量这些都可以自定义的。

1.2 LeNet的网络结构

LeNet一共包含5个网络层,如果算上池化层,就是8个网络层。

输入层:输入层的图像大小为28x28x1

卷积层1:卷积核大小为3x3x1x32,相当于是32个3x3x1的卷积核,移动步幅长为1,故而得到的输出为32个特征图,也可以说成一幅图像有32个通道,28x28x32.

池化层1:采用最大化池化层,为2x2,移动步幅为2,故而输出为:14x14x32

卷积层2:卷积核大小为3x3x32x64,相当于是64个3x3x32的卷积核,移动步幅长为1,故而得到的输出为64个特征图,也可以说成一幅图像有64个通道,14x14x64.

池化层2:采用最大化池化层,为2x2,移动步幅为2,故而输出为:7x7x64

卷积层3:卷积核大小为3x3x64x128,相当于是128个3x3x64的卷积核,移动步幅长为1,故而得到的输出为128个特征图,也可以说成一幅图像有128个通道,7x7x128.

池化层3:采用最大化池化层,为2x2,移动步幅为2,故而输出为:4x4x128

全连接层:输入为128x4x4,需要将其展开成一维的,输出为625.

输出层:输入为625,输出为10.

1.3 LeNet的结构图

二、tensorflow实现LeNet

2.1 实现代码及注释

  1import numpy as np
  2import tensorflow as tf
  3from tensorflow.examples.tutorials.mnist import input_data #导入数据的模块
  4
  5batch_size=100  #表示每一批训练100组数据,因为训练集共有数据55000组,故而训练一个周期需要经过550次迭代
  6test_size=256   #作为验证数据,验证集有10000组数据,但这里只验证256组,因为数据太多,运算太慢
  7img_size=28     #手写字图像的大小
  8num_class=10    #图像的类别
  9
 10X=tf.placeholder(dtype=tf.float32,shape=[None,img_size,img_size,1],name='input')
 11Y=tf.placeholder(dtype=tf.float32,shape=[None,num_class])
 12
 13p_keep=tf.placeholder(tf.float32,name='p_keep_rate') #后面用到dropout层的保留的参数
 14
 15mnist=input_data.read_data_sets('mnist_data',one_hot=True) #导入数据集
 16train_X,train_Y,test_X,test_Y=mnist.train.images,mnist.train.labels,mnist.test.images,mnist.test.labels
 17
 18train_X=train_X.reshape(-1,img_size,img_size,1)   #训练数据和测试数据都需要重塑一下形状,因为导入的是724长度的
 19test_X=test_X.reshape(-1,img_size,img_size,1)
 20
 21#第一个卷积层
 22with tf.name_scope('cnn_layer_01') as cnn_01:     
 23    w1=tf.Variable(tf.random_normal(shape=[3,3,1,32],stddev=0.01))
 24    conv1=tf.nn.conv2d(X,w1,strides=[1,1,1,1],padding="SAME")
 25    conv_y1=tf.nn.relu(conv1)
 26
 27#第一个池化层
 28with tf.name_scope('pool_layer_01') as pool_01:
 29    pool_y2=tf.nn.max_pool(conv_y1,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
 30    pool_y2=tf.nn.dropout(pool_y2,p_keep)
 31
 32#第二个卷积层
 33with tf.name_scope('cnn_layer_02') as cnn_02:
 34    w2=tf.Variable(tf.random_normal(shape=[3,3,32,64],stddev=0.01))
 35    conv2=tf.nn.conv2d(pool_y2,w2,strides=[1,1,1,1],padding="SAME")
 36    conv_y3=tf.nn.relu(conv2)
 37
 38#第二个池化层
 39with tf.name_scope('pool_layer_02') as pool_02:
 40    pool_y4=tf.nn.max_pool(conv_y3,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
 41    pool_y4=tf.nn.dropout(pool_y4,p_keep)
 42
 43#第三个卷积层
 44with tf.name_scope('cnn_layer_03') as cnn_03:
 45    w3=tf.Variable(tf.random_normal(shape=[3,3,64,128],stddev=0.01))
 46    conv3=tf.nn.conv2d(pool_y4,w3,strides=[1,1,1,1],padding="SAME")
 47    conv_y5=tf.nn.relu(conv3)
 48
 49#第三个池化层
 50with tf.name_scope('pool_layer_03') as pool_03:
 51    pool_y6=tf.nn.max_pool(conv_y5,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
 52
 53#全连接层 
 54with tf.name_scope('full_layer_01') as full_01:
 55    w4=tf.Variable(tf.random_normal(shape=[128*4*4,625],stddev=0.01))
 56    FC_layer=tf.reshape(pool_y6,[-1,w4.get_shape().as_list()[0]])
 57    FC_layer=tf.nn.dropout(FC_layer,p_keep)
 58    FC_y7=tf.matmul(FC_layer,w4)
 59    FC_y7=tf.nn.relu(FC_y7)
 60    FC_y7=tf.nn.dropout(FC_y7,p_keep)
 61
 62#输出层,model_Y则为神经网络的预测输出
 63with tf.name_scope('output_layer') as output_layer:
 64    w5=tf.Variable(tf.random_normal(shape=[625,num_class]))
 65    model_Y=tf.matmul(FC_y7,w5,name='output')
 66
 67#损失函数
 68Y_=tf.nn.softmax_cross_entropy_with_logits(logits=model_Y,labels=Y)
 69cost=tf.reduce_mean(Y_)
 70
 71#准确率
 72correct_prediction=tf.equal(tf.argmax(model_Y,axis=1),tf.argmax(Y,axis=1))
 73accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
 74
 75#优化方式
 76optimizer=tf.train.RMSPropOptimizer(0.001,0.9).minimize(cost)
 77
 78#将相关的参数写入tensorboard
 79#-----------------------------------------------------------------------
 80tf.summary.scalar('loss',cost)
 81tf.summary.scalar('accuracy',accuracy)
 82tf.summary.histogram('w1',w1)
 83tf.summary.histogram('w2',w2)
 84tf.summary.histogram('w3',w3)
 85tf.summary.histogram('w4',w4)
 86tf.summary.histogram('w5',w5)
 87merge=tf.summary.merge_all()
 88#--------------------------------------------------------------------------
 89#构建会话任务
 90with tf.Session() as sess:
 91    tf.global_variables_initializer().run()
 92    writer=tf.summary.FileWriter('mnist_cnn_summary_01',graph=sess.graph)
 93    #将索引重组一下,得到【(0,100),(100,200),(200,300)。。。。】的形式
 94    training_batch=zip(range(0,len(train_X),batch_size),range(batch_size,len(train_X)+1,batch_size))
 95
 96    run_metadata=tf.RunMetadata()
 97    #开始训练,此处只训练一个epoch,若想训练多个epoch,可以再添加一个循环
 98    for start,end in training_batch:
 99        opti,summary,loss,acc=sess.run([optimizer,merge,cost,accuracy],\
100        feed_dict={X:train_X[start:end],Y:train_Y[start:end],p_keep:0.8},\
101        run_metadata=run_metadata) #这是最关键的一步,optimizer,summary,loss,accuracy均放在一起进行训练
102
103        writer.add_run_metadata(run_metadata,tag='step{0}'.format(start),global_step=(start/batch_size)+1)
104        writer.add_summary(summary,global_step=(start/batch_size)+1)
105
106        print(f'第 {(start/batch_size)+1} 次迭代时,准确度为 {acc},误差为 {loss}',end='\r',flush=True)
107
108    print('===================下面开始进行测试==============================')
109    #下面开始对测试集上的数据进行验证
110    test_index=np.arange(len(test_X))
111    np.random.shuffle(test_index)      #将测试集上的10000组数据顺序随即大乱
112    test_index=test_index[0:test_size] #只选择打乱顺序之后的256组样本数据进行测试
113    test_acc=sess.run(accuracy,feed_dict={X:test_X[test_index],Y:test_Y[test_index],p_keep:1})
114    print(f'测试集上面的准确率为 :{test_acc}')
115    print('===================下面是保存模型================================')
116     #保存模型
117    saver=tf.train.Saver()
118    path=saver.save(sess,'mnist_cnn_model/medel.ckpt')
119    print(f'模型欧保存到 {path}')
120    print('训练完毕!')

TensorFlow实现LeNet

2.2 程序运行结果分析

2.2.1 结果打印

1===================下面开始进行测试==============================857185366
2测试集上面的准确率为 :0.9765625
3===================下面是保存模型================================
4模型欧保存到 mnist_cnn_model/medel.ckpt
5训练完毕!

从上面可以看出,在256组测试数据及上面的准确率为0.9765625.只进行了一个epoch的训练能达到这样的效果已经很不错了。

2.2.1 误差曲线及准确率

2.2.2 模型graph

graph1.png

三、模型的加载以及预测

3.1 预测结果

一个魔性训练完成之后,需要将模型保存,这样就可以避免每次使用模型的时候都重新训练,本文只讲实现,具体关于模型如何保存,如何加载以及相关保存文件的具体含义后面会继续讲到。

 1import random
 2import matplotlib.pyplot as plt
 3import tensorflow as tf
 4from tensorflow.examples.tutorials.mnist import input_data #导入数据的模块
 5
 6mnist=input_data.read_data_sets('mnist_data',one_hot=True)
 7train_X,train_Y,test_X,test_Y=mnist.train.images,mnist.train.labels,mnist.test.images,mnist.test.labels
 8
 9
10test_image=mnist.test.images[101]  #选取第101张图片
11img_size=28
12test_image=test_image.reshape(-1,img_size,img_size,1)
13
14with tf.Session() as sess:   #    
15    new_saver=tf.train.import_meta_graph('mnist_cnn_model/medel.ckpt.meta') #第二步:导入模型的图结构
16    new_saver.restore(sess,'mnist_cnn_model/medel.ckpt')  #第三步:将这个会话绑定到导入的图中
17    #new_saver.restore(sess,tf.train.latest_checkpoint('mymodel'))    #第三步也可以是这样操作,因为会从mymodel文件夹中获取checkpoint,而checkpoint中存储了最新存档的文件路径
18
19    print('=======================模型加载完成=============================')
20    X=sess.graph.get_tensor_by_name('input:0')                 #从模型中获取输入的那个节点
21    p_keep=sess.graph.get_tensor_by_name('p_keep_rate:0')
22    model_y=sess.graph.get_tensor_by_name('output_layer/output:0')
23    print('=======================输入输出加载完成=============================')
24    result=sess.run(model_y,feed_dict={X:test_image,p_keep:1})  #需要的就是模型预测值model_Y,这里存为result
25    print('++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++')
26    print(result)
27    print('++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++')
28    soft_result=tf.nn.softmax(result)
29    result1=sess.run(soft_result)
30    print(result1)
31    
34    plt.imshow(test_image.reshape([28,28]),cmap='Greys')
35    plt.show()

模型的加载预测

3.2 预测结果分析

本次只选择了一张测试图片,选择的是第101张照片,程序的运行显示为如下:

原始测试图片如下:

Figure_1.png

运行结果为:

1=======================模型加载完成=============================
2=======================输入输出加载完成=============================
3++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4[[15.647467  -6.0671535 -0.9249869 -5.6294613 -3.727207   0.5262224
5   2.540439  -1.8248326 -1.2350063  3.0618703]]
6++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7[[9.9999416e-01 3.7107148e-10 6.3485118e-08 5.7483751e-10 3.8519756e-09
8  2.7097201e-07 2.0308953e-06 2.5815121e-08 4.6562104e-08 3.4209170e-06]]

从上面的运行结果可以看出,第一个数字为0.99999416,后面的其他数子基本上非常接近于0,说明该数字是0的概率为99.9999%。

全文总结

本文基于TensorFlow实现了经典的LeNet网络,准确率较高,如果您看过之后觉得有什么问题和需要改进的地方,欢迎您留言。另外,后面我会陆续实现相关的经典网络,包括VGGNet,GoogleNet,ResNet,DenseNet等,如果想在深度学习方面一起学习的可以持续关注一下。

草样年华.jpg

个人微信号.jpg

猜你喜欢

转载自blog.csdn.net/qq_27825451/article/details/83302861