前馈神经网络进行MNIST数据集分类【实战】

前馈神经网络进行MNIST数据集分类【实战】

import tensorflow as tf
from tensorflow import keras
import numpy as np
import matplotlib.pyplot as plt
print(tf.__version__)

1 需要建立全连接神经网络

输入层 h0 有784个神经元=28 * 28

隐藏层 h1 256

隐藏层 h2 128

输出层 h3 10

w1是在输入成和第一个隐藏层之间的

w2是第一个隐藏层到第二个隐藏层之间的

w3是第二个隐藏层到输出层之间的

# 初始化参数
# tf中一般使用Variable来定义梯度(要变的量),constant一般用于定义常量
# truncated_normal是截断的正态分布
w1 = tf.Variable(tf.random.truncated_normal([784,256],stddev=0.1))
w2 = tf.Variable(tf.random.truncated_normal([256,128],stddev=0.1))
w3 = tf.Variable(tf.random.truncated_normal([128,10],stddev=0.1))

b1 = tf.Variable(tf.zeros([256]))
b2 = tf.Variable(tf.zeros([128]))
b3 = tf.Variable(tf.zeros([10]))

#载入数据集
(x_train, y_train), (x_test,y_test) = tf.keras.datasets.mnist.load_data()

(x_train.shape,y_train.shape),(x_test.shape,y_test.shape)


type(x_train)


# 因为生成的数是0-255之间的,所以需要除以255
# 注意这里必须是ndarray数组
x_train = tf.convert_to_tensor( x_train,dtype=tf.float32 )/255.
y_train = tf.convert_to_tensor( y_train,dtype=tf.int32)
#t通过这个方法可以把ndarray数组转换为Tensor
#十分注意,tf2中的数据类型必须要正确,否则会出现很多奇奇怪怪的错误

#所以需要把x_train拉成(60000,784)并转换数据为TensorShape
x_train = tf.reshape( x_train , [-1,28*28] ) 
#-1代表任意多个值,但是最后一个数必须有
x_train.shape
 

2 完成一次前向计算

x_train.shape,w1.shape,b1.shape

# h1 :net1(z= sum(wx+b))  out1 (relu(z))
# 使用@可以直接进行矩阵运算
# 注意b1的形状,需要将b1扩充为60000*256

# net1 = x_train@w1 + tf.broadcast_to(b1,[x_train.shape[0],256])
# net1

# h1 : net1 (z=sum(wx+b)) out1 (relu(z))
# [60000,784]@[784*256]+[256]
net1 = x_train@w1 + b1 # 加号直接就有广播的性质,但是需要注意这里实际上是做了一个广播
out1 = tf.nn.relu(net1)

# h2 : net2 (z=sum(wx+b)) out2 (relu(z))
# [60000,256]@[256*128]+[128]
net2 = out1@w2 + b2
out2 = tf.nn.relu(net2)

# h3 : net3 (z=sum(wx+b)) out3 (relu(z))
# [60000,256]@[256*128]+[128]
net3 = out2@w3 + b3
out3 = tf.nn.softmax(net3)

y_train = tf.one_hot(y_train,depth=10)
y_train,y_train.shape

loss = tf.nn.softmax_cross_entropy_with_logits(labels=y_train,logits=out3)
loss = tf.reduce_mean(loss)
loss

3 反向传播

with tf.GradientTape() as tape:
    tape.watch([w1,b1,w2,b2,w3,b3])
    out3 = tf.nn.softmax(tf.nn.relu((tf.nn.relu( x_train@w1 + b1))@w2 + b2)@w3+b3)
    loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_train,logits=out3))
    

grads  =tape.gradient(loss , [w1,b1,w2,b2,w3,b3])

lr = 0.01

# 更新参数
# w = w -lr * grads
# w -= lr*grads
# tf.assign_sub

All_loss = []
for step in range(5001):
    with tf.GradientTape() as tape:
        tape.watch([w1,b1,w2,b2,w3,b3])
        out3 = tf.nn.softmax(tf.nn.relu((tf.nn.relu( x_train@w1 + b1))@w2 + b2)@w3+b3)
        loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_train,logits=out3))
    All_loss.append(loss)
    grads  =tape.gradient(loss , [w1,b1,w2,b2,w3,b3])
    # 更新参数
    w1.assign_sub(lr*grads[0])
    b1.assign_sub(lr*grads[1])
    w2.assign_sub(lr*grads[2])
    b2.assign_sub(lr*grads[3])
    w3.assign_sub(lr*grads[4])
    b3.assign_sub(lr*grads[5])
    if step%100 == 0 :
        print(step,'loss: ',float(loss))
    

plt.plot(All_loss)

会画出如下图像,能看出来如果增加迭代次数还能继续小范围

前馈神经网络进行MNIST数据集分类【实战】_第1张图片

测试模型

x_test = tf.convert_to_tensor( x_test,dtype=tf.float32 )/255.
y_test = tf.convert_to_tensor( y_test,dtype=tf.int32)
x_test = tf.reshape( x_test , [-1,28*28] ) 

out3 = tf.nn.softmax(tf.nn.relu((tf.nn.relu( x_test@w1 + b1))@w2 + b2)@w3+b3)
out3

y_predict = tf.math.argmax(out3,axis=-1)

y_predict,y_test

y_test = tf.cast(y_test,tf.int64) #常用于转换数据类型

tf.math.equal(y_predict,y_test)

y_c = tf.math.equal(y_predict,y_test)
y_c

# True无法直接进行计算,所以需要转换数据类型
y_c = tf.cast(y_c,tf.int64)
y_c

r = tf.math.reduce_sum(y_c)/10000
r.numpy()
        

 

你可能感兴趣的:(TensorFlow-深度学习,tensorflow,深度学习,机器学习,神经网络)