二分类神经网络
初次接触到神经网络,在略知一二的情况下,初步实现了神经网络的目标二分类。
简单神经网络结构
神经网络一般分为输入层,隐藏层和输出层三层。具体结构网上随处可见,这里便不再赘述。直接上最基础的神经网络结构图。也是本次实现二分类的网络结构。
这个简单的神经网络由3个感知器搭建而成,其中一层输入层,一层隐藏层,一层输出层。
接下来说一说具体的传播方法。
前向传播
简单来说,前向传播就是将每一层的输入向量与其待定权值矩阵相乘,可以理解为每个输入与对应权值相乘后线性叠加作为输出。如上图结构中,前向传播可以表示为:
L1=W1X+W3Y+B1
L2=W2X+W4Y+B1
T=L1W5+L2W6+B2
这样看来,是不是就是简单的线性叠加呢,答案是肯定的。因此,如果面对非线性问题,这个网络就尴尬了。因此不得不引入一个东西----**函数。你可以理解为是将线性结构非线性化的一个过程。当然他可以将输出映射到0~1之间等的功能,这取决于不同的**函数。
本例使用的**函数:f(x)=1/1+e^(-x)
这样每一次感知器输出结果经过**后,在叠加,就变成非线性的咯。
将上式没行下增加**函数即可。例如L1`=1/1+E^(-L1)
如此,一次前向传播结束。
损失函数
理解为误差即可。在监督学习中,就是可以看作前向传播输出值和实际真实值之间的偏差。
最简单的为:E=(R-T)^2
其中R为真实值,T为输出值。就是方差啦。
当然他会有不少弊端。而在二分类中,常用的损失函数一般为交叉熵。
公式:E=-(RlnT+(1-R)ln(1-T))
具体推导可自行百度
反向传播
反向传播也就是网络的学习过程,将前向传播获得的损失值,计算在对应权值上的偏导值作为更新量。具体理论可以参看梯度下降法,是对这个的直观解释哦。
具体代码:
ww[0]=ww[0]-xxl*(z-tt)*w[4]l1(1-l1)x
ww[2]=ww[2]-xxl(z-tt)*w[4]l1(1-l1)y
ww[1]=ww[1]-xxl(z-tt)w[5]l2(1-l2)x
ww[3]=ww[3]-xxl(z-tt)w[5]l2(1-l2)y
bb[0]=bb[0]-xxl(z-tt)(w[4]l1(1-l1)+w[5]l2(1-l2))
ww[4]=ww[4]-xxl(z-tt)l1
ww[5]=ww[5]-xxl(z-tt)l2
bb[1]=bb[1]-xxl(z-tt)
就不敲公示了,上面是代码中反向传播的公式,其中xxl表示学习率(原谅我用拼音首字母),可以人为设置。(z-tt)为损失函数对应输出的偏导,可以自行验证。后面相乘量都是对应权值路径上的偏导计算值。
具体百度反向传播算法,基本很明确了。
上全部python代码
import matplotlib.pyplot as plt
import numpy as np
import math
x=y=l1=l2=z=e=0.0
w=np.random.random(6)
b=np.random.random(2)
def gofront(xx,yy):
x=xx
y=yy
l1=w[0]*x+w[2]*y+b[0]
l1=1/(1+math.exp(-l1))
l2=w[1]x+w[3]y+b[0]
l2=1/(1+math.exp(-l2))
z=l1w[4]+l2w[5]+b[1]
z=1/(1+math.exp(-z))
return x,y,l1,l2,z
def geterror(tt):
ee=-(tt*math.log(z)+(1-tt)*math.log(1-z))
return ee
def goback(tt):
ww=w
bb=b
ww[0]=ww[0]-xxl*(z-tt)*w[4]l1(1-l1)x
ww[2]=ww[2]-xxl(z-tt)*w[4]l1(1-l1)y
ww[1]=ww[1]-xxl(z-tt)w[5]l2(1-l2)x
ww[3]=ww[3]-xxl(z-tt)w[5]l2(1-l2)y
bb[0]=bb[0]-xxl(z-tt)(w[4]l1(1-l1)+w[5]l2(1-l2))
ww[4]=ww[4]-xxl(z-tt)l1
ww[5]=ww[5]-xxl(z-tt)l2
bb[1]=bb[1]-xxl(z-tt)
return ww,bb
xxl=0.3
x=np.random.uniform(-2,2,[20,2])
y1=np.array([6,7])
y2=np.array([0,4])
y3=np.array([3,0])
m1=x[0:8]+y1
m2=x[8:14]+y2
m3=x[14:20]+y3
m=np.vstack((m1,m2,m3))
print(m)
input()
t=np.array([0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1])
i=0
j=0
x,y,l1,l2,z=gofront(m[i][0],m[i][1])
print(z,l1,l2)
e=geterror(t[i])
while(e>=0.0015 or j<=5000):
j=j+1
w,b=goback(t[i])
i=i+1
if i>19:
i=0
x,y,l1,l2,z=gofront(m[i][0],m[i][1])
e=geterror(t[i])
print(e)
print("------------------")
i=-3
j=-3
while(i<10):
i=i+0.3
j=-3
while(j<10):
j=j+0.3
x,y,l1,l2,z=gofront(i,j)
if z>0.8:
plt.scatter(i,j,s=5,c=‘r’,marker=’.’)
elif z<0.2:
plt.scatter(i,j,s=5,c=‘g’,marker=’.’)
‘’’
for i in range(-4,11):
for j in range(-4,11):
x,y,l1,l2,z=gofront(i,j)
if z>0.5:
plt.scatter(i,j,c=‘r’)
else:
plt.scatter(i,j,c=‘g’)
‘’’
‘’’
for j in range(0,14):
x,y,l1,l2,z=gofront(m[j][0],m[j][1])
print(z)
‘’’
plt.scatter(m[0:8,0],m[0:8,1],c=‘b’)
plt.scatter(m[8:20,0],m[8:20,1],c=‘y’)
plt.show()
分类结果
从图中分类结果看,模型是比较成功的,损失函数值小于0.001,结果基本可靠。