BP神经网络之手写数据识别(python-tensorflow)

BP神经网络之手写数据识别(python-tensorflow)

  • 介绍
    • 数据加载与获取
    • 创建模型
    • 训练模型
    • 预测
    • 补充
      • 记录耗时
      • 保存模型
      • TensorBoard
    • 全代码

介绍

这是一个基于Python的tensorflow的,神经网络对手写数字的识别。
采用两层隐含层的BP神经网络。
本文采用BP全连接网络:输入层(32x32=784)—隐藏层1(256个神经元)—隐藏层2(64个神经元)—输出层(10)。激活函数选择ReLu。
数据集:
下载地址:http://yann.lecun.com/exdb/mnist/
其中包含训练集55000条,验证集5000条,测试集10000条。
图像大小:28x28,灰度图像(通道数=1)。

数据加载与获取

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)#载入数据,独热编码

独热编码:一种疏向量,1个元素为1,其他为0。常用于有限个可能值的字符串或标识符中。优点:使距离计算更合理。

图像显示:

import matplotlib.pyplot as plt
def plot_image(image):
    plt.imshow(image.reshape(28,28),cmap='binary')
    plt.show()
plot_image(mnist.train.images[2000])

BP神经网络之手写数据识别(python-tensorflow)_第1张图片

创建模型

定义全连接层函数:

def fcn_layer(inputs,input_dim,output_dim,activation=None):#全连接层
    W=tf.Variable(tf.truncated_normal([input_dim,output_dim],stddev=0.1))
    b=tf.Variable(tf.zeros([output_dim]))
    XWb=tf.matmul(inputs,W)+b
    if activation is None:
        outputs=XWb
    else:
        outputs=activation(XWb)
    return outputs

创建模型:
输入层(32x32=784)—隐藏层1(256个神经元)—隐藏层2(64个神经元)—输出层(10)。

 x=tf.placeholder(tf.float32,[None,784],name='X')
 y=tf.placeholder(tf.float32,[None,10],name='Y')
 H1_NN=256#第一隐藏层
 H2_NN=64#第二隐藏层
 h1=fcn_layer(inputs=x,input_dim=784,output_dim=H1_NN,activation=tf.nn.relu)
 h2=fcn_layer(inputs=h1,input_dim=H1_NN,output_dim=H2_NN,activation=tf.nn.relu)
 forward=fcn_layer(inputs=h2,input_dim=H2_NN,output_dim=10)#输出
 pred=tf.nn.softmax(forward)#输出

第一隐藏层和第二隐藏层的激活函数为ReLu,输出层用softmax。
Softmax:为每一类别分配一个小数表示的概率,用小数表示的概率相加和为0.1。
P i = e y i ∑ k = 1 c e y k Pi= \frac{e^{yi}}{\sum_{k=1}^{c}e^{yk}} Pi=k=1ceykeyi
初始化损失函数,训练批次等:

loss_function=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y,logits=forward))#损失函数
train_epochs=40#轮次
batch_size=50#每次的样本数
total_batch=int(mnist.train.num_examples/batch_size)
display_step=1#显示
learning_rate=0.01#学习率,更新率
optimizer=tf.train.AdamOptimizer(learning_rate).minimize(loss_function)#优化器
correct_prediction=tf.equal(tf.argmax(y,1),tf.argmax(pred,1))#正确预测表
accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))#准确率

优化器采用AdamOptimizer.
Adam:一阶优化算法,适应性矩估计。通过计算梯度的一阶矩估计和二阶矩估计而为不同参数设计独立自适应性学习率。一般:alpha=0.001,beta1=0.9,beta2=0.999,epslon=10^(-8)。

训练模型

'''创建模型'''
sess=tf.Session()#会话
sess.run(tf.global_variables_initializer())#初始化
'''训练模型'''
for epoch in range(train_epochs):
    for batch in range(total_batch):
        xs,ys=mnist.train.next_batch(batch_size)
        sess.run(optimizer,feed_dict={x:xs,y:ys})#训练
        summary_str=sess.run(merged_summary_op,feed_dict={x:xs,y:ys})#tensorboard
    loss,acc=sess.run([loss_function,accuracy],feed_dict={x:mnist.validation.images,y:mnist.validation.labels})
    if (epoch+1)%display_step==0:#显示
        print("Train Epoch:",'%02d'%(epoch+1),"Loss=",'{:.9f}'.format(loss),"Accuracy=","{:.4f}".format(acc))
accu_test=sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels})#在测试集上准确率
print("Test Accuracy: ",accu_test)

BP神经网络之手写数据识别(python-tensorflow)_第2张图片
BP神经网络之手写数据识别(python-tensorflow)_第3张图片
训练3

预测

