【TensorFlow-CNN】MNIST


MINIST 手写数字识别数据集,由Yann LeCun所收集,CNN创始人
train:55000
trainval: 5000
test:10000

图片大小28*28,灰度图

本文用 Convolutional Neural Network(CNN)进行MNIST识别,CNN由Yann LeCun 提出,与MLP的区别在于,前面用卷积进行了特征提取,后面全连接层和Multilayer Perceptron(MLP)一样,MLP的demo可以查看这篇博客【TensorFlow-MLP】MNIST,本文的套路都是基于这篇博客的。精简版可以参考 《Tensorflow 搭建自己的神经网络 (莫烦 Python 教程)》learning notes


1 database

import tensorflow as tf
import tensorflow.examples.tutorials.mnist.input_data as input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

2 建立共享函数

2.1 weight

tf.truncated_normal 以随机化的方式初始化权重,然后用 tf.Variable 建立TensorFlow变量

def weight(shape):
    return tf.Variable(tf.truncated_normal(shape, stddev=0.1),
                       name ='W')

2.2 bias

def bias(shape):
    return tf.Variable(tf.constant(0.1, shape=shape)
                       , name = 'b')

2.3 conv2d

x必须是4维张量
strides = [1,stride,stride,1]
padding 为 same 会自动padding 0

def conv2d(x, W):
    return tf.nn.conv2d(x, W, strides=[1,1,1,1], 
                        padding='SAME')

2.4 max_pool_2x2

ksize = [1,height,width,1]

def max_pool_2x2(x):
    return tf.nn.max_pool(x, ksize=[1,2,2,1], 
                          strides=[1,2,2,1], 
                          padding='SAME')

2 Build Model

2.1 建立输入层

名字为Input_Layer

with tf.name_scope('Input_Layer'):
    x = tf.placeholder("float",shape=[None, 784]
                       ,name="x")    
    x_image = tf.reshape(x, [-1, 28, 28, 1])

tf.name_scope() 设置计算图的名字
shape=[None, 784]None 表示后续我们会传入很多图片,项数不固定,784是28*28 我们图片的大小

tf.reshape 第一维,-1是因为输入的图片个数不固定
二三维是图片的大小
第四维1因为是灰度图,如果是彩色要设置为3

2.2 建立卷积层1

名字为 C1_Conv

with tf.name_scope('C1_Conv'):
    W1 = weight([5,5,1,16])# filter大小5×5,输入channel为1,输出为16
    b1 = bias([16])
    Conv1=conv2d(x_image, W1)+ b1
    C1_Conv = tf.nn.relu(Conv1 )

2.3 建立池化层1

目的:

  • 减少所需处理的数据量
  • 让图像位置差异边变小
  • 参数的数量和计算量下降(缓解过拟合)

名字为 C1_Pool,通过第一个pooling层后,28×28的图片变为14×14

with tf.name_scope('C1_Pool'):
    C1_Pool = max_pool_2x2(C1_Conv)

2.4 建立卷积层2

名字为C2_Conv

with tf.name_scope('C2_Conv'):
    W2 = weight([5,5,16,36]) #filter size 5×5,输入channel 16,输出36
    b2 = bias([36])
    Conv2=conv2d(C1_Pool, W2)+ b2
    C2_Conv = tf.nn.relu(Conv2)

2.5 建立池化层2

名字 C2_Pool14×14的图片变为7×7

with tf.name_scope('C2_Pool'):
    C2_Pool = max_pool_2x2(C2_Conv) 

2.6 建立全连接层

名字D_Flat

with tf.name_scope('D_Flat'):
    D_Flat = tf.reshape(C2_Pool, [-1, 1764])

第一维是-1,因为后续会传入不限定项数的训练数据——数据图像,-1的功能是保持第一维不变
第二维 1764 = 7*7*36

2.7 建立隐藏层

名字 D_Hidden_Layer

with tf.name_scope('D_Hidden_Layer'):
    W3= weight([1764, 128])# 输入1764,输出128
    b3= bias([128])
    D_Hidden = tf.nn.relu(
                  tf.matmul(D_Flat, W3)+b3)
    D_Hidden_Dropout= tf.nn.dropout(D_Hidden, 
                                keep_prob=0.8)

D_Hidden 进行drop out 操作,keep_prob=0.8 表示保留80% 的神经元

2.8 建立输出层

名字为 Output_Layer

with tf.name_scope('Output_Layer'):
    W4 = weight([128,10])#输入128,输出10
    b4 = bias([10])
    y_predict= tf.nn.softmax(
                 tf.matmul(D_Hidden_Dropout,
                           W4)+b4)

2.9 定义训练方式

