神经网络学习系列(一)前向神经网络和BP算法 附python代码(minst手写体识别)
最近刚开始接触神经网络,想把自己找到的一些好的文章和代码以及自己的一些理解整理一下,一方面和广大学者交流,一方面巩固自己对神经网络的理解,若大家有什么其他更好的见解,欢迎留言讨论
参考资料:吴岸城《神经网络与深度学习》
理论分析
前向神经网络
BP算法
BP全称是 Back Propagation, 也称为Error Back Propagation, 意思是误差的反向传播 ,也算说明了BP算法的特点。
BP算法的基本思想是:由信号正向传播和误差反向传播。
注意:BP算法是在前向网络中误差的反向传递,跟反馈网络有本质的区别!!!!
(1)信号正向传播:正向传播时,输入样本从输入层传入,经各隐含层逐层处理后,传向输出层。若输出层的实际输出与期望的输出不符合,则转向误差的反向传播阶段。
(2)误差反向传播:将输出以某种形式通过隐含层向输入层反传,并将误差分摊给各层的所有单元,从而获得各层单元的误差信号,此误差信号即作为修正各单元权值的依据。
更详细的关于BP算法,请看
大白话讲解BP算法
实战代码
下面是小编找到的一个用BP算法实现minst手写体识别的基于tensorflow的代码
附链接:
链接: link.
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import numpy as np
mnist = input_data.read_data_sets("/tmp/data/", one_hot=True)
num_classes = 10 # 输出大小
input_size = 784 # 输入大小
hidden_units_size = 30 # 隐藏层节点数量
batch_size = 100
training_iterations = 10000
X = tf.placeholder(tf.float32, shape=[None, input_size])
Y = tf.placeholder(tf.float32, shape=[None, num_classes])
W1 = tf.Variable(tf.random_normal([input_size, hidden_units_size], stddev=0.1))
B1 = tf.Variable(tf.constant(0.1), [hidden_units_size])
W2 = tf.Variable(tf.random_normal([hidden_units_size, num_classes], stddev=0.1))
B2 = tf.Variable(tf.constant(0.1), [num_classes])
hidden_opt = tf.matmul(X, W1) + B1 # 输入层到隐藏层正向传播
hidden_opt = tf.nn.relu(hidden_opt) # 激活函数,用于计算节点输出值
final_opt = tf.matmul(hidden_opt, W2) + B2 # 隐藏层到输出层正向传播
# 对输出层计算交叉熵损失
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=Y, logits=final_opt))
# 梯度下降算法,这里使用了反向传播算法用于修改权重,减小损失
opt = tf.train.GradientDescentOptimizer(0.05).minimize(loss)
# 初始化变量
init = tf.global_variables_initializer()
# 计算准确率
correct_prediction = tf.equal(tf.argmax(Y, 1), tf.argmax(final_opt, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, 'float'))
sess = tf.Session()
sess.run(init)
for i in range(training_iterations):
batch = mnist.train.next_batch(batch_size)
batch_input = batch[0]
batch_labels = batch[1]
# 训练
training_loss = sess.run([opt, loss], feed_dict={X: batch_input, Y: batch_labels})
if i % 1000 == 0:
train_accuracy = accuracy.eval(session=sess, feed_dict={X: batch_input, Y: batch_labels})
print("step : %d, training accuracy = %g " % (i, train_accuracy))
这是小编习惯的基于tensorflow的代码编写方式
定义好输入层、隐含层、输出层的神经元个数以及批量处理大小、输入
输出形参(占位)
num_classes = 10 # 输出大小
input_size = 784 # 输入大小
hidden_units_size = 30 # 隐藏层节点数量
batch_size = 100
training_iterations = 10000
X = tf.placeholder(tf.float32, shape=[None, input_size])
Y = tf.placeholder(tf.float32, shape=[None, num_classes])
各层权值和偏置
W1 = tf.Variable(tf.random_normal([input_size, hidden_units_size], stddev=0.1))
B1 = tf.Variable(tf.constant(0.1), [hidden_units_size])
W2 = tf.Variable(tf.random_normal([hidden_units_size, num_classes], stddev=0.1))
B2 = tf.Variable(tf.constant(0.1), [num_classes])
计算隐含层(通过激活函数)和输出层输出值
hidden_opt = tf.matmul(X, W1) + B1 # 输入层到隐藏层正向传播
hidden_opt = tf.nn.relu(hidden_opt) # 激活函数,用于计算节点输出值
final_opt = tf.matmul(hidden_opt, W2) + B2 # 隐藏层到输出层正向传播
BP算法的优化一般都是这两步
# 对输出层计算交叉熵损失
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=Y, logits=final_opt))
# 梯度下降算法,这里使用了反向传播算法用于修改权重,减小损失
opt = tf.train.GradientDescentOptimizer(0.05).minimize(loss)
初始化变量的语句
计算准确率(在minst手写体识别中均可)
# 初始化变量
init = tf.global_variables_initializer()
# 计算准确率
correct_prediction = tf.equal(tf.argmax(Y, 1), tf.argmax(final_opt, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, 'float'))
前面两句运行必须
后面为训练过程
sess = tf.Session()
sess.run(init)
for i in range(training_iterations):
batch = mnist.train.next_batch(batch_size)
batch_input = batch[0]
batch_labels = batch[1]
# 训练
training_loss = sess.run([opt, loss], feed_dict={X: batch_input, Y: batch_labels})
if i % 1000 == 0:
train_accuracy = accuracy.eval(session=sess, feed_dict={X: batch_input, Y: batch_labels})
print("step : %d, training accuracy = %g " % (i, train_accuracy))