首页
学习
活动
专区
工具
TVP
发布

使用矩阵运算驱动神经网络数据加工链

对于学过线性代数的人来说,矩阵运算绝对算得上是一场噩梦。特别是做矩阵乘法时,两个大方块,每个方块里面有好多数字,你需要把一个方块中一行里的所有数字跟另一个方块里面的所有数字做乘法,然后再求和,头昏脑涨的算了半天才得到新矩阵的一个数值,忙活了半天,耗费了大量精力后,你发现居然算错了,只能再来一遍,那时候我想你恨不得一把火把代数课本付之一炬。

上一节,我们手动计算了一个只有两层,每层只有两个节点的神经网络,那时候的手动计算已经让我们精疲力尽了,试想一下任何能在现实中发挥实用效果的神经网络,例如用于人脸识别的网络,往往都是几百几千层,每层至少几百几千个节点,这种大规模网络,你要想想上一节一样用笔和纸去算,那可是不可想象的。

为了处理这种不可想象的繁重之极的计算任务,恶习的矩阵就能派上用场。矩阵在两方面能简化神经网络的数据运算,一方面各种运算压缩在一种简单的数学格式中,使用同一的矩阵运算法则就能流水线般的自动化执行各种运算,这种特性特别适合用计算机去实现,其二是很多编程语言对矩阵运算有非常好的支持,我们当下使用的Python就是,它对矩阵运算的支持就犹如对简单的数字进行加减乘除一样方便。因此依靠矩阵,我们就能找到一种简单有效而又快速的方式完成神经网络庞杂的数据运算。

矩阵其实就是我们前面提到过的二维张量,它的运算在前面章节详细说过,这里我们再次回顾一下。在神经网络的运算中,我们最常使用的就是矩阵乘法,如下图:

两个矩阵相乘需要满足的条件是,左边矩阵的列数必须等于右边矩阵的行数,相乘时,把左边矩阵第i行所有元素,分别与右边矩阵第j列里每个元素做乘法,然后再依次相加,所得结果就是新矩阵第i行第j列的元素。

回到上一节神经网络的例子,我们看看矩阵运算如何运用。

网络中第一层的两个节点分别把信号传送给第二层的两个节点,信号传送时需要经过权重的乘机运算,上图中总共有四个权重,我们可以把四个权重组成一个两行两列的矩阵,第一层又接收两个输入信号,这两个信号可以形成一个两行一列的矩阵,于是第二层两个节点所接收到的信号值可以通过下面的矩阵运算获得:

第一层第一个节点接收到信号值1.0后,根据权重,把信号分解成两部分,第一部分是1.0 * 0.9 = 0.9 传递给第二层节点1,第一层第二个节点接收信号值0.5,根据权重,把0.5 * 0.3 = 0.15 传递给第二层节点1,于是第二层节点1接收到的信号总量就是:

1.0 * 0.9 + 0.5 * 0.3 = 1.05

根据图示,input_1 = 1.0, W(1,1) = 0.9, input_2 = 0.5, W(2,1) = 0.3, 转换一下,第二层第一个节点所接收到的信号值就是:

input_1 * W(1,1) + input_2 * W(2,1)

这个结果正好与前面矩阵运算等候右边矩阵的第一行第一列一致,同理第二层第二个节点接收到的信号量等于右边矩阵的第二行第二列对应的值。如此一来,通过一次矩阵乘法运算,我们就可以得到第二层节点接收的信号量了。由此,依靠矩阵,我们就能从数学上简明的去描述信号的传递和处理过程,我们用符号 X 表示当前一层神经元节点要接收的信号量,用 W 对应上一层节点相对于当层节点的权重,用 I 表示上一层神经元接收的信号量,于是便有:

注意,我们这里用到的符号都是大写,这样用于区别符号对应的是矩阵,也就是一维或二维张量而不是简单的一个数字。上面的矩阵乘法也成为点乘,python 对矩阵点乘及相关运算提供了很好的支持,这就是为何python被广泛的应用与人工智能应用的开发,我们把前面的运算转换为如下代码:

上面代码运行后结果为:

由于python对矩阵运算的良好支持,使得代码的编写很简单省事。着意味着不管一个神经网络有多少层,每层有多少个节点,其对应的也就是矩阵的大小而已,用python实现,只要用几个for循环把相应矩阵里面的数值填上,矩阵的点乘及相关运算全部交给编译器来帮我们完成,我们可以把精力全部集中在算法和逻辑的设计之上。

依靠矩阵运算,我们可以得到每层神经元节点所要接收的信号量,也就是上面式子中的X,接着我们将X中每个值输入激活函数,就能得到该层神经元输出给下一层的信号量:

注意到上面等式中的O是大写,也就是它是一个向量而不是单个数值。根据当前掌握的理论,我看看如何计算一个三层,每层含有三个神经元的网络。该网络的结构图如下:

这里我们顺便引入几个术语,第一层我们称之为输入层,最后一层,我们称之为输出层。中间一层,我们诚挚为隐藏层。根据前面的讲解,我们不难理解,向量I的值为:[0.9, 0.1, 0.8],也就是:

第一层神经元的职责很简单,它就是接收输入信号,然后把信后分解后传递到下一层。隐藏层的神经元就要麻烦一点,他需要把上一层传过来的信号整合起来,要注意隐藏层每个神经元与输入层的每个神经元都有连接,所以隐藏层的神经元所获得的信号量都分别来自输入层的三个神经元。我们把输入层神经元传递给隐藏层神经元间对应的权重转换成矩阵如下:

我们通过矩阵的列来解读其中的含义,第一列的值为[0.9, 0.2, 0.1]它表示输入层第一个神经元将输入信号的0.9传给第二层第一个神经元,把输入信号的0.2传给第二层第二个神经元,把输入信号的0.1传给第二层第三个神经元。第二列和第三列数值的含义依次类推。在前面的结构图中并没有显示第一层第一个神经元与第二层第三个神经元之间的信号传递权重,但从上面矩阵可以看出,这个权重的值就是0.1。我们注意到,上面矩阵符号W右下角有”input_hidden”标注,它表示输入层与隐藏层神经元间的信号传递权重矩阵,对应的我们可以得到隐藏层和输出层神经元间信号传递权重矩阵如下:

根据前面描述的公式: X = W * I,我们可根据矩阵运算得到隐藏层每个神经元应当接收的信号量:

根据上面计算,我们得知,隐藏层第一个神经元将接收的信号量为1.16,第二个神经元将接收的信号量为0.42,第三个神经元将接收的信号量为0.62.我们在后续章节中将详细讲解如何使用Python编写相关计算代码。第二层的输入信号量确定后,我们就可以使用激活函数,计算第二层输出给第三层的信号量:

回忆一下,激活函数是 sigmoid(x) = 1 / (1 + exp(-x));我们把X中的每个值分别代入激活函数,例如把1.16代入激活函数,得到的输出结果为 sigmoid(1.16) = 0.761,以此类推最后算的隐藏层输出信号量为:

隐藏层神经元传出信号量后,输出层的神经元会接收过来并进行相应计算后再输出。同理隐藏层每个神经元都会把一部分信号量传递给输出层的每个神经元,隐藏层和输出层的交互过程跟输入层与隐藏层的交互过程完全是一模一样的。于是我们完全可以依据前面的做法,再次运算输出层神经元接收到的信号量,假设隐藏层和输出层神经元间的权重矩阵如下:

于是对应的计算过程如下:

也就是说,输出层神经元接收到的信号量为0.975,0.888,1.254.对应的结构图如下:

我们再次对输出层神经元接收到的信号量进行激活函数的运算,得到结果如下:

经过一系列的信号传递和计算,在输出层得到了最终结果:

得到最终结果后,我们接下来该做什么呢?通过前几节我们得知,我们要把计算结果与给定的正确结果比较,得出偏差,根据偏差去调整模型的参数,以便让下次计算你的结果与给定正确结果间的偏差越来越小,进而改进模型对数据进行预测的精确度,在下一节我们将详细解读,对于神经网络而言,如何通过输出结果计算偏差,并反过来改进神经网络中的权重参数,从而提升神经网络对数据的计算精确度。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180302G0J9KG00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券