Tensorflow2.0 mnist手写数字识别
使用改进后的Lenet-5网络:
import tensorflow as tf
import tensorflow.keras.layers as layers
from tensorflow.keras import Sequential
import numpy as np
from tensorflow.keras import losses,optimizers
from tensorflow.keras import metrics
#网络层的搭建
networks=Sequential([
layers.Conv2D(6,kernel_size=3,strides=1),
layers.MaxPooling2D(pool_size=2,strides=2),
layers.ReLU(), #(可以不要这一层)激活函数类并不是主要的网络计算层,不计入网络层数
layers.Conv2D(16,kernel_size=3,strides=1),
layers.MaxPooling2D(pool_size=2,strides=2),
layers.ReLU(),
layers.Flatten(),
layers.Dense(120,activation='relu'),
layers.Dense(84,activation='relu'),
layers.Dense(10) #输出层,没有激活函数(激活函数为None)
])
networks.build(input_shape=(4,28,28,1)) #这里的4即为后面的batch_size
#networks.summary()
#数据集的导入
x=np.load('mnist.npz')
print(x.files) #使用files,输出:['x_test', 'x_train', 'y_train', 'y_test']
test_data=x['x_test'] #一定要加''号
train_data=x['x_train']
train_label,test_label=x['y_train'],x['y_test']
#为了契合networks.build(),这里需要将数据集的维度增加一维,即从一个平面,变成单通道
test_data=tf.expand_dims(test_data/255.0,axis=-1) #扩维,并归一化
train_data=tf.expand_dims(train_data/255.0,axis=-1)
#数据集的batch等处理,这里没有使用随机选取batch,而是为了方便按顺序取batch
def get_batch(batch_size,i):
#index=np.random.randint(0,np.shape(train_data)[0],batch_size) #np.shape(train_data)表示train_data的形状
x=4*i
train_data_batch=train_data[x:x+4,:]
train_lable_batch=train_label[x:x+4]
if x+4 >= num_train_data:
x=0
return train_data_batch,train_lable_batch
#定义训练模型所需要的参数
epoch=5
batch_size=4 #这里必须与神经网络的输入尺寸一致
num_train_data=np.shape(train_data)[0]
batch_num=int(num_train_data//batch_size) #这里必须取整
optimizer=optimizers.Adam(learning_rate=0.001)
#模型训练 |损失函数:softmax交叉熵损失函数
#loss_object=losses.CategoricalCrossentropy(from_logits=True) #这是一个类,loss_object为类的实例化对象
for n in range(epoch):
for i in range(batch_num):
with tf.GradientTape() as tape: #with语句内引出需要求导的量
x,y=get_batch(4,i)
out=networks(x)
y_onehot=tf.one_hot(y,depth=10)
loss_object=losses.CategoricalCrossentropy(from_logits=True)
loss=loss_object(y_onehot,out) #使用损失函数类来计算损失
print('epoch:%d batch:%d loss:%f'%(n,i,loss.numpy()))
grad=tape.gradient(loss,networks.trainable_variables) #用以自动计算梯度
optimizer.apply_gradients(zip(grad,networks.trainable_variables))
#模型的测试,使用metrics中的SparseCategoricalAccuracy()中的update_state来对比
#由于在测试集中不需要进行参数的更新等,可使用predict来直接得出训练的结果
#最后使用SparseCategoricalAccuracy()中封装的result()来直接得出预测准确度的结果
s_c_a=metrics.SparseCategoricalAccuracy()
num_test_batch=int(np.shape(test_data)[0]//batch_size)
for num_index in range(num_test_batch):
start_index,end_index=num_index*batch_size,(num_index+1)*batch_size
y_predict=networks.predict(test_data[start_index:end_index])
s_c_a.update_state(y_true=test_label[start_index:end_index],y_pred=y_predict)
print('test accuracy:%f'%s_c_a.result())
由于为经典的数据集,在训练一个epoch后的精确度可达:97.29%,后面随着epoch的增加,还会提高