import numpy as np
prediction_result=sess.run(tf.argmax(pred,1),feed_dict={x:mnist.test.images})#预测结果
def print_predict_errs(labels,prediction):#找出预测错误的
    count=0
    compare_lists=(prediction==np.argmax(labels,1))
    err_list=[i for i in range(len(compare_lists)) if compare_lists[i]==False]
    ax=[]
    bx=[]
    cx=[]
    for x in err_list:
        #print("index="+str(x)+"标签值:",np.argmax(labels[x]),"预测值:",prediction[x])
        count+=1
        ax.append(mnist.test.images[x][:])#图像
        bx.append(np.argmax(labels[x]))#标签
        cx.append(prediction[x])#预测值
    print("总计:"+str(count))    
    return ax,bx,cx
    
ax,bx,cx=print_predict_errs(labels=mnist.test.labels,prediction=prediction_result)

import matplotlib.pyplot as plt
def plot_images_labels_prediction(images,labels,prediction,index,num=10):#结果可视化
    fig=plt.gcf()
    fig.set_size_inches(10,14)
    if num>25:
        num=25
    for i in range(0,num):
        plt.subplot(5,5,i+1)
        plt.imshow(np.reshape(images[index],(28,28)),cmap='binary')
        title="label="+str(labels[index])
        if len(prediction)>0:
            title+=", predict="+str(prediction[index])
        plt.title(title,fontsize=10)
        plt.axis('off')
        index+=1
    plt.show()  
    
plot_images_labels_prediction(ax,bx,cx,0,25)

预测错误的图像:
BP神经网络之手写数据识别(python-tensorflow)_第4张图片

补充

手写数据的训练、预测已经完成了。如果我们想计算它训练的时间、想保存模型、想在tensorboard中可视化显示,该怎么做呢?

记录耗时

在训练前加入:

'''时间计算'''
from time import time
startTime=time()

训练结束后加入代码:

duration=time()-startTime#耗时
print("Train Finished takes:","{:.2f}".format(duration))

保存模型

训练前加入:

save_step=5#保存间隔
import os
ckpt_dir="./ckpt_dir/"#路径
if not os.path.exists(ckpt_dir):
    os.makedirs(ckpt_dir)
saver=tf.train.Saver()

训练中加入:

if (epoch+1)%save_step==0:#保存
    saver.save(sess,os.path.join(ckpt_dir,'mnist_h256_model_{:06d}.ckpt'.format(epoch+1)))
    print('mnist_h256_model_{:06d}.ckpt saved'.format(epoch+1))

训练后加入:

saver.save(sess,os.path.join(ckpt_dir,'mnist_h256_model.ckpt'))#保存
print('Model saved!')

模型读取:(注意:读取模型要求定义和训练时一样的模型,且在读取前要删除所有节点)
‘’‘模型读取’’’

mode_file=tf.train.latest_checkpoint('./ckpt_dir/')#路径
saver.restore(sess,mode_file)#加载
print("Accuracy:",accuracy.eval(session=sess,feed_dict={x:mnist.test.images,y:mnist.test.labels}))

TensorBoard

训练前加入:

'''tensorbord可视化'''
tf.reset_default_graph()#去除节点
logdir='D:/log'
image_shape_input=tf.reshape(x,[-1,28,28,1])#tensorboard,输入图像,-1:一次进多少数据(不确定)
tf.summary.image('input',image_shape_input,10)#输入图像加入summary
'''tensorbord可视化'''
tf.summary.histogram('forward',forward)#直方图
tf.summary.scalar('loss',loss_function)#标量
tf.summary.scalar('accuracy',accuracy)#标量
merged_summary_op=tf.summary.merge_all()#合并所有summary
writer=tf.summary.FileWriter('log/',sess.graph)

训练中加入:

summary_str=sess.run(merged_summary_op,feed_dict={x:xs,y:ys})#tensorboard
writer.add_summary(summary_str,epoch)#tensorboard

训练后加入:

writer.close()#tensorboard

全代码

# -*- coding: utf-8 -*-
'''
手写数字识别,MNIST,两层隐藏层
'''

import tensorflow as tf
import tensorflow.examples.tutorials.mnist.input_data as input_data #输入数据
'''
tensorbord可视化
'''
tf.reset_default_graph()#去除节点
logdir='D:/log'
'''
网络结构
'''
mnist=input_data.read_data_sets("MNIST_data/",one_hot=True)#载入数据,独热编码
x=tf.placeholder(tf.float32,[None,784],name='X')
y=tf.placeholder(tf.float32,[None,10],name='Y')
H1_NN=256#第一隐藏层
H2_NN=64#第二隐藏层

image_shape_input=tf.reshape(x,[-1,28,28,1])#tensorboard,输入图像,-1:一次进多少数据(不确定)
tf.summary.image('input',image_shape_input,10)#输入图像加入summary

def fcn_layer(inputs,input_dim,output_dim,activation=None):#全连接层
    W=tf.Variable(tf.truncated_normal([input_dim,output_dim],stddev=0.1))
    b=tf.Variable(tf.zeros([output_dim]))
    XWb=tf.matmul(inputs,W)+b
    if activation is None:
        outputs=XWb
    else:
        outputs=activation(XWb)
    return outputs
