识别mnist手写数字手动搭建3层神经网络笔记

识别mnist手写数字手动搭建3层神经网络笔记

 

没有采用tf.mode.Sequential的方式搭建,打个基础吧。

参考了鸢尾花识别的代码

保证数据维度相同十分重要!!!

注意:tf.onehot中【tf.float32、int8、int16无法用,int32则可以】。或直接.numpy()转为numpy类型,好像dtype指定类型也行??

import tensorflow as tf  # 导入 TF 库

from tensorflow import keras  # 导入 TF 子库 keras

from tensorflow.keras import layers, optimizers, datasets  # 导入 TF 子库等

import matplotlib.pyplot as plt





(x, y), (x_val, y_val) = datasets.mnist.load_data()  # 加载 MNIST 数据集

# 样本、验证集打平打平 并取出前20000个作为样本数据集

x = x.reshape(x.shape[0],-1)[0:20000,:]

y = y[0:20000]

x_val = x_val.reshape(x_val.shape[0],-1)

y_val = y_val.reshape(y_val.shape[0],-1)

输入样本x需要转化为tf张量,并归一化

# 转换成tensorflow张量,再转换成float32

# x、x_val归一化

x = tf.convert_to_tensor(x)

x_train = tf.cast(x,tf.float32) / 255

y_train = tf.cast(y,tf.int8)

x_val = tf.convert_to_tensor(x_val)

x_test = tf.cast(x_val,tf.float32) / 255

y_test = tf.cast(y_val,tf.float32)

将batch size设置为256 把数据集分批。分批后数据集(如train_db)是一个可迭代对象,batch size设置为2的n次幂

# 将数据集分批次,并设定每批次个数。并特征与标签一一对应

train_db = tf.data.Dataset.from_tensor_slices((x_train,y_train)).batch(256)

test_db = tf.data.Dataset.from_tensor_slices((x_test,y_test)).batch(256)

初始化参数,随机初始化。注意,要与输入样本的维度对应。每个样本打平后有784个像素,所以,第一层维度需要是784*N。最后一层输出10个类别,所以最后一层为 N*10。

# 生成神经网络参数,设置为三层256,128,10个神经元,10分类

w1 = tf.Variable(tf.random.truncated_normal([784,256],stddev=0.1))

b1 = tf.Variable(tf.random.truncated_normal([256], stddev=0.1))




w2 = tf.Variable(tf.random.truncated_normal([256,128],stddev= 0.1))

b2 = tf.Variable(tf.random.truncated_normal([128], stddev=0.1))




w3 = tf.Variable(tf.random.truncated_normal([128,10],stddev= 0.1))

b3 = tf.Variable(tf.random.truncated_normal([10], stddev=0.1))

初始化参数

lr = 0.1  #学习率

train_loss_results = []  # 将每轮的loss记录在此列表中,为后续画loss曲线提供数据

test_acc = []  # 将每轮的acc记录在此列表中,为后续画acc曲线提供数据

epochs = 500  # 循环500轮

loss_all = 0  # 每轮分30个step,loss_all记录四个step生成的4个loss的和

循环每个epoch,每个epoch又要循环batch,用with tf.GradientTape() as tape 可以记录图用来求梯度。

loss记录的是平均损失。每次match会记录一个损失,加起来后除以一个epoch中batch的个数,就是一次epoch中的平均损失。

correct记录预测正确的个数,用来计算准确度。但是,tf.equal(tf.reshape(pred,y_test.shape) 使用过程中,如果pred和y_test的shape不相符会出现问题。

例如:pred 的 shape为 [256],y_test 的 shape为 [256,1] 则结果返回一个 [256,256]。

for epoch in range(epochs):

    # 循环500eopch,每个epoch将各自batch循环一遍

    for step,(x_train,y_train) in enumerate(train_db):

        with tf.GradientTape() as tape:

            #记录梯度

            #神经元计算

            #求和指数函数转化为概率

            #将标签值转换为one-hot编码

            #loss_all += loss.numpy()

            #激活函数

            y1 = tf.matmul(x_train, w1) + b1

            y1 = tf.nn.relu(y1)

            y2 = tf.matmul(y1,w2) + b2

            y2 = tf.nn.relu(y2)

            y3 = tf.matmul(y2,w3) + b3

            y3 = tf.nn.softmax(y3)

            # y = tf.matmul(x_train, w1) + b1

            # y = tf.nn.softmax(y)

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

            loss = tf.reduce_mean(tf.square(y_ - y3))

            loss_all += loss.numpy()

        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])

    print("Epoch {}, loss: {}".format(epoch, loss_all/79))

    train_loss_results.append(loss_all / 79)

    loss_all = 0



    total_correct, total_number = 0, 0    #用来计算精度

    for x_test,y_test in test_db:

        # 求取预测值y

        # 返回y最大概率的索引即为类别

        # 统计正确数量作为精度

        y1 = tf.matmul(x_test, w1) + b1

        y1 = tf.nn.relu(y1)

        y2 = tf.matmul(y1, w2) + b2

        y2 = tf.nn.relu(y2)

        y3 = tf.matmul(y2, w3) + b3

        y3 = tf.nn.softmax(y3)

        pred = tf.argmax(y3,axis=1)    #返回索引,此处不用在将y_test转化为独热码形式了。

        pred = tf.cast(pred,dtype = y_test.dtype)

        correct = tf.cast(tf.equal(tf.reshape(pred,y_test.shape), y_test),  dtype=tf.int32)

        correct = tf.reduce_sum(correct)    #统计预测正确的个数

        total_correct += int(correct)

        total_number += x_test.shape[0]    #统计验证样本个数

    acc = total_correct / total_number    #得到精度

    test_acc.append(acc)

    print("Test_acc:", acc)

    print("--------------------------")

loss与accuracy曲线绘制在一张图。

# 绘制 loss 曲线

plt.subplot(2,1,1)

plt.title('Loss Function Curve')  # 图片标题

plt.xlabel('Epoch')  # x轴变量名称

plt.ylabel('Loss')  # y轴变量名称

plt.plot(train_loss_results, label="$Loss$")  # 逐点画出trian_loss_results值并连线,连线图标是Loss

plt.legend()  # 画出曲线图标




# 绘制 Accuracy 曲线

plt.subplot(2,1,2)

plt.title('Acc Curve')  # 图片标题

plt.xlabel('Epoch')  # x轴变量名称

plt.ylabel('Acc')  # y轴变量名称

plt.plot(test_acc, label="$Accuracy$")  # 逐点画出test_acc值并连线,连线图标是Accuracy

plt.tight_layout()

plt.legend()

plt.show()

最后结果如下

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值