反向传播(BPN)算法是神经网络中研究最多、使用最多的算法之一,它用于将输出层中的误差传播到隐藏层的神经元,然后用于更新权重。
学习 BPN 算法可以分成以下两个过程:
正向传播:输入被馈送到网络,信号从输入层通过隐藏层传播到输出层。在输出层,计算误差和损失函数。
反向传播:在反向传播中,首先计算输出层神经元损失函数的梯度,然后计算隐藏层神经元损失函数的梯度。接下来用梯度更新权重。
这两个过程重复迭代直到收敛。使用MNIST数据集
具体实现过程
# 反向传播(BPN)算法
# 导入模块
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
# 加载数据集,通过设置 one_hot=True 来使用独热编码标签
mnist = input_data.read_data_sets("MNIST_data", one_hot=True)
'''
定义超参数和其他常量。这里,每个手写数字的尺寸是 28×28=784 像素。
数据集被分为 10 类,以 0 到 9 之间的数字表示。这两点是固定的。
学习率、最大迭代周期数、每次批量训练的批量大小以及隐藏层中的神经元数量都是超参数。
可以通过调整这些超参数,看看它们是如何影响网络表现的.
'''
n_input = 784
n_classes = 10
max_epochs = 10000
learning_rate = 0.5
batch_size = 10
seed = 0
n_hidden = 30
# 需要sigmoid函数的导数来进行权重更新,所以定义它:
def sigmaprime(x):
return tf.multiply(tf.sigmoid(x), tf.subtract(tf.constant(1.0), tf.sigmoid(x)))
# 为训练数据创建占位符:
X_in = tf.compat.v1.placeholder(tf.float32, [None, n_input])
y = tf.compat.v1.placeholder(tf.float32, [None, n_classes])
# 创建模型
def multilayer_perceptron(x, weights, biases):
h_layer_1 = tf.add(tf.matmul(x, weights['h1']), biases['h1'])
out_layer_1 = tf.sigmoid(h_layer_1)
h_out = tf.matmul(out_layer_1, weights['out']) + biases['out']
return tf.sigmoid(h_out), h_out, out_layer_1, h_layer_1
# 定义权重和偏置变量
weights = {
'h1': tf.Variable(tf.compat.v1.random.normal([n_input, n_hidden], seed=seed)),
'out': tf.Variable(tf.compat.v1.random.normal([n_hidden, n_classes], seed=seed))
}
biases = {
'h1': tf.Variable(tf.random.normal([1, n_hidden], seed=seed)),
'out': tf.Variable(tf.random.normal([1, n_classes], seed=seed))
}
# 为正向传播、误差、梯度和更新计算创建计算图
# Forward Pass
y_hat, h_2, o_1, h_1 = multilayer_perceptron(X_in, weights, biases)
# Error
err = y_hat - y
# Backward Pass
delta_2 = tf.multiply(err, sigmaprime(h_2))
delta_w_2 = tf.matmul(tf.transpose(o_1), delta_2)
wtd_error = tf.matmul(delta_2, tf.transpose(weights['out']))
delta_1 = tf.multiply(wtd_error, sigmaprime(h_1))
delta_w_1 = tf.matmul(tf.transpose(X_in), delta_1)
eta = tf.constant(learning_rate)
# 更新参数(Update weights)
step = [
tf.compat.v1.assign(weights['h1'], tf.subtract(weights['h1'], tf.multiply(eta, delta_w_1))),
tf.compat.v1.assign(biases['h1'], tf.subtract(biases['h1'], tf.multiply(eta, tf.reduce_mean(delta_1, axis=[0])))),
tf.compat.v1.assign(weights['out'], tf.subtract(weights['out'], tf.multiply(eta, delta_w_2))),
tf.assign(biases['out'], tf.subtract(biases['out'], tf.multiply(eta, tf.reduce_mean(delta_2, axis=[0]))))
]
# 定义计算精度accuracy的操作
acc_mat = tf.equal(tf.argmax(y_hat, 1), tf.argmax(y, 1))
accuracy = tf.reduce_sum(tf.cast(acc_mat, tf.float32))
# 初始化变量:
init = tf.compat.v1.global_variables_initializer()
# 执行图:
with tf.compat.v1.Session() as sess:
sess.run(init)
for epoch in range(max_epochs):
batch_xs, batch_ys = mnist.train.next_batch(batch_size)
sess.run(step, feed_dict={X_in: batch_xs, y: batch_ys})
if epoch % 1000 == 0:
acc_test = sess.run(accuracy, feed_dict={X_in: mnist.test.images, y: mnist.test.labels})
acc_train = sess.run(accuracy, feed_dict={X_in: mnist.train.images, y: mnist.train.labels})
print('Epoch:{0} Accuracy Train%:{1} Accuracy Test%:{2}'.format(epoch, acc_train / 600, (acc_test / 100)))