前言

  本篇主要介绍神经网络的基本结构、激活函数以及学习算法(BP算法)

  神经网络 主要由三个组成部分,第一个是架构(architecture)或称为拓扑结构(topology),描述神经元的层次与连接神经元的结构。第二个组成部分是神经网络使用的激励/激活函数。第三个组成部分是找出最优权重值的学习算法

  为了能够解决感知机人工设定权重的工作,即确定合适的、能符合预期的输入与输出的权重,神经网络便出现了,神经网络的一个重要的性质是它可以自动地从数据中学习得到合适的权重参数。

一、神经网络的结构

bp神经网络确定权重 bp神经网络计算权重_阶跃函数

  • 输入层 :通过输入层输入数据
  • 隐藏层 :通过隐藏的中间层对输入数据进行训练,训练过程中中间节点的真正数值无法通过训练集看到
  • 输出层 :输出模型的预测值

一般情况下,我们通常将输入层、隐藏层、输出层的总数减去1后的数量来表示神经网络的名称,上图即可称为两层神经网络

bp神经网络确定权重 bp神经网络计算权重_阶跃函数_02

  • 上图是一个三层神经网络

二、激活函数

bp神经网络确定权重 bp神经网络计算权重_激活函数_03

上面的激活函数 bp神经网络确定权重 bp神经网络计算权重_深度学习_04

  激活函数 的主要作用是提供网络的非线性建模能力。如果没有激活函数,那么该网络仅能够表达线性映射,此时即便有再多的隐藏层,其整个网络跟单层神经网络也是等价的。因此也可以认为,只有加入了激活函数之后,深度神经网络才具备了分层的非线性映射学习能力。 激活函数的主要特性是:可微性、单调性、输出值的范围

  • 常见的激活函数:Sign函数Sigmoid函数Tanh函数ReLU函数P-ReLU函数Leaky-ReLU函数ELU函数Maxout函数

1、sigmoid 函数

数学表达式为:
bp神经网络确定权重 bp神经网络计算权重_激活函数_05

python实现:

import numpy as np
import matplotlib.pylab as plt

def sigmoid(x):
    return 1 / (1 + np.exp(-x))

x = np.arange(-5.0, 5.0, 0.1)
y = sigmoid(x)
# 画图
plt.plot(x,y)
plt.ylim(-0.1, 1.1) # 指定y轴的范围
plt.show()

bp神经网络确定权重 bp神经网络计算权重_神经网络_06

2、阶跃函数

数学表达式:
bp神经网络确定权重 bp神经网络计算权重_bp神经网络确定权重_07

python实现:

# 方法一
def step_function1(x):
	if x > 0:
		return 1
	else:
		return 0
# 方法二		
def step_function2(x):
    return np.array(x>0, dtype=np.int)

x = np.arange(-5.0, 5.0, 0.1) # 在-0.5到0.5的范围内,以0.1为单位,生成NumPy数组([-5.0,-4.9,...,4.9])
y = step_function2(x)

plt.plot(x,y)
plt.ylim(-0.1, 1.1) # 指定y轴的范围
plt.show()

bp神经网络确定权重 bp神经网络计算权重_激活函数_08

3、阶跃函数与sigmoid函数的比较

  • “平滑性”不同,sigmoid 函数是一条平滑的曲线,而阶跃函数在0处有突变,输出发生急剧性变化,sigmoid函数的平滑性对神经网络的学习具有重要意义;
  • 返回值的不同,阶跃函数只能返回0和1,sigmoid函数可以返回0到1的任意数,这和平滑性有关,也就是说,感知机中神经元之间流动的是0和1的二元信号,而神经网络中流动的是连续的实值信号;
  • 二者也有共同性质,输入较小时,输出接近0(或为0),随着输入增大,输出向1靠近(或变成1),也就是说,当输入信号为重要信息时,两者都会输出较大的值,当输入信号不重要的时,两者都会输出较小的值;
  • 二者输出值都在0到1之前

4、ReLU 函数

数学表达式:
bp神经网络确定权重 bp神经网络计算权重_神经网络_09

python 实现:

def relu(x):
    return np.maximum(0,x)

x = np.arange(-5.0, 5.0, 0.1)
y = relu(x)

plt.plot(x,y)
plt.ylim(-0.1, 5) # 指定y轴的范围
plt.show()

bp神经网络确定权重 bp神经网络计算权重_神经网络_10

5、softmax函数

数学表达式为:
bp神经网络确定权重 bp神经网络计算权重_阶跃函数_11

