Tensorflow入门(7)——基于单个神经元的手写数字识别

一、神经网络

关于神经网络,网上的介绍很多,一些基本原理就不再赘述了,默认大家已经掌握了一定程度的知识,只简单提及一些相关内容。博客以如何在tensoeflow下实现为主。

 其中,z为输出结果,x_{i}为输入,w_{i}为相应的权重,b为偏置,f为激活函数。

正向传播:数据是从输入端流向输出端的,当赋予w_{i}b合适的值并结合合适的激活函数时,可产生很好的拟合效果。

反向传播

  • 反向传播的意义在于,告诉我们需要将w和b调整到多少。
  • 在刚开始没有得到合适的w和b时,正向传播所产生的结果与真实值之间存在误差,反向传播就是利用这个误差信号修正w和b的取值,从而获得一个与真实值更加接近的输出。
  • 在实际训练过程中,往往需要多次调整ww和bb,直至模型输出值与真实值小于某个阈值。

激活函数:运行时激活神经网络中部分神经元,将激活信息向后传入下一层神经网络。激活函数的主要作用是,加入非线性因素,以解决线性模型表达能力不足的问题。

常用激活函数:

  • Sigmoid ,在Tensorflow中对应函数为:tf.nn.sigmoid(x, name=None)
  • Tanh ,在Tensorflow中对应函数为:tf.nn.tanh(x, name=None)
  • Relu ,在Tensorflow中对应函数为:tf.nn.relu(x, name=None)

二、载入数据

MNIST 数据集 来自美国国家标准不技术研究所, National Institute of Standards and Technology (NIST). 数据集由来自 250 个不同人手写的数字构成, 其中 50% 是高中学生, 50% 来自人口普查局 (the Census Bureau) 的工作人员 。
MNIST 数据集可在 http://yann.lecun.com/exdb/mnist/ 获取 ,不过TensorFlow自己提供了数据集读取方法
import tensorflow as tf 
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

三、构建模型

1.创建变量

# 定义占位符 
tf.reset_default_graph() #清除default graph和不断增加的节点

x = tf.placeholder(tf.float32, [None, 784]) # mnist 中每张图片共有28*28=784个像素点
y = tf.placeholder(tf.float32, [None, 10]) # 0-9 一共10个数字=> 10 个类别

# 创建变量
norm = tf.random_normal([100]) #生成100个随机数
with tf.Session() as sess:
    norm_data=norm.eval()
print(norm_data[:10])                  #打印前10个随机数

import matplotlib.pyplot as plt
plt.hist(norm_data)
plt.show()

# 在本案例中,以正态分布的随机数初始化权重w,以常数0初始化偏置b
W = tf.Variable(tf.random_normal([784, 10]))
b = tf.Variable(tf.zeros([10])) 

2.用单个神经元构建神经网络

forward=tf.matmul(x, W) + b # 前向输出
tf.summary.histogram('forward',forward)#将前向输出值以直方图显示
pred = tf.nn.softmax(forward) # Softmax分类

示例中在执行训练后在tensorboard界面可查看到如下关于forward的直方图【histograms】以及模型概况:

当我们处理多分类任务时,通常需要使用Softmax Regression模型。
Softmax Regression会对每一类别估算出一个概率。
工作原理: 将判定为某一类的特征相加,然后将这些特征转化为判定是这一类的概率。

3.训练模型

# 设置训练参数
train_epochs = 30
batch_size = 100
total_batch= int(mnist.train.num_examples/batch_size)
display_step = 1
learning_rate=0.01

# 定义损失函数 
# 交叉熵
loss_function = tf.reduce_mean(-tf.reduce_sum(y*tf.log(pred), reduction_indices=1)) 
tf.summary.scalar('loss', loss_function)#将损失以标量显示

# 选择优化器 
# 梯度下降
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss_function) 

# 定义准确率
# 检查预测类别tf.argmax(pred, 1)与实际类别tf.argmax(y, 1)的匹配情况
correct_prediction = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1))
# 准确率
# 将布尔值转化为浮点数,并计算平均值
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) 

tf.summary.scalar('accuracy', accuracy)#将准确率以标量显示

sess = tf.Session() #声明会话
init = tf.global_variables_initializer() # 变量初始化
sess.run(init)

