提交 d6c880d0 编写于 作者: W wizardforcel

c d tex

上级 6f7f4514
......@@ -372,7 +372,7 @@ Bellman 找到了一种估计任何状态`S`的最佳状态值的方法,他提
+ `R`为智能体选择以动作`a`从状态`s`到状态`s'`的过程中得到的奖励
+ $\gamma$为衰减率
+ ![\gamma](../images/tex-ae539dfcc999c28e25a0f3ae65c1de79.gif)为衰减率
这个等式直接引出了一种算法,该算法可以精确估计每个可能状态的最优状态值:首先将所有状态值估计初始化为零,然后用数值迭代算法迭代更新它们(见公式 16-2)。一个显著的结果是,给定足够的时间,这些估计保证收敛到最优状态值,对应于最优策略。
......@@ -380,7 +380,7 @@ Bellman 找到了一种估计任何状态`S`的最佳状态值的方法,他提
其中:
+ $V_k (s)$是在`k`次算法迭代对状态`s`的估计
+ ![V_k (s)](../images/tex-12561b9e1cad1ffa385140c6c5cf9c12.gif)是在`k`次算法迭代对状态`s`的估计
该算法是动态规划的一个例子,它将了一个复杂的问题(在这种情况下,估计潜在的未来衰减奖励的总和)变为可处理的子问题,可以迭代地处理(在这种情况下,找到最大化平均报酬与下一个衰减状态值的和的动作)
......@@ -390,7 +390,7 @@ Bellman 找到了一种估计任何状态`S`的最佳状态值的方法,他提
![图E16-3](../images/chapter_16/E16-3.png)
一旦你有了最佳的 Q 值,定义最优的策略`π*(s)`,它是平凡的:当智能体处于状态`S`时,它应该选择具有最高 Q 值的动作,用于该状态:$\pi ^ * (s) =\arg \max_a Q^*(s, a)$
一旦你有了最佳的 Q 值,定义最优的策略`π*(s)`,它是平凡的:当智能体处于状态`S`时,它应该选择具有最高 Q 值的动作,用于该状态:![\pi ^ * (s) =\arg \max_a Q^*(s, a)](../images/tex-11b3b872c168f182e8efc0bec2e6a0c5.gif)
让我们把这个算法应用到图 16-8 所示的 MDP 中。首先,我们需要定义 MDP:
......@@ -633,11 +633,11 @@ copy_critic_to_actor = tf.group(*copy_ops)
其中:
+ $s^{(i)}, a^{(i)}, r^{(i)}$和$s{'(i)}$分别为状态,行为,回报,和下一状态,均从存储器中第`i`次采样得到
+ ![s^{(i)}, a^{(i)}, r^{(i)}](../images/tex-a9a5a2bca55c71f2968500d1961e8b9b.gif)和![s{'(i)}](../images/tex-49432ed302ad60b5818085cb01e642f1.gif)分别为状态,行为,回报,和下一状态,均从存储器中第`i`次采样得到
+ `m`是记忆批处理的长度
+ θ critic和` θactor `为评论者和行动者的参数
+ $Q(s^{(i)}, a^{(i)}, \theta_{critic})$是评论家 DQN 对第`i`记忆状态行为 Q 值的预测
+ $Q(s^{'(i)}, a^{'}, \theta_{actor})$是演员 DQN 在选择动作`A'`时的下一状态`S'`的期望 Q 值的预测
+ ![Q(s^{(i)}, a^{(i)}, \theta_{critic})](../images/tex-9ec72967f11b037e1e8ad34f647b04c1.gif)是评论家 DQN 对第`i`记忆状态行为 Q 值的预测
+ ![Q(s^{'(i)}, a^{'}, \theta_{actor})](../images/tex-7049aba70c46d7b934955ebdd0424749.gif)是演员 DQN 在选择动作`A'`时的下一状态`S'`的期望 Q 值的预测
+ `y`是第`i`记忆的目标 Q 值,注意,它等同于行动者实际观察到的奖励,再加上行动者对如果它能发挥最佳效果(据它所知),未来的回报应该是什么的预测。
+ `J`为训练评论家 DQN 的损失函数。正如你所看到的,这只是由行动者 DQN 估计的目标 Q 值`y`和评论家 DQN 对这些 Q 值的预测之间的均方误差。
......
# Appendix C. SVM 对偶问题
为了理解对偶性,你首先得理解拉格朗日乘子法。它基本思想是将一个有约束优化问题转化为一个无约束优化问题,其方法是将约束条件移动到目标函数中去。让我们看一个简单的例子,例如要找到合适的 $x$ 和 $y$ 使得函数 $f(x, y) = x^2 + 2y$ 最小化,且其约束条件是一个等式约束:$3x + 2y + 1 = 0$。 使用拉格朗日乘子法,我们首先定义一个函数,称为**拉格朗日函数**:$g(x, y, \alpha) = f(x, y) - \alpha(3x + 2y + 1)$. 每个约束条件(在这个例子中只有一个)与新的变量(称为拉格朗日乘数)相乘,作为原目标函数的减数。
为了理解对偶性,你首先得理解拉格朗日乘子法。它基本思想是将一个有约束优化问题转化为一个无约束优化问题,其方法是将约束条件移动到目标函数中去。让我们看一个简单的例子,例如要找到合适的 ![x](../images/tex-9dd4e461268c8034f5c8564e155c67a6.gif) 和 ![y](../images/tex-415290769594460e2e485922904f345d.gif) 使得函数 ![f(x, y) = x^2 + 2y](../images/tex-ec2b11c28f337d90d1a55c83bd738475.gif) 最小化,且其约束条件是一个等式约束:![3x + 2y + 1 = 0](../images/tex-08bc7e7224cfe0e39e04b69d4ed96298.gif)。 使用拉格朗日乘子法,我们首先定义一个函数,称为**拉格朗日函数**:![g(x, y, \alpha) = f(x, y) - \alpha(3x + 2y + 1)](../images/tex-e78acaa101dc94594e813eab3f01f428.gif). 每个约束条件(在这个例子中只有一个)与新的变量(称为拉格朗日乘数)相乘,作为原目标函数的减数。
Joseph-Louis Lagrange 大牛证明了如果 $(\bar{x}, \bar{y})$ 是原约束优化问题的解,那么一定存在一个 $\bar{\alpha}$ ,使得 $(\bar{x}, \bar{y}, \bar{\alpha})$ 是拉格朗日函数的不动点(不动点指的是,在该点处,该函数所有的偏导数均为0)。换句话说,我们可以计算拉格朗日函数 $g(x, y, \alpha) $ 关于 $x, y$ 以及 $\alpha$ 的偏导数;然后我们可以找到那些偏导数均为0的不动点;最后原约束优化问题的解(如果存在)一定在这些不动点里面。
Joseph-Louis Lagrange 大牛证明了如果 ![(\bar{x}, \bar{y})](../images/tex-fe85b05b6cd2641c29612bc75a270208.gif) 是原约束优化问题的解,那么一定存在一个 ![\bar{\alpha}](../images/tex-d9c29791dd3b792c7702ed2b7cf5ac40.gif) ,使得 ![(\bar{x}, \bar{y}, \bar{\alpha})](../images/tex-ac2d6cc9cbad11acc20ba9f6dd0ef830.gif) 是拉格朗日函数的不动点(不动点指的是,在该点处,该函数所有的偏导数均为0)。换句话说,我们可以计算拉格朗日函数 ![g(x, y, \alpha) ](../images/tex-c663f5d534674fc3f1b13074c6ae467b.gif) 关于 ![x, y](../images/tex-2317793a8de61ab32c0f17adff9ea8d4.gif) 以及 ![\alpha](../images/tex-7b7f9dbfea05c83784f8b85149852f08.gif) 的偏导数;然后我们可以找到那些偏导数均为0的不动点;最后原约束优化问题的解(如果存在)一定在这些不动点里面。
在上述例子里,偏导数为
$\begin{align}\frac{\partial}{\partial x}g(x, y, \alpha) = 2x - 3\alpha \\ \frac{\partial}{\partial y}g(x, y, \alpha) = 2 - 2\alpha \\ \frac{\partial}{\partial \alpha}g(x, y, \alpha) = -3x - 2y - 1 \end{align}$
![\begin{align}\frac{\partial}{\partial x}g(x, y, \alpha) = 2x - 3\alpha \\ \frac{\partial}{\partial y}g(x, y, \alpha) = 2 - 2\alpha \\ \frac{\partial}{\partial \alpha}g(x, y, \alpha) = -3x - 2y - 1 \end{align}](../images/tex-96d88ee52e2a53c2350376ac3b1f3c30.gif)
当这些偏导数均为0时,即 2x − 3α = 2 − 2α = − 3x − 2y − 1 = 0,即可得 $x = \frac{3}{2}, y=-\frac{11}{4}, \alpha=1$. 这是唯一一个不动点,那它一定是原约束优化问题的解。然而,上述方法仅应用于等式约束,幸运的是,在某些正则性条件下,这种方法也可被一般化应用于不等式约束条件(例如不等式约束,$3x + 2y + 1 \geq 0$)。如下公式 C-1 ,给了SVM硬间隔问题时的一般化拉格朗日函数。在该公式中,$\alpha^{(i)}$ 是 KKT 乘子,它必须大于或等于0. (译者注:$\alpha^{(i)}$ 是 $\geq0$ 抑或 $\leq0$ 取决于拉格朗日函数的写法,以及原目标函数函数最大化抑或最小化)
当这些偏导数均为0时,即 2x − 3α = 2 − 2α = − 3x − 2y − 1 = 0,即可得 ![x = \frac{3}{2}, y=-\frac{11}{4}, \alpha=1](../images/tex-9439cb7cb2e1c01f22745401287a0638.gif). 这是唯一一个不动点,那它一定是原约束优化问题的解。然而,上述方法仅应用于等式约束,幸运的是,在某些正则性条件下,这种方法也可被一般化应用于不等式约束条件(例如不等式约束,![3x + 2y + 1 \geq 0](../images/tex-3b6ed467ca1ae09aeafe40f4b40251c7.gif))。如下公式 C-1 ,给了SVM硬间隔问题时的一般化拉格朗日函数。在该公式中,![\alpha^{(i)}](../images/tex-99f0c7b568236eb0a52bf15cbbfa342e.gif) 是 KKT 乘子,它必须大于或等于0. (译者注:![\alpha^{(i)}](../images/tex-99f0c7b568236eb0a52bf15cbbfa342e.gif) 是 ![\geq0](../images/tex-e56717342e6431bdaa1f37c90f7ba7b3.gif) 抑或 ![\leq0](../images/tex-825a000824ab58528de14389acafd231.gif) 取决于拉格朗日函数的写法,以及原目标函数函数最大化抑或最小化)
![公式C-1](../images/Appendix/E_C-1.png)
就像拉格朗日乘子法,我们可以计算上述式子的偏导数、定位不动点。如果该原问题存在一个解,那它一定在不动点$(\bar{w}, \bar{b}, \bar{\alpha})$之中,且遵循 KKT 条件:
就像拉格朗日乘子法,我们可以计算上述式子的偏导数、定位不动点。如果该原问题存在一个解,那它一定在不动点![(\bar{w}, \bar{b}, \bar{\alpha})](../images/tex-e0569dbaecb2e5955e7ff0bad0749154.gif)之中,且遵循 KKT 条件:
- 遵循原问题的约束: $t^{(i)}((\bar{w})^T x^{(i)} +\bar{b}) \geq 1$, 对于 $i = 1, 2, ..., m$
- 遵循现问题里的约束,即 $\bar{\alpha}^{(i)} \geq 0$
- $\bar{\alpha}^{(i)} = 0$ 或者第`i`个约束条件是积极约束,意味着该等式成立:$t^{(i)}((\bar{w})^T x^{(i)} +\bar{b}) = 1$. 这个条件叫做 互补松弛 条件。它暗示了 $\bar{\alpha}^{(i)} = 0$ 和第`i`个样本位于SVM间隔的边界上(该样本是支撑向量)。
- 遵循原问题的约束: ![t^{(i)}((\bar{w})^T x^{(i)} +\bar{b}) \geq 1](../images/tex-5c71c1287e7a6b8fef19874c553b0cd4.gif), 对于 ![i = 1, 2, ..., m](../images/tex-31f8dedd0a66fb646ef261c638243923.gif)
- 遵循现问题里的约束,即 ![\bar{\alpha}^{(i)} \geq 0](../images/tex-61b00d67f0968d7be5bf4b7a3260b1f4.gif)
- ![\bar{\alpha}^{(i)} = 0](../images/tex-9eaf40b81df456c80b338612aa1e6fb7.gif) 或者第`i`个约束条件是积极约束,意味着该等式成立:![t^{(i)}((\bar{w})^T x^{(i)} +\bar{b}) = 1](../images/tex-758714f96d598b4cbb8a7642bc3fb017.gif). 这个条件叫做 互补松弛 条件。它暗示了 ![\bar{\alpha}^{(i)} = 0](../images/tex-9eaf40b81df456c80b338612aa1e6fb7.gif) 和第`i`个样本位于SVM间隔的边界上(该样本是支撑向量)。
注意 KKT 条件是确定不动点是否为原问题解的必要条件。在某些条件下,KKT 条件也是充分条件。幸运的是,SVM 优化问题碰巧满足这些条件,所以任何满足 KKT 条件的不动点保证是原问题的解。
......@@ -32,9 +32,9 @@ $\begin{align}\frac{\partial}{\partial x}g(x, y, \alpha) = 2x - 3\alpha \\ \frac
![公式C-4](../images/Appendix/E_C-4.png)
现在该对偶形式的目标是找到合适的向量 $\bar{\alpha}$ , 使得该函数 $L(w, b, \alpha)$ 最小化,且 $\bar{\alpha}^{(i)} \geq 0$. 现在这个有约束优化问题正是我们苦苦追寻的对偶问题。
现在该对偶形式的目标是找到合适的向量 ![\bar{\alpha}](../images/tex-d9c29791dd3b792c7702ed2b7cf5ac40.gif) , 使得该函数 ![L(w, b, \alpha)](../images/tex-8d9370145286bec564a001265dd85ff9.gif) 最小化,且 ![\bar{\alpha}^{(i)} \geq 0](../images/tex-61b00d67f0968d7be5bf4b7a3260b1f4.gif). 现在这个有约束优化问题正是我们苦苦追寻的对偶问题。
一旦你找到了最优的 $\bar{\alpha}$, 你可以利用公式C-3第一行计算 $\bar{w}$。为了计算 $\bar{b}$, 你可以使用支撑向量的已知条件 $t^{(i)}((\bar{w})^T x^{(i)} +\bar{b}) = 1$, 当第 k 个样本是支撑向量时(即它对应的 $\alpha_k > 0$,此时使用它计算 $\bar{b} =1-t^{(k)}((\bar{w})^T . x^{(k)}) $. 对了,我们更喜欢利用所有支撑向量计算一个平均值,以获得更稳定和更准确的结果,如公式C-5.
一旦你找到了最优的 ![\bar{\alpha}](../images/tex-d9c29791dd3b792c7702ed2b7cf5ac40.gif), 你可以利用公式C-3第一行计算 ![\bar{w}](../images/tex-28175dc40d9c53d6d2c186a7817cf866.gif)。为了计算 ![\bar{b}](../images/tex-222e2caf9c7b49d3432466e360eceba6.gif), 你可以使用支撑向量的已知条件 ![t^{(i)}((\bar{w})^T x^{(i)} +\bar{b}) = 1](../images/tex-758714f96d598b4cbb8a7642bc3fb017.gif), 当第 k 个样本是支撑向量时(即它对应的 ![\alpha_k > 0](../images/tex-fe658058e9257029aa88bc89b34348de.gif),此时使用它计算 ![\bar{b} =1-t^{(k)}((\bar{w})^T . x^{(k)}) ](../images/tex-75080a1229e54394d1c6d95b9e542eaa.gif). 对了,我们更喜欢利用所有支撑向量计算一个平均值,以获得更稳定和更准确的结果,如公式C-5.
![公式C-5](../images/Appendix/E_C-5.png)
......@@ -2,17 +2,17 @@
这个附录解释了 TensorFlow 的自动微分功能是如何工作的,以及它与其他解决方案的对比。
假定你定义了函数 $f(x, y) = x^2y + y + 2$, 需要得到它的偏导数 $\frac{\partial f}{\partial x}$和 $\frac{\partial f}{\partial y}$,以用于梯度下降或者其他优化算法。你的可选方案有手动微分法,符号微分法,数值微分法,前向自动微分,和反向自动微分。TensorFlow实现的反向自动微分法。我们来看看每种方案。
假定你定义了函数 ![f(x, y) = x^2y + y + 2](../images/tex-162751afe7e0aa904426973dbac3654e.gif), 需要得到它的偏导数 ![\frac{\partial f}{\partial x}](../images/tex-f6e0346d1d3410b0fbe32b41b85999aa.gif)和 ![\frac{\partial f}{\partial y}](../images/tex-408378e8bc55170258126d10000c53d9.gif),以用于梯度下降或者其他优化算法。你的可选方案有手动微分法,符号微分法,数值微分法,前向自动微分,和反向自动微分。TensorFlow实现的反向自动微分法。我们来看看每种方案。
## 手动微分法
第一个方法是拿起一直笔和一张纸,使用你的代数知识去手动的求偏导数。对于已定义的函数,求它的偏导并不太困难。你需要使用如下5条规则:
- 常数的导数为0.
- $\lambda x$ 的导数为 $\lambda$ , $\lambda$为常数。
- $x^{\lambda}$ 的导数是 $\lambda x^{\lambda - 1}$
- ![\lambda x](../images/tex-d08b62e799e1ff8f24464dc26a2daebe.gif) 的导数为 ![\lambda](../images/tex-c6a6eb61fd9c6c913da73b3642ca147d.gif) , ![\lambda](../images/tex-c6a6eb61fd9c6c913da73b3642ca147d.gif)为常数。
- ![x^{\lambda}](../images/tex-74bde878aa116856d62aba260e55c67a.gif) 的导数是 ![\lambda x^{\lambda - 1}](../images/tex-6c620d50445244971a9718316db37470.gif)
- 函数的和的导数,等于函数的导数的和
- $\lambda$ 乘以函数,再求导,等于 $\lambda$ 乘以函数的导数
- ![\lambda](../images/tex-c6a6eb61fd9c6c913da73b3642ca147d.gif) 乘以函数,再求导,等于 ![\lambda](../images/tex-c6a6eb61fd9c6c913da73b3642ca147d.gif) 乘以函数的导数
从上述这些规则,可得到公式D-1.
......@@ -22,17 +22,17 @@
## 符号微分
图D-1展示了符号微分是如何运行在相当简单的函数上的,$g(x,y) = 5 + xy$. 该函数的计算图如图的左边所示。通过符号微分,我们可得到图的右部分,它代表了 $\frac{\partial g}{\partial x} = 0 + (0 \times x + y \times 1) = y$, 相似地也可得到关于`y`的导数。
图D-1展示了符号微分是如何运行在相当简单的函数上的,![g(x,y) = 5 + xy](../images/tex-595a140c599de3ceab7b72d4aaab8a41.gif). 该函数的计算图如图的左边所示。通过符号微分,我们可得到图的右部分,它代表了 ![\frac{\partial g}{\partial x} = 0 + (0 \times x + y \times 1) = y](../images/tex-9e9fa7bbdcb31a3b04a549685db18042.gif), 相似地也可得到关于`y`的导数。
![D-1](../images/Appendix/D-1.png)
概算法先获得叶子结点的偏导数。常数5返回常数0, 因为常数的导数总是0。变量`x`返回常数1,变量`y`返回常数0因为 $\frac{\partial y}{\partial x} = 0$(如果我们找关于`y`的偏导数,那它将反过来)。
概算法先获得叶子结点的偏导数。常数5返回常数0, 因为常数的导数总是0。变量`x`返回常数1,变量`y`返回常数0因为 ![\frac{\partial y}{\partial x} = 0](../images/tex-ea6d21230d9c335a071d341ceb54d780.gif)(如果我们找关于`y`的偏导数,那它将反过来)。
现在我们移动到计算图的相乘结点处,代数告诉我们,`u``v`相乘后的导数为 $\frac{\partial (u \times v)}{\partial x} = \frac{\partial v}{\partial x} \times u + \frac{\partial u}{\partial x} \times v $. 因此我们可以构造有图中大的部分,代表0 × x + y × 1.
现在我们移动到计算图的相乘结点处,代数告诉我们,`u``v`相乘后的导数为 ![\frac{\partial (u \times v)}{\partial x} = \frac{\partial v}{\partial x} \times u + \frac{\partial u}{\partial x} \times v ](../images/tex-1cf5205e2548cc4e0ce9e5343ab1a377.gif). 因此我们可以构造有图中大的部分,代表0 × x + y × 1.
最后我们往上走到计算图的相加结点处,正如5条规则里提到的,和的导数等于导数的和。所以我们只需要创建一个相加结点,连接我们已经计算出来的部分。我们可以得到正确的偏导数,即:$\frac{\partial g}{\partial x} = 0 + (0 \times x + y \times 1) $.
最后我们往上走到计算图的相加结点处,正如5条规则里提到的,和的导数等于导数的和。所以我们只需要创建一个相加结点,连接我们已经计算出来的部分。我们可以得到正确的偏导数,即:![\frac{\partial g}{\partial x} = 0 + (0 \times x + y \times 1) ](../images/tex-7e03e8e758791a8db7937cbbcc78f2b9.gif).
然而,这个过程可简化。对该图应用一些微不足道的剪枝步骤,可以去掉所有不必要的操作,然后我们可以得到一个小得多的只有一个结点的偏导计算图:$\frac{\partial g}{\partial x} = y$.
然而,这个过程可简化。对该图应用一些微不足道的剪枝步骤,可以去掉所有不必要的操作,然后我们可以得到一个小得多的只有一个结点的偏导计算图:![\frac{\partial g}{\partial x} = y](../images/tex-1fda7e8979ad0fdf4a2022ee529661d0.gif).
在这个例子里,简化操作是相当简单的,但对更复杂的函数来说,符号微分会产生一个巨大的计算图,该图可能很难去简化,以导致次优的性能。更重要的是,符号微分不能处理由任意代码定义的函数,例如,如下已在第9章讨论过的函数:
......@@ -46,11 +46,11 @@ def my_func(a, b):
## 数值微分
从数值上说,最简单的方案是去计算导数的近似值。回忆`h(x)`$x_0$ 的导数 $h^{'}(x_0)$,是该函数在该点处的斜率,或者更准确如公式D-2所示。
从数值上说,最简单的方案是去计算导数的近似值。回忆`h(x)`![x_0](../images/tex-3e0d691f3a530e6c7e079636f20c111b.gif) 的导数 ![h^{'}(x_0)](../images/tex-6499b5277397390a9878a93fa4205525.gif),是该函数在该点处的斜率,或者更准确如公式D-2所示。
![E_D-2](../images/Appendix/E_D-2.png)
因此如果我们想要计算 $f(x,y)$ 关于`x`,在 $x=3, y=4$ 处的导数,我们可以简单计算 $f(3+\epsilon, 4) - f(3, 4)$ 的值,将这个结果除以 $\epsilon$, 且 $\epsilon$ 去很小的值。这个过程正是如下的代码所要干的。
因此如果我们想要计算 ![f(x,y)](../images/tex-3baf1600ae50930a155f58ae172b51bd.gif) 关于`x`,在 ![x=3, y=4](../images/tex-99e7bebb7eb398dc777eea8fa1bfe3ba.gif) 处的导数,我们可以简单计算 ![f(3+\epsilon, 4) - f(3, 4)](../images/tex-5dcd5b36cf658a9fbb13000a4cac6989.gif) 的值,将这个结果除以 ![\epsilon](../images/tex-92e4da341fe8f4cd46192f21b6ff3aa7.gif), 且 ![\epsilon](../images/tex-92e4da341fe8f4cd46192f21b6ff3aa7.gif) 去很小的值。这个过程正是如下的代码所要干的。
```python
def f(x, y):
......@@ -78,23 +78,23 @@ df_dy = derivative(f, 3, 4, 0, 0.00001)
## 前向自动微分
前向自动微分既不是数值微分,也不是符号微分,但在某些方面,它是他们爱的小孩儿。它依赖对偶数。对偶数是奇怪但迷人的,是 $a + b\epsilon$ 形式的数,这里 `a``b` 是实数,$\epsilon$ 是无穷小的数,满足 $\epsilon ^ 2 = 0$, 但 $\epsilon \ne 0$. 你可以认为对偶数 $42 + 24\epsilon$ 类似于有着无穷个0的42.0000⋯000024(但当然这是简化后的,仅仅给你对偶数什么的想法)。一个对偶数在内存中表示为一个浮点数对,例如,$42 + 24\epsilon$ 表示为 (42.0, 24.0)。
前向自动微分既不是数值微分,也不是符号微分,但在某些方面,它是他们爱的小孩儿。它依赖对偶数。对偶数是奇怪但迷人的,是 ![a + b\epsilon](../images/tex-595b3d916d7b666f7cec8f222f665759.gif) 形式的数,这里 `a``b` 是实数,![\epsilon](../images/tex-92e4da341fe8f4cd46192f21b6ff3aa7.gif) 是无穷小的数,满足 ![\epsilon ^ 2 = 0](../images/tex-0fe16f5f8178c40813008f32155da044.gif), 但 ![\epsilon \ne 0](../images/tex-11096ba55e57b0ba1b35efb241f87569.gif). 你可以认为对偶数 ![42 + 24\epsilon](../images/tex-63b17a82b832b929bd916f01c8a4dadd.gif) 类似于有着无穷个0的42.0000⋯000024(但当然这是简化后的,仅仅给你对偶数什么的想法)。一个对偶数在内存中表示为一个浮点数对,例如,![42 + 24\epsilon](../images/tex-63b17a82b832b929bd916f01c8a4dadd.gif) 表示为 (42.0, 24.0)。
对偶数可相加、相乘、等等操作,正如公式D-3所示。
![E_D-3](../images/Appendix/E_D-3.png)
最重要的,可证明 h(a + bϵ) = h(a) + b × h′(a)ϵ,所以计算一次 h(a + ϵ) 就得到了两个值 h(a) 和 h′(a) 。图D-2展示了前向自动微分如何计算 $f(x,y)=x^2y + y + 2$ 关于`x`,在 $x=3, y=4$ 处的导数的。我们所要做的一切只是计算 $f(3+\epsilon, 4)$; 它将输出一个对偶数,其第一部分等于 $f(3, 4)$, 第二部分等于 $f^{'}(3, 4) = \frac{\partial f}{\partial x} (3,4)$.
最重要的,可证明 h(a + bϵ) = h(a) + b × h′(a)ϵ,所以计算一次 h(a + ϵ) 就得到了两个值 h(a) 和 h′(a) 。图D-2展示了前向自动微分如何计算 ![f(x,y)=x^2y + y + 2](../images/tex-bf7d4f41a093293adbb04e43c7d12839.gif) 关于`x`,在 ![x=3, y=4](../images/tex-99e7bebb7eb398dc777eea8fa1bfe3ba.gif) 处的导数的。我们所要做的一切只是计算 ![f(3+\epsilon, 4)](../images/tex-da5577f9751e71377558278256ff1115.gif); 它将输出一个对偶数,其第一部分等于 ![f(3, 4)](../images/tex-744a84046c00c267c037276ee9483cff.gif), 第二部分等于 ![f^{'}(3, 4) = \frac{\partial f}{\partial x} (3,4)](../images/tex-399b8bab86aa930cdbf5c93b2e3fa818.gif).
![D-2](../images/Appendix/D-2.png)
为了计算 $\frac{\partial f}{\partial y} (3,4)$ 我们不得不再历经一遍计算图,但这次前馈的值为 $x=3, y = 4 + \epsilon$.
为了计算 ![\frac{\partial f}{\partial y} (3,4)](../images/tex-3b5f49ee9fe10430f81eeef7000f1b30.gif) 我们不得不再历经一遍计算图,但这次前馈的值为 ![x=3, y = 4 + \epsilon](../images/tex-a6ef39467ae1ecfdf09a7e93357c3154.gif).
所以前向自动微分比数值微分准确得多,但它遭受同样的缺陷:如果有1000个参数,那为了计算所有的偏导数,得历经计算图 1000 次。这正是反向自动微分耀眼的地方:计算所有的偏导数,它只需要经历计算图2次。
## 反向自动微分
反向自动微分是 TensorFlow 采取的方案。它首先前馈经历计算图(即,从输入到输出),计算出每个结点的值。然后进行第二次经历,这次是反向经历(即,从输出到输入),计算出所有的偏导数。图D-3展示了第二次经历的过程。在第一次经历过程中,所有结点值已被计算,输入是 $x=3, y=4$。你可以在每个结点底部右方看到这些值(例如,$x \times x = 9$)。结点已被标号,从 $n_1$ 到 $n_7$。输出结点是 $n_7: f(3, 4) = n_7 = 42$.
反向自动微分是 TensorFlow 采取的方案。它首先前馈经历计算图(即,从输入到输出),计算出每个结点的值。然后进行第二次经历,这次是反向经历(即,从输出到输入),计算出所有的偏导数。图D-3展示了第二次经历的过程。在第一次经历过程中,所有结点值已被计算,输入是 ![x=3, y=4](../images/tex-99e7bebb7eb398dc777eea8fa1bfe3ba.gif)。你可以在每个结点底部右方看到这些值(例如,![x \times x = 9](../images/tex-ddfd45b07cca3862ad001dc6551d826a.gif))。结点已被标号,从 ![n_1](../images/tex-6c773b2b7798e5713845e475d0c4b4c7.gif) 到 ![n_7](../images/tex-97d045dcd64af5ae4cc4add328629288.gif)。输出结点是 ![n_7: f(3, 4) = n_7 = 42](../images/tex-17241d7ea090e8a7be55cacfcd5b2768.gif).
![D-3](../images/Appendix/D-3.png)
......@@ -102,14 +102,14 @@ df_dy = derivative(f, 3, 4, 0, 0.00001)
![E_D-4](../images/Appendix/E_D-4.png)
由于 $n_7$ 是输出结点,即 $f= n_7$, 所以 $\frac{\partial f}{\partial n_7} = 1$.
由于 ![n_7](../images/tex-97d045dcd64af5ae4cc4add328629288.gif) 是输出结点,即 ![f= n_7](../images/tex-9233369b2eac1c4808ae768a0534fa78.gif), 所以 ![\frac{\partial f}{\partial n_7} = 1](../images/tex-c052878d41402368d536c53f4937b012.gif).
接着到了图的 $n_5$ 结点:当 $n_5$ 变化时,$f$ 会变化多少?答案是 $\frac{\partial f}{\partial n_5} = \frac{\partial f}{\partial n_7} \times \frac{\partial n_7}{\partial n_5}$. 我们已经知道 $\frac{\partial f}{\partial n_7} = 1$, 因此我们只需要知道 $\frac{\partial n_7}{\partial n_5}$ 就行。因为 $n_7$ 是 $n_5 + n_6$ 的和,因此可得到 $\frac{\partial n_7}{\partial n_5} = 1$, 因此 $\frac{\partial f}{\partial n_5}=1 \times 1 = 1$.
接着到了图的 ![n_5](../images/tex-53eba210fc14ef60860265ec70fb718d.gif) 结点:当 ![n_5](../images/tex-53eba210fc14ef60860265ec70fb718d.gif) 变化时,![f](../images/tex-8fa14cdd754f91cc6554c9e71929cce7.gif) 会变化多少?答案是 ![\frac{\partial f}{\partial n_5} = \frac{\partial f}{\partial n_7} \times \frac{\partial n_7}{\partial n_5}](../images/tex-c4664533339cdf3ddbe912caf82c5bdc.gif). 我们已经知道 ![\frac{\partial f}{\partial n_7} = 1](../images/tex-c052878d41402368d536c53f4937b012.gif), 因此我们只需要知道 ![\frac{\partial n_7}{\partial n_5}](../images/tex-3d189a2e226493acc6538bcd3e9cb366.gif) 就行。因为 ![n_7](../images/tex-97d045dcd64af5ae4cc4add328629288.gif) 是 ![n_5 + n_6](../images/tex-bf018abe4e43c0b3132cba23cb971907.gif) 的和,因此可得到 ![\frac{\partial n_7}{\partial n_5} = 1](../images/tex-68f34602f87a1f0669551323e59a17ea.gif), 因此 ![\frac{\partial f}{\partial n_5}=1 \times 1 = 1](../images/tex-d0a7f1641b3fe72530efcea74fd7a4d2.gif).
现在前进到 $n_4$: 当 $n_4$ 变化时,$f$ 会变化多少?答案是 $\frac{\partial f}{\partial n_4} = \frac{\partial f}{\partial n_5} \times \frac{\partial n_5}{\partial n_4}$. 由于 $n_5 = n_4 \times n_2$, 我们可得到 $\frac{\partial n_5}{\partial n_4} = n_2$, 所以 $\frac{\partial f}{\partial n_4}= 1 \times n_2 = 4$.
现在前进到 ![n_4](../images/tex-43c5783d36b015e36edeecd60da73206.gif): 当 ![n_4](../images/tex-43c5783d36b015e36edeecd60da73206.gif) 变化时,![f](../images/tex-8fa14cdd754f91cc6554c9e71929cce7.gif) 会变化多少?答案是 ![\frac{\partial f}{\partial n_4} = \frac{\partial f}{\partial n_5} \times \frac{\partial n_5}{\partial n_4}](../images/tex-414889b175f816852566907db5edd6a5.gif). 由于 ![n_5 = n_4 \times n_2](../images/tex-c982adc41e9ee58af9aed4995717fa82.gif), 我们可得到 ![\frac{\partial n_5}{\partial n_4} = n_2](../images/tex-421556b6c8203ded772656e90a1a570c.gif), 所以 ![\frac{\partial f}{\partial n_4}= 1 \times n_2 = 4](../images/tex-5da5d4cf0bebe9ea96d3fbb2c2fd93ca.gif).
这个遍历过程一直持续,此时我们达到图的底部。这时我们已经得到了所有偏导数在点 $x=3, y=4$ 处的值。在这个例子里,我们得到 $\frac{\partial f}{\partial x} = 24, \frac{\partial f}{\partial y} = 10$. 听起来很美妙!
这个遍历过程一直持续,此时我们达到图的底部。这时我们已经得到了所有偏导数在点 ![x=3, y=4](../images/tex-99e7bebb7eb398dc777eea8fa1bfe3ba.gif) 处的值。在这个例子里,我们得到 ![\frac{\partial f}{\partial x} = 24, \frac{\partial f}{\partial y} = 10](../images/tex-e39fd6874bfece3703cdd1eb53e170b0.gif). 听起来很美妙!
反向自动微分是非常强大且准确的技术,尤其是当有很多输入参数和极少输出时,因为它只要求一次前馈传递加上一次反向传递,就可计算所有输出关于所有输入的偏导数。最重要的是,它可以处理任意代码定义的函数。它也可以处理那些不完全可微的函数,只要 你要求他计算的偏导数在该点处是可微的。
如果你在 TensorFlow 中实现了新算子,你想使它与现有的自动微分相兼容,那你需要提供函数,该函数用于构建一个子图,来计算关于新算子输入的偏导数。例如,假设你实现了一个计算其输入的平方的函数,平方算子 $f(x)= x ^2$,在这个例子中你需要提供相应的导函数 $f^{'}(x)= 2x $. 注意这个导函数不计算一个数值结果,而是用于构建子图,该子图后续将计算偏导结果。这是非常有用的,因为这意味着你可以计算梯度的梯度(为了计算二阶导数,或者甚至更高维的导数)。
\ No newline at end of file
如果你在 TensorFlow 中实现了新算子,你想使它与现有的自动微分相兼容,那你需要提供函数,该函数用于构建一个子图,来计算关于新算子输入的偏导数。例如,假设你实现了一个计算其输入的平方的函数,平方算子 ![f(x)= x ^2](../images/tex-d26940d88870bfe622e50be50381fdb9.gif),在这个例子中你需要提供相应的导函数 ![f^{'}(x)= 2x ](../images/tex-8f515dd3c20d16c5ed6223da611b9a2f.gif). 注意这个导函数不计算一个数值结果,而是用于构建子图,该子图后续将计算偏导结果。这是非常有用的,因为这意味着你可以计算梯度的梯度(为了计算二阶导数,或者甚至更高维的导数)。
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册