其中,bp神经网络确定权重 bp神经网络计算权重_阶跃函数_12表示假设输出层共有n个神经元,计算第k个神经元的输出bp神经网络确定权重 bp神经网络计算权重_阶跃函数_12
分子是输入信号bp神经网络确定权重 bp神经网络计算权重_激活函数_14的指数函数,分母是所有输入信号的指数函数之和

python实现:

a = np.array([0.3, 2.9, 4.0])

exp_a = np.exp(a)

print(exp_a)
输出为:[ 1.34985881 18.17414537 54.59815003]
sum_exp_a = np.sum(exp_a)
print(sum_exp_a)

y = exp_a / sum_exp_a
print(y)
输出为:74.1221542101633
[0.01821127 0.24519181 0.73659691]
def softmax(a):
    exp_a = np.exp(a)
    sum_exp_a = np.sum(exp_a)
    y = exp_a / sum_exp_a
    
    return y

6、神经网络为何要使用非线性函数

如果使用线性函数,那么不管如何加深层数,总是存在与子等效的“无隐藏层神经网络”

  • 假如我们使用 bp神经网络确定权重 bp神经网络计算权重_阶跃函数_15 作为激活函数,使用三层神经网络对应 bp神经网络确定权重 bp神经网络计算权重_bp神经网络确定权重_16 运算,即 bp神经网络确定权重 bp神经网络计算权重_阶跃函数_17,我们取 bp神经网络确定权重 bp神经网络计算权重_bp神经网络确定权重_18

三、三层神经网络的简单实现

bp神经网络确定权重 bp神经网络计算权重_阶跃函数_19

图中,红色表示输入层到第一层的信号传递,蓝色表示第一层到第二层的信号传递,绿色表示第二层到输出层的信号传递

  • 其中bp神经网络确定权重 bp神经网络计算权重_激活函数_20表示输入,灰色实心圆表示偏置项,
  • bp神经网络确定权重 bp神经网络计算权重_激活函数_21中a表示后一层的第a个神经元,b表示前一层的第b个神经元,c表示第c层的权重
  • bp神经网络确定权重 bp神经网络计算权重_深度学习_22中c表示第c层的第d个输出,用于下一层的输入
  • bp神经网络确定权重 bp神经网络计算权重_神经网络_23表示最终输出

1、从输入层到第一层的信号传递

由图,可得到:

bp神经网络确定权重 bp神经网络计算权重_神经网络_24
bp神经网络确定权重 bp神经网络计算权重_深度学习_25也按此规律运算,写成矩阵的乘法运算可以表示为:
bp神经网络确定权重 bp神经网络计算权重_激活函数_26
其中,bp神经网络确定权重 bp神经网络计算权重_阶跃函数_27
bp神经网络确定权重 bp神经网络计算权重_深度学习_28

下面我们通过pythonNumPy 多维数组来实现以上步骤,这里将输入信号、权重、偏置设置成任意值。

X = np.array([1.0, 0.5])
W1 = np.array([
    [0.1, 0.3, 0.5],
    [0.2, 0.4, 0.6]
])
B1 = np.array([0.1, 0.2, 0.3])
A1 = np.dot(X, W1) + B1
Z1 = sigmoid(A1)   # 使用sigmoid函数转换

print(Z1)
输出为:[0.57444252 0.66818777 0.75026011]

2、从第一层到第二层的信号传递

W2 = np.array([
    [0.1, 0.4],
    [0.2, 0.5],
    [0.3, 0.6]
])
B2 = np.array([0.1, 0.2])
A2 = np.dot(Z1, W2) + B2
Z2 = sigmoid(A2)   # 使用sigmoid函数转换

print(Z2)
输出为:[0.62624937 0.7710107 ]

3、从第二层到输出层的信号传递

W3 = np.array([
    [0.1, 0.3],
    [0.2, 0.4]
])
B3 = np.array([0.1, 0.2])
A3 = np.dot(Z2, W3) + B3
# 第二层到输出层的信号传递使用的激活函数不是sigmoid函数,而是恒等函数
def identity_function(x):
    return x
Y = identity_function(A3)

print(Y)
输出为:[0.31682708 0.69627909]

4、代码整合

# 恒等函数
def identity_function(x):
    return x