merged_summary_op = tf.summary.merge_all()#合并所有summary
writer = tf.summary.FileWriter('log/mnist_single_neuron', 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
        summary_str = sess.run(merged_summary_op,feed_dict={x: xs,y: ys})
        writer.add_summary(summary_str, epoch)#将summary 写入文件
        #total_batch个批次训练完成后,使用验证数据计算误差与准确率   
    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))

print("Train Finished!")  

从上述打印结果可以看出损失值 Loss 是趋于更小的,同时,准确率 Accuracy 越来越高。
此外,我们还可以通过Tensorboard查看loss和accuracy的执行过程。
通过tensorboard --logdir=log/mnist_single_neuron进入可视化界面,在scalar版面中可以查看loss和accuracy,如下图所示

4.模型评估与预测

# 完成训练后,在测试集上评估模型的准确率
print("Test Accuracy:", sess.run(accuracy,
        feed_dict={x: mnist.test.images, y: mnist.test.labels}))

# 在建立模型并进行训练后,若认为准确率可以接受,则可以使用此模型进行预测。
# 由于pred预测结果是one-hot编码格式,所以需要转换为0~9数字 
prediction_result=sess.run(tf.argmax(pred,1), 
                           feed_dict={x: mnist.test.images })

# 查看预测结果 
prediction_result[0:10] #查看预测结果中的前10项

5.可视化

# 定义可视化函数 
import matplotlib.pyplot as plt
import numpy as np
def plot_images_labels_prediction(images,labels,
                                  prediction,idx,num=10):
    fig = plt.gcf()
    fig.set_size_inches(10, 12)
    if num>25: num=25 
    for i in range(0, num):
        ax=plt.subplot(5,5, 1+i)
        
        ax.imshow(np.reshape(images[idx],(28, 28)), 
                  cmap='binary')
            
        title= "label=" +str(np.argmax(labels[idx]))
        if len(prediction)>0:
            title+=",predict="+str(prediction[idx]) 
            
        ax.set_title(title,fontsize=10) 
        ax.set_xticks([]);ax.set_yticks([])        
        idx+=1 
    plt.show()


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

从上面结果可知,通过30次迭代所训练的由 单个神经元 构成的神经网络模型,在测试集上能够取得百分之八十以上的准确率。接下来,我们将尝试 加宽 加深 模型,看看能否得到更高的准确率。 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是一个基于OpenCV和机器学习的手写数字识别教程的简要步骤: 1. 收集和准备数据集:首先,收集一组手写数字图像,并将它们分为训练集和测试集。确保图像是标准化的,例如统一大小和灰度。 2. 提取特征:将图像转换为特征向量是进行机器学习的关键步骤。在手写数字识别中,常用的特征提取方法是将图像像素矩阵展平为一维向量。 3. 训练模型:使用机器学习算法对训练集进行训练,以构建一个数字分类器。常用的算法包括支持向量机(SVM)、随机森林(Random Forest)和神经网络等。 4. 测试和评估模型:使用测试集对训练好的模型进行测试,并计算准确率、召回率、F1分数等评估指标来评估模型的性能。 下面是一个基于OpenCV和SVM的简单示例代码: ```python import cv2 import numpy as np from sklearn import svm # 加载手写数字数据集 digits = cv2.imread('digits.png', 0) digits = np.float32(digits) # 分割图像并准备训练数据 cells = [np.hsplit(row, 100) for row in np.vsplit(digits, 50)] X = np.array(cells).reshape(-1, 400).astype(np.float32) # 创建标签 y = np.repeat(np.arange(10), len(X) / 10) # 训练SVM模型 model = svm.SVC(kernel='linear') model.fit(X, y) # 加载测试图像并进行预测 image = cv2.imread('test_digit.png', 0) image = np.float32(image.reshape(1, -1)) # 预测结果 result = model.predict(image) print("Predicted digit:", result[0]) ``` 在上述示例中,我们首先加载手写数字数据集,将图像分割为单个数字图像,并准备训练数据。然后,使用SVM算法对训练数据进行训练。最后,我们加载测试图像并将其用于预测,输出预测结果。 这只是一个简单的示例,实际的手写数字识别系统可能需要更复杂的特征提取和模型优化方法。但希望这个简要教程对你有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值