您的位置  > 互联网

基于numpy的《矩阵分析》,最开始我把自己代数时候的数学书

作为一个科学计算库,numpy 不包括计算图、尝试学习、梯度等函数,但我们可以简单地使用 numpy 来拟合第 2 层网络。

解决的问题:

生成一组随机的输入数据和一组输出数据。根据输入数据定义向前传播的神经网络结构及其参数,根据误差找到误差反向传播梯度,更新神经元各节点的参数

代码如下:

# -*- coding: utf-8 -*-
import numpy as np
# N is batch size; D_in is input dimension;
# H is hidden dimension; D_out is output dimension.
N, D_in, H, D_out = 64, 1000, 100, 10
# Create random input and output data
x = np.random.randn(N, D_in)
y = np.random.randn(N, D_out)
# Randomly initialize weights
w1 = np.random.randn(D_in, H)
w2 = np.random.randn(H, D_out)
learning_rate = 1e-6
for t in range(500):
    # Forward pass: compute predicted y
    h = x.dot(w1)
    h_relu = np.maximum(h, 0)
    y_pred = h_relu.dot(w2)
    # Compute and print loss
    loss = np.square(y_pred - y).sum()
    print(t, loss)
    # Backprop to compute gradients of w1 and w2 with respect to loss
    grad_y_pred = 2.0 * (y_pred - y)
    grad_w2 = h_relu.T.dot(grad_y_pred)
    grad_h_relu = grad_y_pred.dot(w2.T)
    grad_h = grad_h_relu.copy()
    grad_h[h < 0] = 0
    grad_w1 = x.T.dot(grad_h)
    # Update weights
    w1 -= learning_rate * grad_w1
    w2 -= learning_rate * grad_w2

 

原文见:

3 网络结构

绘制上述代码结构和相应的参数维度,如下所示:

然后,代码使用大小为 64 的批处理,因此输入值的实际大小实际上是 (64,1000)。

将上面的代码转换为数学公式,如下所示,括号内为相应矩阵的形状:

4 远期计算

数据流的正向传播

最后,计算损失函数损失,即实际预测值和先验数据矩阵的二元范数,作为两组矩阵的距离度量。

正向传播比较简单,基本上大学里线性代数的基础知识,看几章就能很好地理解。这也是在深度学习框架下设计网络时的后续,在关注神经元大小时,需要考虑矩阵乘法的可行性,即维度兼容性。

PS:关于矩阵范数的定义,参见P32的《1.4.3矩阵的内积和范数》。

5 反向传播

5.1 实现代码

下面是反射传播的代码实现:

5.2 数学基础

反射传播的数学原理可能没那么容易理解,因为它需要使用矩阵的高级算法,而一般的理工数学《线性代数》甚至《高等代数》都没有提到相关内容,所以基本上超出了大多数大学生的知识范围。这个时候,是时候牺牲张仙达的《矩阵分析》了。

起初,我翻阅了我的大学数学书籍“数学分析”、“高等代数”和“数值计算”,但我找不到任何相关内容。我觉得矩阵的微分是一个“三不相容”的区域,但这个内容是深度学习神经网络中最常用的数学原理。然后我上网找到了《矩阵分析与应用》,想着这么厚的一本百科全书般的书,应该包罗万象,果然,我在里面找到了我想要的内容。

当然,在看这本书之前,我也看了无数的网文,下面两篇比较有价值:

矩阵推导-I/p/

矩阵推导-下: /p/

当然,对于数学工具这样的内容,建议你还是看一读,因为这本书是几十年来的经典教科书,它的推导过程、内容的完整性、认证的严谨性都经得起推敲。网上文章只能帮你启发和学习几个术语,但如果你想更深入地了解细节,建议你阅读这本书。

开门见山。

上面提到的不到10行的反向传播梯度,更新参数的代码,在外行人看来有点天才,完全混乱,这是很正常的。因为为了理解上面的代码,需要提前储备以下知识(“矩阵分析与应用”):

矩阵上的基本操作。第 4 页,第 1.1.2 章 矩阵的内积和范数。P32, 1.4.3 矩阵的迹线。P49, 1.6.4 矢量化和矩阵化。第 74 页,1。矩阵和梯度矩阵。P143, 3.1 一阶实矩阵的微分和矩阵辨识.第152页,3.2

注意:函数有不同的分类,所以请不要从“线性代数”中的变量都是实标量的角度来看矩阵变量和矩阵函数的运算。因为它们是不同的,即使你勉强得出代码合适的结论,它很可能是“瞎猫遇到死老鼠”。对于函数微分的讨论,光实值函数的分类可以分为以下几类(P143,3.1):

矩阵和矩阵在实值区间内转置。在数学推导中,首先根据矩阵辨识法找到矩阵,然后转置相应的梯度。

定义相对于变量偏导数的标量函数时:

矩阵和梯度矩阵是定义偏导数的不同方法,分别是行向量偏导数和列向量偏导数。只是矩阵是研究思维的更自然的选择,但梯度向量是优化和实际工程计算的更自然的选择。

5.3 预测值梯度

= 2.0 * ( - y)

以下是推导过程,红色笔迹为推导过程的基础,请参考《矩阵分析与应用》。

继续前面的公式,继续进行微分:

5.4 参数 W2 梯度

= 。T.dot()

5.5 参数

梯度

= .dot(w2.T)

5.6 Relu 梯度

grad_h = grad_h_relu.copy()
grad_h[h < 0] = 0
grad_w1 = x.T.dot(grad_h)

5.7 参数 W1 梯度

那么下一步就是利用梯度和学习率批量更新参数,实现整个训练过程。

6 参考资料

《矩阵分析与应用》(第2版),张仙达,清华大学出版社,2011-11,第2版

本文中的所有引文和页面徽标均来自本书。