# 进行权重和偏置的初始化,并保存到字典network中    
def init_network():
    network = {}
    network['W1'] = np.array([
                        [0.1, 0.3, 0.5],
                        [0.2, 0.4, 0.6]
                    ])
    network['b1'] = np.array([0.1, 0.2, 0.3])
    network['W2'] = np.array([
                        [0.1, 0.4],
                        [0.2, 0.5],
                        [0.3, 0.6]
                    ])
    network['b2'] = np.array([0.1, 0.2])
    network['W3'] = np.array([
                        [0.1, 0.3],
                        [0.2, 0.4]
                    ])
    network['b3'] = np.array([0.1, 0.2])
    
    return network

# 前向(从输入到输出的传递处理)
def forward(network, x):
    W1, W2, W3 = network['W1'], network['W2'], network['W3']
    b1, b2, b3 = network['b1'], network['b2'], network['b3']
    
    a1 = np.dot(x, W1) + b1
    z1 = sigmoid(a1)
    
    a2 = np.dot(z1, W2) + b2
    z2 = sigmoid(a2)
    
    a3 = np.dot(z2, W3) + b3
    y = identity_function(a3)
    
    return y

# 测试
network = init_network()
x = np.array([1.0, 0.5])
y = forward(network, x)
print(y)
输出为:[0.31682708 0.69627909]

5、输出层的设计

bp神经网络确定权重 bp神经网络计算权重_bp神经网络确定权重_29神经网络可以用在分类问题回归问题上,不过需要改变输出层的激活函数,一般而言,回归问题用恒等函数,分类问题用softmax函数

bp神经网络确定权重 bp神经网络计算权重_bp神经网络确定权重_29softmax函数,它的分子和分母都涉及指数运算,因为指数运算的值很容易变得非常大,这在计算机的运算上有一定的缺陷,即溢出问题。

因此可对 softmax函数 进行改进,表达式如下:
bp神经网络确定权重 bp神经网络计算权重_阶跃函数_31

这里的 bp神经网络确定权重 bp神经网络计算权重_神经网络_32 可以使用任何值,但是一般选择输入信号的最大值
分子、分母都乘上bp神经网络确定权重 bp神经网络计算权重_激活函数_33这个任意常数,值不变

不改进softmax函数

a = np.array([1010,1000,990])
print(np.exp(a) / np.sum(np.exp(a)))
输出为:array([nan, nan, nan])
很明显发生了溢出问题

通过减去最大值

c = np.max(a)
print(a - c)

print(np.exp(a-c) / np.sum(np.exp(a-c)))
输出为:array([  0, -10, -20])

array([9.99954600e-01, 4.53978686e-05, 2.06106005e-09])
def softmax(a):
    c = np.max(a)
    exp_a = np.exp(a - c)  # 溢出对策
    sum_exp_a = np.sum(exp_a)
    y = exp_a / sum_exp_a
    
    return y
    
a = np.array([0.3,2.9,4.0])
y = softmax(a)
print(y)   # 输出是0.0到1.0之间的实数

print(np.sum(y))  # 和为1
输出为:[0.01821127 0.24519181 0.73659691]
1.0

四、BP 算法

  BP算法便是神经网络的一种求解W的算法,分为信号“正向传播(FP)”求损失,“反向传播(BP)”回传误差;根据误差值修改每层的权重,继续迭代。上面我们将输入信号、权重、偏置设置成任意值,然后经过了FP过程,而神经网络的一个重要的性质是它可以自动地从数据中学习得到合适的权重参数,这便是“反向传播(BP)”的作用。

下面我们通过一个具体的例子来说明BP 算法的 FPBP过程:

bp神经网络确定权重 bp神经网络计算权重_阶跃函数_34


wb 的初始值:

  • bp神经网络确定权重 bp神经网络计算权重_阶跃函数_35
  • bp神经网络确定权重 bp神经网络计算权重_深度学习_36
  • 输出为:
  • bp神经网络确定权重 bp神经网络计算权重_神经网络_37
  • 假设隐层和输出层都使用 sigmoid 激活函数
  • 学习率 bp神经网络确定权重 bp神经网络计算权重_bp神经网络确定权重_38

1、FP过程

bp神经网络确定权重 bp神经网络计算权重_深度学习_39

bp神经网络确定权重 bp神经网络计算权重_阶跃函数_40

同理可以得到:

bp神经网络确定权重 bp神经网络计算权重_阶跃函数_41

bp神经网络确定权重 bp神经网络计算权重_bp神经网络确定权重_42

bp神经网络确定权重 bp神经网络计算权重_深度学习_43

bp神经网络确定权重 bp神经网络计算权重_深度学习_44

bp神经网络确定权重 bp神经网络计算权重_神经网络_45
同理可以得到:

bp神经网络确定权重 bp神经网络计算权重_激活函数_46

输出层误差表示如下:
bp神经网络确定权重 bp神经网络计算权重_阶跃函数_47

bp神经网络确定权重 bp神经网络计算权重_阶跃函数_48

bp神经网络确定权重 bp神经网络计算权重_神经网络_49

bp神经网络确定权重 bp神经网络计算权重_深度学习_50

2、BP 过程

输出层到第二层隐层,以求 bp神经网络确定权重 bp神经网络计算权重_神经网络_51

bp神经网络确定权重 bp神经网络计算权重_神经网络_52

下面我们分别求上式的三个部分,其中第一部分

bp神经网络确定权重 bp神经网络计算权重_激活函数_53

又因为:

bp神经网络确定权重 bp神经网络计算权重_神经网络_54

bp神经网络确定权重 bp神经网络计算权重_阶跃函数_55

第二分部:

bp神经网络确定权重 bp神经网络计算权重_阶跃函数_56

因为:
bp神经网络确定权重 bp神经网络计算权重_深度学习_57

第三部分:
bp神经网络确定权重 bp神经网络计算权重_阶跃函数_58

最终得到:
bp神经网络确定权重 bp神经网络计算权重_阶跃函数_59

更新bp神经网络确定权重 bp神经网络计算权重_激活函数_60的值:

bp神经网络确定权重 bp神经网络计算权重_bp神经网络确定权重_61

同理可以求出:

bp神经网络确定权重 bp神经网络计算权重_bp神经网络确定权重_62
bp神经网络确定权重 bp神经网络计算权重_阶跃函数_63
bp神经网络确定权重 bp神经网络计算权重_激活函数_64
bp神经网络确定权重 bp神经网络计算权重_阶跃函数_65
bp神经网络确定权重 bp神经网络计算权重_阶跃函数_66

第二层隐层到第一层隐层,以求 bp神经网络确定权重 bp神经网络计算权重_bp神经网络确定权重_67

bp神经网络确定权重 bp神经网络计算权重_深度学习_68

bp神经网络确定权重 bp神经网络计算权重_激活函数_69

下面我们分别计算,第一部分()内的

bp神经网络确定权重 bp神经网络计算权重_阶跃函数_70

其中:

bp神经网络确定权重 bp神经网络计算权重_深度学习_71

bp神经网络确定权重 bp神经网络计算权重_bp神经网络确定权重_72

bp神经网络确定权重 bp神经网络计算权重_深度学习_43

bp神经网络确定权重 bp神经网络计算权重_深度学习_74

注意:这里由于是反向传播,此时要用到之前更新后的bp神经网络确定权重 bp神经网络计算权重_神经网络_51的值

bp神经网络确定权重 bp神经网络计算权重_神经网络_76

bp神经网络确定权重 bp神经网络计算权重_bp神经网络确定权重_77

同理:
bp神经网络确定权重 bp神经网络计算权重_bp神经网络确定权重_78

第二部分:

bp神经网络确定权重 bp神经网络计算权重_bp神经网络确定权重_79

第三部分:

bp神经网络确定权重 bp神经网络计算权重_阶跃函数_80

最终:

bp神经网络确定权重 bp神经网络计算权重_阶跃函数_81

于是:
bp神经网络确定权重 bp神经网络计算权重_深度学习_82

同理求出:
bp神经网络确定权重 bp神经网络计算权重_深度学习_83

以上是第一次迭代,经过多次迭代,最终的误差会越来越小

bp神经网络确定权重 bp神经网络计算权重_激活函数_84

上图可以看出,当迭代1000次时,输出为 bp神经网络确定权重 bp神经网络计算权重_神经网络_85 和原本的 bp神经网络确定权重 bp神经网络计算权重_神经网络_86以及比较接近了。

五、上例 Python 代码实现

import numpy as np

# 初始值
w = [0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65]
# 偏置项b不进行更新
b = [0.35, 0.65]

l = [5, 10]

# sigmoid函数
def sigmoid(z):
    return 1.0 / (1 + np.exp(-z))


