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算子优化时候出现了震荡,不稳定,我们对比梯度下降方法试试
下面是使用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 自适应学习率优化算法