前馈神经网络进行MNIST数据集分类

前馈神经网络

前馈神经网络是一种最简单的神经网络,各神经元分层排列,每个神经元只与前一层的神经元相连。接收前一层的输出,并输出给下一层,各层之间没有反馈。是目前应用最广泛、发展最迅速的人工神经网络之一。——百度百科

借用百度百科中的前馈神经网络示意图

在这里插入图片描述

这是一个多层前馈神经网络模型,除开输入层和输出层外,有两层隐藏层。

这里是一个全连接的情况,即除开输入层外,每一层的每个神经元都与前一层所有的神经元相连。

根据这样的一个模型,前馈神经网络可以通过逐层的信息传递,得到整个网络的最终输出 a ( L ) a^{(L)} a(L),这样我们可以把整个网络看成是一个复合函数 ϕ ( x ; W , b ) \phi(x;W,b) ϕ(x;W,b),将向量 x = [ x 1 , x 2 , . . . , x n ] T x=[x_1,x_2,...,x_n]^T x=[x1,x2,...,xn]T作为第一层的输入 a ( 0 ) a^{(0)} a(0),将第 L L L层的输出 a ( L ) a^{(L)} a(L)作为整个函数的输出。
x = a ( 0 ) → z ( 1 ) → a ( 1 ) → a ( 2 ) → ⋅ ⋅ ⋅ → a ( L − 1 ) → z ( L ) → a ( L ) = ϕ ( x ; W , b ) x=a^{(0)}→z^{(1)}→a^{(1)}→a^{(2)}→···→a^{(L-1)}→z^{(L)}→a^{(L)}=\phi(x;W,b) x=a(0)z(1)a(1)a(2)a(L1)z(L)a(L)=ϕ(x;W,b)
从输出层开始为第0层, a ( i ) a^{(i)} a(i)是第 i i i层输出给第 i + 1 i+1 i+1层的数据, z ( i ) z^{(i)} z(i)是第 i i i层将 a ( i − 1 ) a^{(i-1)} a(i1)进行计算后得到的数据。

这个 a ( i ) a^{(i)} a(i)的含义也称作第 i i i层神经元的活性值, z ( i ) z^{(i)} z(i)称作第 i i i层的净活性值。

具体神经元进行计算的过程如下:
KaTeX parse error: No such environment: align at position 8: \begin{̲a̲l̲i̲g̲n̲}̲ z^{(i)}&=W^{(i…
将两层的公式合并,就可以写成:
KaTeX parse error: No such environment: align at position 8: \begin{̲a̲l̲i̲g̲n̲}̲ z^{(i)}&=W^{(i…

参数学习

前馈神经网络的参数个数与网络模型的规模有关。

本文只考虑“每个神经元都与前一层的所有神经元相连”的情况,前馈神经网络顾名思义,数据从前往后顺序输入输出,参数学习通过梯度下降算法不断迭代每一个参数。

由于MNIST分类问题依然是个十分类问题,所以损失函数依然采用交叉熵损失函数;

并且将标签 y y y替换为 o n e − h o t one-hot onehot向量表示;

通过梯度下降算法进行参数学习;

激活函数使用relu激活函数。

具体算法实现

import tensorflow as tf
import matplotlib.pyplot as plt
# 输入层 784 
# 隐藏层 256
# 隐藏层 128 
# 输出层 10
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 = tf.convert_to_tensor(x_train,dtype=tf.float32)/255.

# (60000,28,28) -> (60000,784)
x_train = tf.reshape(x_train,[-1,28*28])
# one-hot
y_train = tf.one_hot(y_train,depth=10)

lr = 0.01
# 开始训练
All_loss = []
for step in range(4001):
    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])
    All_loss.append(loss)
    # 更新参数
    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]) 

训练次数为4000次,学习率 α = 0.01 \alpha=0.01 α=0.01

查看loss值下降曲线

plt.plot(All_loss)

在这里插入图片描述

loss值从1500次之后下降变得平缓,逐渐稳定在1.7以下。

查看模型在测试集上的效果

x_r_test = x_test
y_r_test = y_test
x_test = tf.convert_to_tensor(x_test,dtype=tf.float32)/255.

x_test = tf.reshape(x_test,[-1,28*28])
y_test=tf.one_hot(y_test,depth=10)

out3 = tf.nn.softmax(tf.nn.relu(tf.nn.relu(x_test@w1 + b1)@w2 + b2)@w3+b3)
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_test,logits=out3))

import numpy as np
plt.figure(figsize=(18,18))
for i in range(10):
    plt.subplot(2,5,i+1)
    plt.title(str(y_r_test[i])+str(",")+str(np.argmax(out3[i])))
    plt.imshow(x_r_test[i])
plt.show()

抽取测试集中前10个数据样本,绘图查看结果:

在这里插入图片描述

在这里插入图片描述

可以看到,这十副图片的预测结果都是比较准确的。

(图片标题中,第一个数字是真实值,第二个数字是预测值)

查看正确率

acc_count = 0
for i in range(len(x_test)):
    if np.argmax(out3[i]) == y_r_test[i]:
        acc_count = acc_count + 1
acc_count/len(x_test)

在这里插入图片描述

4000次的迭代,10000个数据的测试集上的预测正确率已经达到了 83.27 % 83.27\% 83.27%

acc_count = 0
for i in range(len(x_train)):
    if np.argmax(out3_train[i]) == y_r_train[i]:
        acc_count = acc_count + 1
acc_count/len(x_train)

在这里插入图片描述

而在60000个数据的训练集上,预测正确率达到了 82.34 % 82.34\% 82.34%

总结

神经网络的使用,突破了很多深度学习任务的瓶颈。使用神经网络去训练得到的结果,比一般的线性模型要好很多。虽然在激活函数、损失函数等等函数的使用上,跟简单的线性模型使用的一样,但是仅仅是三层神经网络,它的模型就优于线性模型很多了。

而且在训练次数、学习率、训练样本、网络深度、网络结构等等超参数上还可以进行人为调整,那么在一定范围内调整这些超参数,还可以得到更高更好的分类结果。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值