手写识别tensorflow版

本文通过创建一个全连接神经网络实现手写数字识别,详细介绍了网络结构设计、参数初始化、前向传播、损失函数计算及反向传播过程,并对比了不同优化算法的效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 使用全连接实现手写识别

1.1 创建Net类

1 样本中手写识别样本都是28*28尺寸的图片,再写net时候要使用tf.placehoder定义x,y。我们这里x就是输入图片矩阵,y就是10个数字,所以我们分别定义了x的shape=[None,784],前面的None表示批次,再网络训练时候会自动给定值,与此同时我们的y值也差不多的格式shape=[None,10],10表示将输出10个概率,其中最大的概率的onehot的下标就是我们的识别概率数字。

2 我们定义了w1,w2,b1,b2 要形成wx+b形式 且上层神经元输出就是下层输入。我们这里使用随机的正太分布获取w,b的初始值。下面我们先看看定以的2层网络的训练变化。

import tensorflow as tf
import numpy as np
class firstNet:
    def __init__(self):
        self.x = tf.placeholder(dtype=tf.float32,shape=[None,784])
        self.y = tf.placeholder(dtype=tf.float32,shape=[None,10])
        self.w1 = tf.Variable(tf.truncated_normal(shape=[784,256],stddev=0.01,dtype=tf.float32))
        self.b1 = tf.Variable(tf.zeros(shape=[256],dtype=tf.float32))
        self.w2 = tf.Variable(tf.truncated_normal(shape=[256, 10], stddev=0.01, dtype=tf.float32))
        self.b2 = tf.Variable(tf.zeros(shape=[10], dtype=tf.float32))
        

    def forward(self):
        y1 = tf.nn.relu(tf.matmul(self.x,self.w1)+self.b1)
       
        self.y2 = tf.matmul(y1, self.w2) + self.b2
        self.output = tf.nn.softmax(self.y2)

    def loss(self):
        self.error  =tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=self.y,logits=self.y2))

    def backforward(self):
        self.optimizer = tf.train.AdamOptimizer(0.001).minimize(self.error)
        # self.optimizer = tf.train.AdagradOptimizer(0.001).minimize(self.error)
        # 使用梯度法会一直下降到局部动荡
        # self.optimizer = tf.train.GradientDescentOptimizer(0.001).minimize(self.error)

    def accuracy(self):
        y = tf.equal(tf.argmax(self.output,axis=1),tf.argmax(self.y,axis=1))
        self.acc = tf.reduce_mean(tf.cast(y, dtype=tf.float32))

使用AdamOptimizer算子优化时候出现了震荡,不稳定,我们对比梯度下降方法试试

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Nv99l6dM-1588167085640)(C:\Users\enjian.li\Desktop\工作日志\images\1588165802807.png)]

下面是使用tf.train.GradientDescentOptimizer(0.001).minimize(self.error) 梯度下降方式。

在这里插入图片描述

而且训练的准确度才0.6左右,造成这个原因是因为神经元一下从256降到10个,死掉很多神经元,造成的。

下面我们对神经网络改造下,将网络层使用四层神经元

import tensorflow as tf
import numpy as np
class firstNet:
    def __init__(self):
        self.x = tf.placeholder(dtype=tf.float32,shape=[None,784])
        self.y = tf.placeholder(dtype=tf.float32,shape=[None,10])
        self.w1 = tf.Variable(tf.truncated_normal(shape=[784,256],stddev=0.01,dtype=tf.float32))
        self.b1 = tf.Variable(tf.zeros(shape=[256],dtype=tf.float32))
        self.w2 = tf.Variable(tf.truncated_normal(shape=[256, 128], stddev=0.01, dtype=tf.float32))
        self.b2 = tf.Variable(tf.zeros(shape=[128], dtype=tf.float32))
        self.w3 = tf.Variable(tf.truncated_normal(shape=[128, 64], stddev=0.01, dtype=tf.float32))
        self.b3 = tf.Variable(tf.zeros(shape=[64], dtype=tf.float32))
        self.w4 = tf.Variable(tf.truncated_normal(shape=[64, 10], stddev=0.01, dtype=tf.float32))
        self.b4 = tf.Variable(tf.zeros(shape=[10], dtype=tf.float32))

    def forward(self):
        y1 = tf.nn.relu(tf.matmul(self.x,self.w1)+self.b1)
        y2 = tf.nn.relu(tf.matmul(y1, self.w2) + self.b2)
        y3 = tf.nn.relu(tf.matmul(y2, self.w3) + self.b3)
        self.y4 = tf.matmul(y3, self.w4) + self.b4
        self.output = tf.nn.softmax(self.y4)

    def loss(self):
        self.error  =tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=self.y,logits=self.y4))

    def backforward(self):
        # self.optimizer = tf.train.AdamOptimizer(0.001).minimize(self.error)
        # self.optimizer = tf.train.AdagradOptimizer(0.001).minimize(self.error)
        # 使用梯度法会一直下降到局部动荡
        self.optimizer = tf.train.GradientDescentOptimizer(0.001).minimize(self.error)

    def accuracy(self):
        y = tf.equal(tf.argmax(self.output,axis=1),tf.argmax(self.y,axis=1))
        self.acc = tf.reduce_mean(tf.cast(y, dtype=tf.float32))

虽然使用四层神经网络,但使用梯度下降很难找到全局最小值,一直跑过头,来回震荡,损失很大,而且精确度才0.1。所以我们通常训练网络模型一般使用adm优化损失函数。

在这里插入图片描述

下面是.AdamOptimizer优化的最终结果 才几个批次,精确度已经达到了0.99了。

在这里插入图片描述

appTask层。

import sys;
from Net import firstNet
import tensorflow as tf
import matplotlib.pyplot as plt
from tensorflow.examples.tutorials.mnist import input_data
import numpy as np
if __name__ == '__main__':
    mnist = input_data.read_data_sets(".\MNIST_data", one_hot=True)
    net = firstNet()
    net.forward()
    net.loss()
    net.backforward()
    net.accuracy()
    init = tf.global_variables_initializer()
    # plt.ion()
    a =[]
    b=[]
    c= []
    with tf.Session() as sess:
       sess.run(init)
       for i in  range(50000):
           xs,ys = mnist.train.next_batch(100)
           error,_ = sess.run([net.error,net.optimizer],feed_dict={net.x:xs,net.y:ys})
           if i % 100 == 0:
               xss, yss = mnist.validation.next_batch(100)
               _error, _output, acc = sess.run([net.error, net.output, net.acc], feed_dict={net.x: xss, net.y: yss})
               label = np.argmax(yss[0])
               out = np.argmax(_output[0])
               print("error:", error)
               print("label:", label, "output:", out)
               print(acc)
               a.append(i)
               b.append(error)
               c.append(_error)
               plt.clf()
               train, = plt.plot(a, b, linewidth=1, color="red")
               validate, = plt.plot(a, c, linewidth=1, color="blue")
               plt.legend([train, validate], ["train", "validate"], loc="right top", fontsize=10)
               plt.pause(0.01)
       plt.show()

在这里插入图片描述

1.2 总结

使用tensorflow我们就轻松实现了手写识别算法的demo,下次来看看激活函数。
优化问题:

1 梯度下降

2 动量优化法(加速下降)

3 自适应学习率优化算法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值