企业级AI技术内幕:深度学习框架开发+机器学习案例实战+Alluxio解密
上QQ阅读APP看书,第一时间看更新

3.3 实现前向传播算法

数据输入已经完成,接下来在神经元节点中设置值,在隐藏层中进行前向传播计算。

如图3-13所示,输入层数据为x1x2,第一个隐藏层读取输入层的数据(例如隐藏层第1层的第一个神经元读取x1x2的数据),第二个隐藏层读取第一个隐藏层的数据……以此类推。注意,隐藏层参与计算的节点不能为偏爱因子节点,每层都要跳过偏爱因子节点(第一个节点),这与我们盘古框架有关。循环遍历隐藏层所有的节点,通过nodes[j].get_is_bias_unit()值为False来判断神经元节点是否为偏爱因子,同时神经元节点的层ID必须要大于0(输入层是第0层)。只有在这样的情况下,神经元节点才可能处于隐藏层,同时过滤掉了偏爱因子节点。

图3-13 层次大于0且神经元节点不为偏爱因子

ForwardPropagation.py的applyForwardPropagation的源代码如下:

如图3-14所示,如果要设置隐藏层第1层第1个神经元的值,与之关联的所有的权重的神经元节点是哪些?必须把当前处理的神经元节点记录下来。

图3-14 权重怎样关联神经元

读者如果读过PyTorch的源代码可能理解起来比较轻松。要获得目标神经元最快的方式是通过节点的ID。如图3-15所示,隐藏层第一层的第一个神经元,要找所有和它相关的权重,然后通过权重找到它所有的输入节点。它有2个连接权重,第0个权重连接x1和它本身,第1个权重连接x2和它本身,其中x1的ID是第0个权重的from_index,它本身的ID是第0个权重的to_index()。

图3-15 权重源节点、目标节点示意图

ForwardPropagation.py的applyForwardPropagation的源代码如下:

获取神经元节点的target_neuron_input值。

第10行代码:第一步,获取权重本身的值。

第19行代码:第二步,获取权重关联的来源节点的值。

第22行代码:计算上一个层次中所有和自己相关的神经元节点值和权重的乘积之和。

第24行代码:终止循环。一个权重是一条边,一条边连接2个节点,一旦找到了来源节点,没必要再循环其他的节点,一个权重只连接一个上一层的神经元,所以不需要继续循环整个神经网络的其他神经元。

如图3-16所示,对于隐藏层第一层第一个神经元,输入层x1节点和它的权重值是0.46,x1节点的值是0,将0乘以0.46;输入层x2节点和它的权重值是–0.034,x2节点的值是1,将1乘以–0.034;然后进行累加0×0.46+1×(–0.034),得到它的累加输入值(target_neuron_input)为–0.034。

ForwardPropagation.py的applyForwardPropagation的源代码如下:

图3-16 前向传播算法线性处理

这样就完成了一个非常重要的步骤,即前向传播算法中的线性处理部分。

在图3-17中还考虑了偏爱因子的因素,偏爱因子节点的值为–1。输入层的第一个节点的值是1,第二个节点的值是0,第三个节点的值是1,获取权重及来源的值,将它们相乘并进行累加,然后加上偏爱因子的值,线性变换的计算结果为(1×3+0×8+1×4)–1=6。激活函数采用简单的逻辑判断(>5),判断值为6,大于5,因此输出1。

图3-17 权重计算

回到ForwardPropagation.py代码,这里有个问题:如果找到了来源的神经元,并且获取了神经元的值,也知道权重的值,有没有必要循环下去,去查看其他的神经元?一个权重是可视化图中的一条边,一条边连接2个节点,一旦找到了来源节点,就没必要再循环其他的节点。因此在上述代码第12行中进行break。