我们以一个实验来说明整个流程,包括了数据生成,网络构建,网络训练,预测和最终验证。实验的要求如下:


一、实验计划

1.数据生成

采用np.random.multivariate_normal (mean, cov, size=None, check_valid=None, tol=None)方法,它用于生成多元正态分布矩阵。其中mean和cov为必要的传参而size,check_valid以及tol为可选参数。

2.网络结构定义,前向传播

网络采用3-3-4型BP网,即输入层为3,隐藏层为3,输出层为4,含偏置项,隐藏层激活函数采用ReLu,输出层采用softmax,loss函数J(W)采用均方差,如下所示,其中tk是实际标签,zk为网络估计的结果,c为样本的类别数。

3-3-4 BP网的结构如下图所示。由于输入为三维样本点,因此输入层为3;由于需要分为四类,因此输出层为4。中间隐藏层节点数和层数可随意组合,本实验设为3个。

前向传播较为简单,规则如下。xj是输入样本,wkj是权重矩阵,wk0是偏置值。

经过上式计算出输出后,经过激活函数得到如下结果。f为激活函数,本实验隐层采用ReLu,输出层采用softmax。

3.反向传播

该部分对于初学者是较难理解的部分,建议多花时间理解透彻,其实本质就是对loss函数求偏导,以达到降低loss就能优化网络的目的。偏导的求解过程读者可自行推导,对J(w)求导即可。最终得到权重的更新公式如下:

其中,wji是输入到隐藏层的权重,维度为3*3,wkj是隐藏层到输出的权重,维度为4*3。xi是输入样本,yj是隐藏层经过ReLu激活后的输出。det j和det k分别是隐层和输出层的敏感度。它们的定义如下,f'是softmax的偏导数。

4.预测

最后,经过softmax之后的输出,求其最大值所在的索引,将它作为预测的标签,具体规则是np.argmax(softmax(net k))。


二、实验过程

均方差的定义如下:

def mean_square(output, y):
    return np.sum((y - output) ** 2) / 2.0

softmax的定义如下:

def softmax(x):

    exps = np.exp(x - np.max(x))

    return exps / np.sum(exps)

ReLu函数的定义如下:

def ReLuFunc(x):

    x = (np.abs(x) + x) / 2.0

    return x

前向传播的定义如下:

# Hidden layer

for j in range(0, 3):

for i in range(0, 3):

net1[j] = net1[j] + w1[j][i] * x[i]

    net1[j] += bias1[j]

    fnet1 = ReLuFunc(net1)

     

# Output layer

for k in range(0, 4):

     for j in range(0, 3):

          net2[k] = net2[k] + w2[k][j] * fnet1[j]

     net2[k] += bias2[k]

 output = softmax(net2)

反向传播的定义如下:

# Back

det_k = np.zeros(4)

for k in range(0, 4):

     det_k[k] = (y[k] - output[k]) * (output[k] * (1 - output[k]))

det_j = np.zeros(3)

for j in range(0, 3):

     sum = 0

     for k in range(0, 4):

          sum = sum + w2[k][j] * det_k[k]

     if net1[j] >= 0:

          det_j[j] = sum

     else:

          det_j[j] = 0

               

# Update w and b

for j in range(0, 3):

    for i in range(0, 3):

        w1[j][i] = w1[j][i] + learning_rate * det_j[j] * x[i]

    bias1[j] = bias1[j] + learning_rate * det_j[j]

for k in range(0, 4):

     for j in range(0, 3):

         w2[k][j] = w2[k][j] + learning_rate * det_k[k] * fnet1[j]

     bias2[k] = bias2[k] + learning_rate * det_k[k]

准确率计算定义如下:

if np.argmax(output) == y:

    acc += 1


三、实验结果分析

1.数据生成

初始样本分布如图所示,可看到交叉较为严重,因此后面训练出来准确率也并不会太高,读者可自行调整u和sigma生成数据。

2.网络训练及测试集预测

学习率设为0.01,每隔2轮降低为原来的0.97倍,每轮遍历所有的训练样本,得到结果图3所示。其中,最浅色的虚线是测试集400个样本的准确率随训练轮数的变化,最后稳定在51%左右。

3.给定样本预测

(1)网络预测

我们对实验第3题给出的5个样本进行预测,通过网络得到的结果如下,分别属于0、3、0、0、0类,而后是估计的后验概率。

(2)理论计算

该部分采用贝叶斯函数进行估计,先验概率为0.25,似然函数采用多维高斯分布概率密度函数,其公式定义如下:

具体计算的函数定义如下:

u = np.asarray([[0, 0, 0],
               [0, 1, 0],
               [-1, 0, 1],
               [0, 0.5, 1]])
sigma = np.asarray([[[1, 0, 0], [0, 1, 0], [0, 0, 1]],
                   [[1, 0, 1], [0, 2, 2], [1, 2, 5]],
                   [[2, 0, 0], [0, 6, 0], [0, 0, 1]],
                   [[2, 0, 0], [0, 1, 0], [0, 0, 3]]])
p = np.zeros(4)
for i in range(0, 4):
    det = np.linalg.det(sigma[i])
    inv = np.linalg.inv(sigma[i])
    xu_ = np.transpose(x - u[i])
    xu = np.transpose(xu_)
    first = np.dot(xu_, inv)
    second = np.dot(first, xu)
    d = len(x)
    p[i] = 1.0/((2*np.pi)**(d/2.0)*np.sqrt(det))*np.exp(-second/2.0)
prob = max(p)/np.sum(p)

得到结果如下:

对比网络预测结果如下表所示。可见,对5个样本的预测,BP网计算的结果是是03000,而理论计算的结果是00000,只有第2个样本的结果不一致,其他均相符。

样本数据

先验概率

理论后验概率(最大值)

理论结果(最大值对应类别)

预测后验概率

预测结果

(0,0,0)

0.25

0.57

0

0.51

0

(-1,0,1)

0.25

0.38

0

0.39

3

(0.5,-0.5,0)

0.25

0.61

0

0.55

0

(-1,0,0)

0.25

0.55

0

0.53

0

(0,0,-1)

0.25

0.50

0

0.36

0

项目github开源地址:https://github.com/HuiyanWen/BP_Network ,如果有用,请您点个赞,谢谢~

 

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