h1=fcn_layer(inputs=x,input_dim=784,output_dim=H1_NN,activation=tf.nn.relu)
h2=fcn_layer(inputs=h1,input_dim=H1_NN,output_dim=H2_NN,activation=tf.nn.relu)
forward=fcn_layer(inputs=h2,input_dim=H2_NN,output_dim=10)#输出
pred=tf.nn.softmax(forward)#输出

loss_function=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y,logits=forward))#损失函数
train_epochs=40#轮次
batch_size=50#每次的样本数
total_batch=int(mnist.train.num_examples/batch_size)
display_step=1#显示
learning_rate=0.01#学习率,更新率
optimizer=tf.train.AdamOptimizer(learning_rate).minimize(loss_function)#优化器
correct_prediction=tf.equal(tf.argmax(y,1),tf.argmax(pred,1))#正确预测表
accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))#准确率
'''tensorbord可视化'''
tf.summary.histogram('forward',forward)#直方图
tf.summary.scalar('loss',loss_function)#标量
tf.summary.scalar('accuracy',accuracy)#标量
merged_summary_op=tf.summary.merge_all()#合并所有summary


'''模型保存'''
save_step=5#保存间隔
import os
ckpt_dir="./ckpt_dir/"#路径
if not os.path.exists(ckpt_dir):
    os.makedirs(ckpt_dir)
saver=tf.train.Saver()
'''时间计算'''
from time import time
startTime=time()
'''创建模型'''
sess=tf.Session()#会话
sess.run(tf.global_variables_initializer())#初始化
writer=tf.summary.FileWriter('log/',sess.graph)

'''训练模型'''
for epoch in range(train_epochs):
    for batch in range(total_batch):
        xs,ys=mnist.train.next_batch(batch_size)
        sess.run(optimizer,feed_dict={x:xs,y:ys})#训练
        summary_str=sess.run(merged_summary_op,feed_dict={x:xs,y:ys})#tensorboard
        writer.add_summary(summary_str,epoch)#tensorboard
        
    loss,acc=sess.run([loss_function,accuracy],feed_dict={x:mnist.validation.images,y:mnist.validation.labels})
    if (epoch+1)%display_step==0:#显示
        print("Train Epoch:",'%02d'%(epoch+1),"Loss=",'{:.9f}'.format(loss),"Accuracy=","{:.4f}".format(acc))
    if (epoch+1)%save_step==0:#保存
        saver.save(sess,os.path.join(ckpt_dir,'mnist_h256_model_{:06d}.ckpt'.format(epoch+1)))
        print('mnist_h256_model_{:06d}.ckpt saved'.format(epoch+1))
saver.save(sess,os.path.join(ckpt_dir,'mnist_h256_model.ckpt'))#保存
print('Model saved!')
duration=time()-startTime#耗时
print("Train Finished takes:","{:.2f}".format(duration))

accu_test=sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels})#在测试集上准确率
print("Test Accuracy: ",accu_test)

writer.close()#tensorboard

import numpy as np
prediction_result=sess.run(tf.argmax(pred,1),feed_dict={x:mnist.test.images})#预测结果
def print_predict_errs(labels,prediction):#找出预测错误的
    count=0
    compare_lists=(prediction==np.argmax(labels,1))
    err_list=[i for i in range(len(compare_lists)) if compare_lists[i]==False]
    ax=[]
    bx=[]
    cx=[]
    for x in err_list:
        #print("index="+str(x)+"标签值:",np.argmax(labels[x]),"预测值:",prediction[x])
        count+=1
        ax.append(mnist.test.images[x][:])#图像
        bx.append(np.argmax(labels[x]))#标签
        cx.append(prediction[x])#预测值
    print("总计:"+str(count))    
    return ax,bx,cx
ax,bx,cx=print_predict_errs(labels=mnist.test.labels,prediction=prediction_result)

import matplotlib.pyplot as plt
def plot_images_labels_prediction(images,labels,prediction,index,num=10):#结果可视化
    fig=plt.gcf()
    fig.set_size_inches(10,14)
    if num>25:
        num=25
    for i in range(0,num):
        plt.subplot(5,5,i+1)
        plt.imshow(np.reshape(images[index],(28,28)),cmap='binary')
        title="label="+str(labels[index])
        if len(prediction)>0:
            title+=", predict="+str(prediction[index])
        plt.title(title,fontsize=10)
        plt.axis('off')
        index+=1
    plt.show()  
plot_images_labels_prediction(ax,bx,cx,0,25)

'''模型读取'''
mode_file=tf.train.latest_checkpoint('./ckpt_dir/')#路径
saver.restore(sess,mode_file)#加载
print("Accuracy:",accuracy.eval(session=sess,feed_dict={x:mnist.test.images,y:mnist.test.labels}))

你可能感兴趣的:(Python,神经网络)