在经历了漫长的代码推导之后,我们对反向传播(BP)算法总算有了更具体的认知。不过仍有一些关键细节尚未透彻解析——例如,为什么必须引入激活函数?随机梯度下降(SGD)为何如此重要?接下来,我们将逐一揭开这些疑问。
首先探讨激活函数存在的必要性。这需要回溯到学习BP之前接触过的感知器模型。感知器模拟了人体内部信号传递的过程:当信号累积达到一定阈值时,就会继续向后传播。

那么感知器模型与BP神经网络之间究竟有何关联?平时看到的BP网络结构图实际上是一个简化版本。下面这张图能更清晰地展示其逻辑:

至此就很明确了:BP神经网络本质上是由一个个感知器逐层堆叠而成的真正神经网络。激活函数的作用也随之明了——如果没有它,层与层之间的映射将只是线性变换,无论网络有多深,都无法表达复杂的非线性模式。

接下来看看使用TensorFlow实现BP神经网络有多么简洁:
# 构建一个结构为[10,15,1]的BP神经网络
model = tf.keras.Sequential([
tf.keras.layers.Dense(15, activation='relu', input_shape=(10,)),
tf.keras.layers.Dense(1)
])
model.summary() # 显示网络结构
model.compile(optimizer='SGD', loss='mse') # 定义优化方法为随机梯度下降,损失函数为均方误差
# x->训练集, y->标签, epochs=10000, validation_data=(test_x, test_y)
history = model.fit(x, y, epochs=10000, validation_data=(test_x, test_y))
上面展示的就是最基础的BP网络结构。过去需要手写上百行代码才能完成的功能,如今仅用寥寥几行即可实现。
这里对validation_data(验证集)做一个解释:它的作用与测试集类似,但区别在于它在训练过程中实时对模型进行测试,便于我们随时观察模型的准确率。loss函数用于计算预测误差,以此衡量模型的精度,常用的误差函数还包括mse、mae、rmse、mape等。框架内置了多种误差函数,如果默认函数无法满足需求,也可以自行定义。SGD指的是随机梯度下降算法。不过目前业界普遍认为"adam"是综合表现最出色的优化算法,当然具体选择还需根据神经网络的类型而定。想深入研究理论的朋友可以查阅相关资料,作为实战派,这里不对理论做过多的展开。
再列举另一个同样强大的PyTorch框架代码,大家可以根据自己的开发习惯自行选择:
class Model(nn.Module):
def __init__(self):
super().__init__()
self.fc = nn.Sequential(
nn.Linear(10, 15),
nn.ReLU(),
nn.Dropout(), # 防止过拟合,TensorFlow也有类似的机制
nn.Linear(15, 2)
)
def forward(self, x):
x = self.fc(x)
return x
至于在TensorFlow与PyTorch之间如何抉择——在TensorFlow 2.0正式发布之前,更多人可能倾向于PyTorch。但现在TensorFlow 2.0的代码风格已经与PyTorch非常接近,而且支持的平台更为广泛,因此这里更推荐使用TensorFlow 2.0。
如果大家有任何疑问,欢迎留言交流讨论。
