深度学习之BP神经网络3
1.原理
1.1多层网络
输入层多个输入节点分别以不同的权重输入到隐藏层之中,汇合后的数值再通过隐藏层或者输出到输出层,可以有多个不同的激活函数。
1.2BP网络模型
下图为一个三层的BP神经网络,X为输入层的输入向量,V是输入层输出到隐藏层的权值,Y为隐藏层的输出向量,W为隐藏层输出到输出层的权值,O为最后输出层的输出。
对于输出层,f代表激活函数,netk
是隐藏层的输出乘以各自的权值W后相加,O是将netk
通过激活函数后得到的。
对于隐藏层,f代表激活函数,netj
是输入层的输入值分别乘以各自的权值V后相加,Yj
是将netj
通过激活函数后得到的。
对于整个BP网络,激活函数采用单极性Sigmoid函数(y=1/(1+e^(-x)))或者双极性Sigmoid函数(y=(1-e^(-x))/(1+e^(-x)))。
1.3BP学习算法
定义误差E=0.5*(期望输出-实际输出)^2,下面还有将定义误差的公式展开到隐藏层和输入层。
和上一篇博文一样,使用梯度下降法,使权值的调整量与误差梯度下降成正比,在前面已经解释过了。
1.4BP算法推导
2.应用
2.1问题
异或问题,即0 0=0,0 1=1,1 0=1,1 1=0,我们需要用线性神经网络做一个分类。
2.2思路
输入层设置x0
,x1
,x2
;隐藏层设置y0
,y1
,y2
,y3
;输出层设置o0
,o1
;输入层到隐藏层的权值设置为V00
,V01
,V02
,V03
,V10
,V11
…等十二个权值,隐藏层到输出层的权值设置为W0
,W1
,W2
,W3
。
y0
=x0
V00
+x1
V10
+x2
V20
;
y1
=x0
V01
+x1
V11
+x2
V21
;
…
[x0
x1
x2
]*
[
V
‘
00
‘
V
‘
01
‘
V
‘
02
‘
V
‘
03
‘
V
‘
10
‘
V
‘
11
‘
V
‘
12
‘
V
‘
13
‘
V
‘
20
‘
V
‘
21
‘
V
‘
22
‘
V
‘
23
‘
]
\left[ \begin{matrix}V`00` & V`01` & V`02` & V`03`\\ V`10` & V`11` & V`12` & V`13` \\ V`20` & V`21` & V`22` & V`23` \end{matrix} \right]
⎣⎡V‘00‘V‘10‘V‘20‘V‘01‘V‘11‘V‘21‘V‘02‘V‘12‘V‘22‘V‘03‘V‘13‘V‘23‘⎦⎤=(y0
y1
y2
y3
)
O=y0
w0
+y1
w1
+y2
w2
+y3
w3
;
[y0
y1
y2
y3
]*
[
w
‘
0
‘
w
‘
1
‘
w
‘
2
‘
w
‘
3
‘
]
\left[ \begin{matrix}w`0` \\ w`1` \\ w`2` \\w`3` \end{matrix} \right]
⎣⎢⎢⎡w‘0‘w‘1‘w‘2‘w‘3‘⎦⎥⎥⎤=O
2.3代码
\\引入库
import numpy as np
import matplotlib.pyplot as plt
\\输入数据
X=np.array([[1,0,0],
[1,0,1],
[1,1,0],
[1,1,1]])
\\标签
Y=np.array([[0,1,1,0]])
\\权值初始化,-1到1
V=np.random.random((3,4))*2-1
W=np.random.random((4,1))*2-1
print(V)
print(W)
\\设置学习率
Lr=0.11
\\定义Sigmoid函数
def sigmoid(x):
return 1/(1+np.exp(-x))
\\定义dSigmoid函数
def dsigmoid(x):
return x*(1-x)
\\定义更新迭代函数
def update():
global X,Y,W,V,Lr,n
L1=sigmoid(np.dot(X,V))
L2=sigmoid(np.dot(L1,W))
L2_delta=(Y.T-L2)*dsigmoid(L2)
L1_delta=L2_delta.dot(W.T)*dsigmoid(L1)
W_C=Lr*L1.T.dot(L2_delta)
V_C=Lr*X.T.dot(L1_delta)
W += W_C
V += V_C
\\定义迭代次数
for i in range(10000):
update()
if i%500==0:
L1=sigmoid(np.dot(X,V))
L2=sigmoid(np.dot(L1,W))
print('Error:',np.mean(np.abs(Y.T-L2)))
L1=sigmoid(np.dot(X,V))
L2=sigmoid(np.dot(L1,W))
print(L2)
2.4结果
2.5问题
对数字进行分类。
2.6代码
\\引入库
from sklearn.datasets import load_digits
import pylab as pl
import numpy as np
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split
\\定义Sigmoid函数
def sigmoid(x):
return 1/(1+np.exp(-x))
\\定义dSigmoid函数
def dsigmoid(x):
return x*(1-x)
\\定义神经网络的类
class NeuralNetwork:
\\初始化
def __init__(self,layers):#(64,100,10)
\\权值的初始化
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.07,epochs=10000):
\\添加偏置
temp=np.ones([X.shape[0],X.shape[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)#转换为2维数据
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)*dsigmoid(L1)
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#数据
print(X.shape)
y=digits.target#标签
\\数据归一化
X -= X.min()
X /=X.max()
\\创建网络
nm=NeuralNetwork([64,100,10])
\\默认1/4为测试数据,3/4为训练数据
X_train,X_test,y_train,y_test=train_test_split(X,y)
\\标签二值化
labels_train=LabelBinarizer().fit_transform(y_train)
labels_test=LabelBinarizer().fit_transform(y_test)
print('start')
nm.train(X_train,labels_train,epochs=100000)
print('end')
2.7结果