神经网络学习系列(一)前向神经网络和BP算法 附python代码(minst手写体识别)

最近刚开始接触神经网络,想把自己找到的一些好的文章和代码以及自己的一些理解整理一下,一方面和广大学者交流,一方面巩固自己对神经网络的理解,若大家有什么其他更好的见解,欢迎留言讨论

参考资料:吴岸城《神经网络与深度学习》

理论分析

前向神经网络

bp神经网络为什么要归为前馈网络 bp神经网络前向传播_深度学习

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