1
基本概念
BP神经网络是一种通过误差反向传播算法进行误差校正的多层前馈神经网络,其最核心的特点就是:信号是前向传播,而误差是反向传播。前向传播过程中,输入信号经由输入层、隐藏层逐层处理,到输出层时,如果结果未到达期望要求,则进入反向传播过程,将误差信号原路返回,修改各层权重。
2
BP神经网络结构
BP神经网络包含输入层、隐藏层和输出层,其中,隐藏层可有多个,其中,输入层和输出层的节点个数是固定的(分别是输入样本的变量个数和输出标签个数),但隐藏层的节点个数不固定。以具有单隐藏层的BP神经网络为例,其网络结构如下图:
3
BP神经网络原理公式
以单隐藏层的BP神经网络为例,各阶段原理公式如下:
4
python代码实现
这里,我们用手写数字图片建立一个仅有1层隐藏层的BP神经网络,并进行训练及预测。每张图片大小为8*8,因此有64个图片像素变量及1个偏置项,共65个输入层节点;训练目标是将手写图片判断为0-9,因此有10个输出层节点;隐藏层节点数这里设置为100。图片示例如下:
另外,这里两个激活函数我们都选用sigmoid函数,且这个函数都导数有一个特点,即f′(x)=f(x)(1−f(x))。
import numpy as np
from sklearn.datasets import load_digits
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split
def sigmoid(x):
return 1/(1+np.exp(-x))
def dsigmoid(x):
return x*(1-x)
class NeuralNetwork:
def __init__(self,layers):
#权值等初始化,范围-1到1
self.V = np.random.random((layers[0]+1,layers[1]+1))*2-1
self.W = np.random.random((layers[1]+1,layers[2]))*2-1
def train(self,X,y,lr=0.11,epochs=10000): # lr为学习率,X为训练集
#添加偏置
temp = np.ones([X.shape[0],X.shape[1]+1])#1为偏置
temp[:,0:-1] = X
X = temp
for n in range(epochs+1):
i = np.random.randint(X.shape[0]) #随机选取训练集中的一个数据
x = [X[i]]
x = np.atleast_2d(x)#转为二维数据
L1 = sigmoid(np.dot(x,self.V)) #隐藏层输出
L2 = sigmoid(np.dot(L1,self.W)) #输出层输出
L2_delta = (y[i]-L2)*dsigmoid(L2)
L1_delta = L2_delta.dot(self.W.T)
self.W += lr*L1.T.dot(L2_delta)
self.V += lr*x.T.dot(L1_delta)
#每训练1000次预测一次准确率
if n%1000==0:
predictions = []
for j in range(X_test.shape[0]):
o = self.predict(X_test[j])
predictions.append(np.argmax(o))#获取预测结果
accuracy = np.mean(np.equal(predictions,y_test))
print('epoch:',n,'accuracy:',accuracy)
def predict(self,x):
#添加偏置
temp = np.ones(x.shape[0]+1)
temp[0:-1] = x
x = temp
x = np.atleast_2d(x)#转为二维数据
L1 = sigmoid(np.dot(x,self.V)) #隐藏层输出
L2 = sigmoid(np.dot(L1,self.W)) #输出层输出
return L2
digits = load_digits()#载入数据
X = digits.data#数据
y = digits.target#标签
X -= X.min()
X /= X.max()
nm = NeuralNetwork([64,100,10])#创建网络
X_train,X_test,y_train,y_test = train_test_split(X,y) #默认3:1划分
labels_train = LabelBinarizer().fit_transform(y_train)#标签二值化
labels_test = LabelBinarizer().fit_transform(y_test)#标签二值化
print('start')
nm.train(X_train,labels_train,epochs=20000)
print('end')
输出结果如下,可以看到随着训练次数提升,模型准确率稳定在0.95、0.96。