def f1(w, b, l):
    # 前向传播,计算结果值
    h1 = sigmoid(w[0] * l[0] + w[1] * l[1] + b[0])
    h2 = sigmoid(w[2] * l[0] + w[3] * l[1] + b[0])
    h3 = sigmoid(w[4] * l[0] + w[5] * l[1] + b[0])

    o1 = sigmoid(w[6] * h1 + w[8] * h2 + w[10] * h3 + b[1])
    o2 = sigmoid(w[7] * h1 + w[9] * h2 + w[11] * h3 + b[1])

    # 后向传播,更新w
    # 输出层到第二层隐层,前两项
    # 公式中的第一部分-(0.01 - o1),第二部分o1 * (l - o1)
    t1 = -(0.01 - o1) * o1 * (l - o1)
    # 第二层隐层到第一层隐层,前两项
    t2 = -(0.99 - o2) * o2 * (l - o2)
    # t1*第三部分,即输出层到第二层隐层的参数梯度
    w[6] = w[6] - 0.5 * (t1 * h1)
    w[8] = w[8] - 0.5 * (t1 * h2)
    w[10] = w[10] - 0.5 * (t1 * h3)
    w[7] = w[7] - 0.5 * (t2 * h1)
    w[9] = w[9] - 0.5 * (t2 * h2)
    w[11] = w[11] - 0.5 * (t2 * h3)

    # (t1 * w[6] + t2 * w[7])对于公式()中的两项,h1 * (1 - h1)对于第二项,l[0]对应第三项
    w[0] = w[0] - 0.5 * (t1 * w[6] + t2 * w[7]) * h1 * (1 - h1) * l[0]
    w[1] = w[1] - 0.5 * (t1 * w[6] + t2 * w[7]) * h1 * (1 - h1) * l[1]
    w[2] = w[2] - 0.5 * (t1 * w[8] + t2 * w[9]) * h2 * (1 - h2) * l[0]
    w[3] = w[3] - 0.5 * (t1 * w[6] + t2 * w[9]) * h2 * (1 - h2) * l[1]
    w[4] = w[4] - 0.5 * (t1 * w[10] + t2 * w[11]) * h3 * (1 - h3) * l[0]
    w[5] = w[5] - 0.5 * (t1 * w[10] + t2 * w[11]) * h3 * (1 - h3) * l[1]

    return o1, o2, w


for i in range(1000):
    r1, r2, w = f1(w, b, l)
    print("第{}次迭代后,结果值为:({},{}),权重更新为:{}".format(i+1, r1, r2, w))

运行结果:

第0次迭代,结果值为:(0.8910896614765176,0.9043299248500164),权重更新为:[0.09453429502265628, 0.13906859004531255, 0.1982111758493806, 0.2472699352051287, 0.29949648483800345, 0.34899296967600685, 0.3609680622498306, 0.4533833089635062, 0.4581364640581681, 0.5536287533891512, 0.5574476639638248, 0.653688458944847]
 …
 第1000次迭代,结果值为:(0.022971398121212325,0.9776750383779403),权重更新为:[0.21489448646234574, 0.3797889729246913, 0.26021215340481807, 0.3781845403360407, 0.3231871485490716, 0.3963742970981442, -1.4890558608085964, 0.9416395064631622, -1.5030558044874467, 1.0491054496597343, -1.4269056227390988, 1.151801999870186]

结果中标记的为第一次迭代 bp神经网络确定权重 bp神经网络计算权重_bp神经网络确定权重_67bp神经网络确定权重 bp神经网络计算权重_神经网络_51

六、使用BP神经网络对公路货运量预测

使用数据 traffic_data.csv

人口数,机动车数,公路面积,客运量,货运量
20.55,0.6,0.09,5126.0,1237.0
22.44,0.75,0.11,6217.0,1379.0
25.37,0.85,0.11,7730.0,1385.0
27.13,0.9,0.14,9145.0,1399.0
29.45,1.05,0.2,10460.0,1663.0
30.1,1.35,0.23,11387.0,1714.0
30.96,1.45,0.23,12353.0,1834.0
34.06,1.6,0.32,15750.0,4322.0
36.42,1.7,0.32,18304.0,8132.0
38.09,1.85,0.34,19836.0,8936.0
39.13,2.15,0.36,21024.0,11099.0
39.99,2.2,0.36,19490.0,11203.0
41.93,2.25,0.38,20433.0,10524.0
44.59,2.35,0.49,22598.0,11115.0
47.3,2.5,0.56,25107.0,13320.0
52.89,2.6,0.59,33442.0,16762.0
55.73,2.7,0.59,36836.0,18673.0
56.76,2.85,0.67,40548.0,20724.0
59.17,2.95,0.69,42927.0,20803.0
60.63,3.1,0.79,43462.0,21804.0

代码:

import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler

# 设置字符集,防止中文乱码
mpl.rcParams['font.sans-serif'] = [u'simHei']
mpl.rcParams['axes.unicode_minus'] = False