Keras 和 TensorFlow 定义训练方式不同
Keras:只需要使用model.compile 设置损失函数、优化器、并用 metrics 设置评估模型的方式
TensorFlow: 必须自行定义损失函数的公式、优化器和设置参数,并定义评估模型准确率的公式

with tf.name_scope("optimizer"):
    
    y_label = tf.placeholder("float", shape=[None, 10], 
                              name="y_label")
    
    loss_function = tf.reduce_mean(
                      tf.nn.softmax_cross_entropy_with_logits
                         (logits=y_predict , 
                          labels=y_label))
    
    optimizer = tf.train.AdamOptimizer(learning_rate=0.0001) \
                    .minimize(loss_function)

2.10 定义模型的准确率的方式

名字为 evaluate_model,one-hot编码,argmax输出最大值的位置,

with tf.name_scope("evaluate_model"):
	# 计算每一项数据是否正確预测
	# tf.equal,相等返回1,不等返回0
    correct_prediction = tf.equal(tf.argmax(y_predict, 1),
                                  tf.argmax(y_label, 1))

	# 将計算预测正确结果,加权平均
	# 先使用 tf.cast 转化为 float,再使用 tf.reduce_mean 将所有值平均
	accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

3 Training process

3.1 参数设置

trainEpochs = 30
batchSize = 100
totalBatchs = int(mnist.train.num_examples/batchSize)
print(totalBatchs)
epoch_list=[];accuracy_list=[];loss_list=[];
from time import time
startTime=time()
sess = tf.Session()
sess.run(tf.global_variables_initializer())

output

550

3.2 Train

# for each epoch
for epoch in range(trainEpochs):
    # for each mini-batch
    for i in range(totalBatchs):
        # 调用读mini-batch的函数
        batch_x, batch_y = mnist.train.next_batch(batchSize)
        # 训练优化器,更新w,最小化损失函数,输入x和y
        sess.run(optimizer,feed_dict={x: batch_x,y_label: batch_y})
    # 在验证集上计算精度和误差
    loss,acc = sess.run([loss_function,accuracy],
                        feed_dict={x: mnist.validation.images, 
                                   y_label: mnist.validation.labels})
    # 显示训练结果并存入列表
    epoch_list.append(epoch)
    loss_list.append(loss)
    accuracy_list.append(acc)    
    print("Train Epoch:", '%02d' % (epoch+1), "Loss=", \
                "{:.9f}".format(loss)," Accuracy=",acc)
                
# 计算训练的时间 
duration =time()-startTime
print("Train Finished takes:",duration)      

output

Train Epoch: 01 Loss= 1.653820515  Accuracy= 0.825
Train Epoch: 02 Loss= 1.542834163  Accuracy= 0.9316
Train Epoch: 03 Loss= 1.522341847  Accuracy= 0.9488
Train Epoch: 04 Loss= 1.508871317  Accuracy= 0.9578
Train Epoch: 05 Loss= 1.503607273  Accuracy= 0.9624
Train Epoch: 06 Loss= 1.497657776  Accuracy= 0.9692
Train Epoch: 07 Loss= 1.495323420  Accuracy= 0.9692
Train Epoch: 08 Loss= 1.490671635  Accuracy= 0.973
Train Epoch: 09 Loss= 1.491126657  Accuracy= 0.9722
Train Epoch: 10 Loss= 1.487095952  Accuracy= 0.9764
Train Epoch: 11 Loss= 1.485939264  Accuracy= 0.9776
Train Epoch: 12 Loss= 1.484445453  Accuracy= 0.9782
Train Epoch: 13 Loss= 1.482881784  Accuracy= 0.98
Train Epoch: 14 Loss= 1.481629491  Accuracy= 0.9812
Train Epoch: 15 Loss= 1.480455637  Accuracy= 0.9824
Train Epoch: 16 Loss= 1.480812192  Accuracy= 0.9814
Train Epoch: 17 Loss= 1.478735685  Accuracy= 0.984
Train Epoch: 18 Loss= 1.477754354  Accuracy= 0.9856
Train Epoch: 19 Loss= 1.480426788  Accuracy= 0.9822
Train Epoch: 20 Loss= 1.478232026  Accuracy= 0.9842
Train Epoch: 21 Loss= 1.478392363  Accuracy= 0.9848
Train Epoch: 22 Loss= 1.475563645  Accuracy= 0.987
Train Epoch: 23 Loss= 1.477076173  Accuracy= 0.9846
Train Epoch: 24 Loss= 1.477659345  Accuracy= 0.9854
Train Epoch: 25 Loss= 1.477388263  Accuracy= 0.984
Train Epoch: 26 Loss= 1.477272630  Accuracy= 0.9852
Train Epoch: 27 Loss= 1.474917412  Accuracy= 0.9876
Train Epoch: 28 Loss= 1.474585891  Accuracy= 0.9878
Train Epoch: 29 Loss= 1.475056171  Accuracy= 0.9872
Train Epoch: 30 Loss= 1.474527240  Accuracy= 0.987
Train Finished takes: 77.65863227844238