# 1. 读取数据
df = pd.read_csv('traffic_data.csv', encoding='utf-8')
# print(df.head())

# 2. 读取特征属性X
x = df[['人口数', '机动车数', '公路面积']]
y = df[['客运量', '货运量']]

# 3. 因为x和y的数据取值范围太大了,所以做一个归一化操作(使用区间缩放法)
x_scaler = MinMaxScaler(feature_range=(-1, 1))
y_scaler = MinMaxScaler(feature_range=(-1, 1))
x = x_scaler.fit_transform(x)
y = y_scaler.fit_transform(y)

# 为了后面和w进行矩阵的乘法操作
sample_in = x.T
sample_out = y.T

# 超参数
max_epochs = 60000
learn_rate = 0.035
mse_final = 6.5e-4
sample_number = x.shape[0]
input_number = 3
out_number = 2
hidden_unit_number = 8

# 网络参数
# 8*3的矩阵
w1 = 0.5 * np.random.rand(hidden_unit_number, input_number) - 0.1
# 8*1的矩阵
b1 = 0.5 * np.random.rand(hidden_unit_number, 1) - 0.1
# 2*8的矩阵
w2 = 0.5 * np.random.rand(out_number, hidden_unit_number) - 0.1
# 2*1的矩阵
b2 = 0.5 * np.random.rand(out_number, 1) - 0.1


def sigmoid(z):
    return 1.0 / (1 + np.exp(-z))


mse_history = []
# BP的计算
for i in range(max_epochs):
    # FP过程
    # 隐藏层的输出(8*20)
    hidden_out = sigmoid(np.dot(w1, sample_in) + b1)
    # 输出层的输出(为了简化我们的写法,输出层不进行sigmoid激活)(2*20)
    netword_out = np.dot(w2, hidden_out) + b2

    # 错误
    # 2*20
    err = sample_out - netword_out
    mse = np.average(np.square(err))
    mse_history.append(mse)
    if mse < mse_final:
        break

    # BP过程
    # delta2: 2*20
    delta2 = -err
    delta1 = np.dot(w2.transpose(), delta2) * hidden_out * (1 - hidden_out)
    dw2 = np.dot(delta2, hidden_out.transpose())
    db2 = np.dot(delta2, np.ones((sample_number, 1)))
    dw1 = np.dot(delta1, sample_in.transpose())
    db1 = np.dot(delta1, np.ones((sample_number, 1)))
    # w2: 2*8的矩阵, 那也就是要求dw2必须是2*8的一个矩阵
    w2 -= learn_rate * dw2
    b2 -= learn_rate * db2
    w1 -= learn_rate * dw1
    b1 -= learn_rate * db1

# 误差曲线图
mse_history10 = np.log10(mse_history)
min_mse = min(mse_history10)
plt.plot(mse_history10)
plt.plot([0, len(mse_history10)], [min_mse, min_mse])
ax = plt.gca()
ax.set_yticks([-2, -1, 0, 1, 2, min_mse])
ax.set_xlabel('iteration')
ax.set_ylabel('MSE')
ax.set_title('Log10 MSE History')
plt.show()

# 仿真输出和实际输出对比图
# 隐藏层输出
hidden_out = sigmoid((np.dot(w1, sample_in) + b1))
# 输出层输出
network_out = np.dot(w2, hidden_out) + b2
# 反转获取实际值
network_out = y_scaler.inverse_transform(network_out.T)
sample_out = y_scaler.inverse_transform(y)

fig, axes = plt.subplots(nrows=2, ncols=1, figsize=(12, 10))
line1, = axes[0].plot(network_out[:, 0], 'k', marker='o')
line2, = axes[0].plot(sample_out[:, 0], 'r', markeredgecolor='b', marker='*', markersize=9)
axes[0].legend((line1, line2), ('预测值', '实际值'), loc='upper left')
axes[0].set_title('客流模拟')
line3, = axes[1].plot(network_out[:, 1], 'k', marker='o')
line4, = axes[1].plot(sample_out[:, 1], 'r', markeredgecolor='b', marker='*', markersize=9)
axes[1].legend((line3, line4), ('预测值', '实际值'), loc='upper left')
axes[1].set_title('货流模拟')
plt.show()

运行结果:

bp神经网络确定权重 bp神经网络计算权重_神经网络_89

因为程序中 mse_history10 = np.log10(mse_history) 对MSE取了log10对数,所以会有负数的

bp神经网络确定权重 bp神经网络计算权重_bp神经网络确定权重_90