3.3 可视化精度和损失变化

先看看损失函数

%matplotlib inline
import matplotlib.pyplot as plt
fig = plt.gcf()
fig.set_size_inches(5,3)
plt.plot(epoch_list, loss_list, label = 'loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['loss'])

output
这里写图片描述

再看看精度变化

plt.plot(epoch_list, accuracy_list,label="accuracy" )
fig = plt.gcf()
fig.set_size_inches(5,3)
plt.ylim(0.8,1)
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend()
plt.show()

output
这里写图片描述

4 评估模型的准确性

查看测试集的大小

len(mnist.test.images)

output

10000

用训练的模型测试下性能

print("Accuracy:", 
      sess.run(accuracy,feed_dict={x: mnist.test.images,
                                   y_label: mnist.test.labels}))

output

Accuracy: 0.9855

5 预测概率和结果

5.1 预测的概率

y_predict=sess.run(y_predict, 
                   feed_dict={x: mnist.test.images})

看看前5项

y_predict[:5]

output

array([[3.02073045e-16, 2.95635516e-16, 2.74746163e-11, 1.37873916e-14,
        1.98319444e-20, 3.49799479e-22, 4.14647587e-33, 1.00000000e+00,
        7.10312555e-19, 7.26562098e-16],
       [1.31700683e-12, 1.75494536e-10, 1.00000000e+00, 4.09089775e-14,
        3.36607737e-24, 8.11432040e-25, 2.81481463e-16, 1.04421221e-22,
        1.00114605e-13, 5.16368183e-25],
       [7.71991552e-07, 9.99960899e-01, 8.24850375e-08, 6.61203448e-09,
        2.96174749e-05, 9.90071393e-12, 2.44029543e-08, 2.58124288e-07,
        8.30804674e-06, 7.27800459e-11],
       [9.99999642e-01, 1.25004302e-16, 2.09856771e-10, 1.53727348e-17,
        7.64048918e-16, 2.45482430e-16, 4.06873284e-07, 2.00636972e-11,
        5.20325861e-13, 3.99716745e-14],
       [2.58168181e-10, 1.29268818e-10, 1.05348274e-14, 5.35697674e-19,
        9.99999881e-01, 8.84295946e-13, 5.98036228e-14, 3.60072305e-09,
        4.24842461e-15, 1.09104448e-07]], dtype=float32)

5.2 预测的结果

prediction_result=sess.run(tf.argmax(y_predict,1),
                           feed_dict={x: mnist.test.images})

查看前10项

prediction_result[:10]

output

array([7, 2, 1, 0, 4, 1, 4, 9, 5, 9])

6 可视化预测结果

import numpy as np
def show_images_labels_predict(images,labels,prediction_result):
    fig = plt.gcf()
    fig.set_size_inches(8, 10)
    for i in range(0, 10):
        ax=plt.subplot(5,5, 1+i)
        ax.imshow(np.reshape(images[i],(28, 28)), 
                  cmap='binary')
        ax.set_title("label=" +str(np.argmax(labels[i]))+
                     ",predict="+str(prediction_result[i])
                     ,fontsize=9) 
    plt.show()

调用

plot_images_labels_prediction(mnist.test.images,
                              mnist.test.labels,
                              prediction_result,0)

output

7 找出预测出错的结果

for i in range(500):
    if prediction_result[i]!=np.argmax(mnist.test.labels[i]):
        print("i="+str(i)+
              "   label=",np.argmax(mnist.test.labels[i]),
              "predict=",prediction_result[i])

output

i=78   label= 9 predict= 8
i=247   label= 4 predict= 2
i=320   label= 9 predict= 1
i=340   label= 5 predict= 3
i=359   label= 9 predict= 4
i=445   label= 6 predict= 0
i=449   label= 3 predict= 5
i=492   label= 2 predict= 3
i=495   label= 8 predict= 0

可视化一下

def show_images_labels_predict_error(images,labels,prediction_result):
    fig = plt.gcf()
    fig.set_size_inches(8, 10)
    i=0;j=0
    while i<10:
        if prediction_result[j]!=np.argmax(labels[j]):
            ax=plt.subplot(5,5, 1+i)
            ax.imshow(np.reshape(images[j],(28, 28)), 
                      cmap='binary')
            ax.set_title("j="+str(j)+
                         ",l=" +str(np.argmax(labels[j]))+
                         ",p="+str(prediction_result[j])
                         ,fontsize=9) 
            i=i+1  
        j=j+1
    plt.show()

调用

show_images_labels_predict_error(mnist.test.images,mnist.test.labels,prediction_result)

output
这里写图片描述

8 TensorBoard

用下面的代码,把要显示的计算图写入log文件

merged = tf.summary.merge_all()
train_writer = tf.summary.FileWriter('log/CNN',sess.graph)

如何打开TensorBoard可以参考【TensorFlow】程序设计模式 第5节(在本地访问服务器的log)

output
这里写图片描述


声明

声明:代码源于《TensorFlow+Keras深度学习人工智能实践应用》 林大贵版,引用、转载请注明出处,谢谢,如果对书本感兴趣,买一本看看吧!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 手写数字识别是深度学习在计算机视觉领域的一项经典任务,可以使用PyQt5和TensorFlow Keras框架来实现。这种任务可以通过卷积神经网络(CNN)来完成。 首先,需要下载一个手写数字图像数据集,例如MNIST数据集。然后,可以使用TensorFlow Keras框架来搭建一个简单的CNN模型,来对图像进行分类。这个CNN模型可以包含一些卷积层、池化层、扁平层和全连接层来实现对手写数字图像的分类。 接下来,使用PyQt5编写一个简单的GUI界面,提供用户手动输入数字图像的功能。GUI界面可以提供一个画布来让用户手动在上面绘制数字,然后对这个数字图像进行预测和分类。 具体实现时,可以结合PyQt5的信号和槽机制,将用户手动绘制的数字图像与CNN模型进行关联。当用户完成数字图像的绘制后,程序可以自动进行图像分类,并输出数字的识别结果。 总之,PyQt5和TensorFlow Keras框架提供了一个完整的工具链,用于实现手写数字识别的任务。开发者可以使用这些工具和技术来实现更加复杂的图像识别和分析任务。 ### 回答2: 手写数字识别是深度学习中的一个常见问题,而PyQt5则是一个流行的Python图形界面开发框架,可以将模型的结果以可视化的方式展示给用户。因此,使用PyQt5和TensorFlow-Keras搭建一个手写数字识别的应用程序是很有实际应用价值的。下面简单介绍一下实现步骤。 首先,我们需要一个手写数字数据集,可以使用MNIST数据集。通过使用TensorFlow-Keras的API,我们可以快速地构建一个CNN模型,并在训练数据上进行训练。 接下来,我们需要使用PyQt5构建GUI界面,这里可以使用QWidget框架。我们需要构建一个画布,允许用户手写数字,然后将用户手写的图像输入到CNN模型中进行预测。 在这里,我们可以使用QPainter来绘图,它可以使用户绘制完整的数字。在预测数字时,我们需要对图像进行一些预处理,例如将其大小调整为网络需要的输入尺寸,并将其转换为灰度图像。 在模型训练完毕之后,我们可以将模型保存下来,然后在PyQt5应用程序中加载模型,并使用它进行手写数字的识别。当用户在画布上完成手写数字绘制后,我们可以将其送入已经训练好的CNN模型,然后让程序显示识别结果。 通过这样的方式,我们可以使用PyQt5和TensorFlow-Keras开发手写数字识别应用程序,为用户提供更加便捷的数字识别方式。 ### 回答3: 手写数字识别是深度学习中的一个经典问题,利用人工神经网络或深度卷积神经网络可以达到很高的准确率。PyQt5是一个Python编写的GUI库,可以将深度学习算法应用到用户友好的界面中,同时TensorFlow-Keras是一个强大的深度学习框架,利用它可以快速搭建一个卷积神经网络。 首先,我们需要准备手写数字数据集,比如MNIST数据集。我们可以使用Keras自带的数据集接口进行加载。然后,通过PyQt5绘制一个界面,使得用户可以在界面上进行手写数字输入。手写数字数据可以通过鼠标或触控板进行输入,我们可以将手写数字截图并进行处理,可以使用 PIL 库或 OpenCV 进行图片处理,将图片大小调整为合适的大小。接着,我们需要将图片输入到卷积神经网络中进行预测。我们可以使用TensorFlow-Keras搭建一个卷积神经网络模型,并把刚刚处理好的图片输入到模型中,进行预测。最后,我们可以在界面上输出预测结果,告诉用户识别的数字是什么。 总之,借助PyQt5和TensorFlow-Keras的强大功能,我们可以轻松地设计一个手写数字识别的应用程序。但是需要注意的是,要精度高的数字识别需要使用比较深的卷积神经网络模型,并花费更多的时间来训练和调优模型。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值