Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 53 additions & 59 deletions lectures/optgrowth_fast.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,21 +35,21 @@ tags: [hide-output]

## 概述

{doc}`在之前的内容中 <optgrowth>`,我们研究了一个具有单个代表性个体的随机最优增长模型
{doc}`上一讲 <optgrowth>`中,我们研究了一个具有代表性个体的随机最优增长模型

我们使用动态规划方法求解了该模型
我们使用动态规划方法对该模型进行了求解

在编写代码时,我们注重清晰性和灵活性。

这些都很重要,但灵活性和速度之间通常存在权衡
尽管这些特性十分重要,但在实际应用中,灵活性与运行速度之间往往存在权衡

原因是,当代码灵活性较低时,我们可以更容易地利用其结构特点
其原因在于,当代码的灵活性降低时,我们能够更容易地利用模型的结构特征

这对算法和数学问题来说普遍适用:更具体的问题具有更多的结构特征,经过思考后,可以利用这些特征获得更好的结果。)
这一点在算法与数学问题中普遍成立:越具体的问题往往具有更强的结构特征,而经过适当设计,这些结构可被有效利用,从而获得更优的结果。)

因此,在本讲中,我们将接受较低的灵活性以获得更快的速度,使用即时(JIT)编译来加速我们的代码
因此,在本讲中,我们将牺牲一定的灵活性以换取更高的运行速度,采用即时(JIT)编译来加速代码的执行

让我们从一些导入开始
下面让我们从导入相关库开始

```{code-cell} ipython
import matplotlib.pyplot as plt
Expand All @@ -63,33 +63,33 @@ from numba import jit, jit
from quantecon.optimize.scalar_maximization import brent_max
```

函数`brent_max`也设计用于嵌入JIT编译代码中
函数`brent_max`同样被设计用于嵌入JIT编译代码中

这些是SciPy中类似函数的替代方案(不幸的是,SciPy的函数不支持JIT)。
这些函数可作为SciPy中类似函数的替代方案(遗憾的是,SciPy中的相关函数目前尚不支持JIT)。

## 模型

```{index} single: Optimal Growth; Model
```

这个模型与我们在{doc}`之前的讲座 <optgrowth>`中讨论的最优增长模型相同
本节所使用的模型与我们在{doc}`前一讲 <optgrowth>`关于最优增长的讲授中所讨论的模型相同

我们将从对数效用函数开始
我们从对数型效用函数开始

$$
u(c) = \ln(c)
$$

我们继续假设
并继续作如下假设

* $f(k) = k^{\alpha}$
* $\phi$是当$\zeta$为标准正态分布时,$\xi := \exp(\mu + s \zeta)$的分布
* 生产函数为 $f(k) = k^{\alpha}$
* 随机冲击项 $\xi$ 的分布为 $\phi$,其中 $\xi := \exp(\mu + s \zeta)$ 且 $\zeta$ 为标准正态分布。

我们将再次使用值函数迭代来求解这个模型
我们将再次使用价值函数迭代(VFI)来求解这个模型

具体来说,算法保持不变,唯一的区别在于实现本身
具体来说,算法保持不变,唯一的区别在于具体的实现方式

和之前一样,我们将能够与真实解进行比较
和之前一样,我们会对比本次计算所得结果与真实解。

```{code-cell} ipython3
:load: _static/lecture_specific/optgrowth/cd_analytical.py
Expand All @@ -100,29 +100,29 @@ $$
```{index} single: Dynamic Programming; Computation
```

我们将再次把最优增长模型的基本要素存储在一个类中
我们将再次把最优增长模型的基本要素封装在一个类中

但这次我们将使用[Numba的](https://python-programming.quantecon.org/numba.html) `@jitclass`装饰器来对我们的类进行JIT编译
然而,与此前不同的是,我们将使用[Numba](https://python-programming.quantecon.org/numba.html) `@jitclass`装饰器来对该类进行JIT编译

因为我们要使用Numba来编译我们的类,所以需要指定数据类型
由于我们计划使用Numba来编译该类,因此需要明确指定数据类型

你会在我们的类上方看到一个名为`opt_growth_data`的列表。
在代码中,你将看到一个名为`opt_growth_data`的列表,该列表定义在类的上方,用于说明这些类型

与{doc}`上一讲<optgrowth>`不同,我们将生产和效用函数的具体形式直接写入类中
与{doc}`上一讲<optgrowth>`不同的是,这里我们将生产和效用函数的具体形式直接写入类中,而非保持一般性形式

这是我们为了获得更快的速度而牺牲灵活性的地方
也就是说,我们在此牺牲了一定的灵活性,以换取更高的运行速度

```{code-cell} ipython3
:load: _static/lecture_specific/optgrowth_fast/ogm.py
```

该类包含一些方法如`u_prime`,我们现在不需要但会在后续课程中使用
该类还包含若干方法,例如`u_prime`,虽然在当前讲义中尚未使用,但将在后续课程中发挥作用

### Bellman算子
### 贝尔曼算子

我们将使用JIT编译来加速Bellman算子
我们将使用JIT编译来加速贝尔曼算子的计算

首先,这里有一个函数,根据贝尔曼方程{eq}`fpb30`返回特定消费选择`c`在给定状态`y`下的值
首先,定义一个函数,用于计算在给定状态`y`下,某一特定消费选择`c`所对应的价值。该函数基于贝尔曼方程{eq}`fpb30`

```{code-cell} ipython3
@jit
Expand Down Expand Up @@ -184,16 +184,16 @@ def T(v, og):
og = OptimalGrowthModel()
```

现在我们调用`solve_model`,使用`%%time`魔法指令来检查运行时间
现在我们调用`solve_model`,使用`%%time`魔法指令来记录运行时间

```{code-cell} ipython3
%%time
v_greedy, v_solution = solve_model(og)
```

你会注意到这比我们的{doc}`原始实现 <optgrowth>`要*快得多*。
你会发现,这比我们的{doc}`原始实现 <optgrowth>`要*快得多*。

下面是生成的策略与真实策略的对比图
下面,生成近似策略与真实策略的对比图

```{code-cell} ipython3
fig, ax = plt.subplots()
Expand All @@ -208,7 +208,7 @@ ax.legend()
plt.show()
```

再次,拟合效果非常好 --- 这是意料之中的,因为我们没有改变算法。
与之前一样,拟合效果非常好 --- 这是意料之中的,因为我们没有改变算法。

两种策略之间的最大绝对偏差是

Expand All @@ -221,22 +221,20 @@ np.max(np.abs(v_greedy - σ_star(og.grid, og.α, og.β)))
```{exercise}
:label: ogfast_ex1

计时使用贝尔曼算子迭代20次所需的时间,从初始条件 $v(y) = u(y)$ 开始。

使用默认参数设置。
在默认参数设定下,从给定的初始条件 $v(y) = u(y)$ 开始,对贝尔曼算子进行 20 次迭代,并记录整个迭代过程所耗费的时间。
```

```{solution-start} ogfast_ex1
:class: dropdown
```

让我们设置初始条件。
设置初始条件:

```{code-cell} ipython3
v = og.u(og.grid)
```

这是时间统计
计时

```{code-cell} ipython3
%%time
Expand All @@ -246,46 +244,46 @@ for i in range(20):
v = v_new
```

与我们对非编译版本的值函数迭代的{ref}`计时 <og_ex2>`相比,JIT编译的代码通常快一个数量级。
与非编译版本的价值函数迭代的{ref}`用时 <og_ex2>`相比,JIT编译的代码通常快一个数量级。

```{solution-end}
```

```{exercise}
:label: ogfast_ex2

修改最优增长模型以使用CRRA效用函数规范。
将最优增长模型修改为采用CRRA效用函数的设定:

$$
u(c) = \frac{c^{1 - \gamma} } {1 - \gamma}
$$

`γ = 1.5`设为默认值,并保持其他规范不变
设定`γ = 1.5`为默认值,并保持其他模型设定不变

(注意,`jitclass`目前不支持继承,所以你必须复制类并更改相关参数和方法。)
(注意,`jitclass`目前不支持类继承,因此你需要复制原有的类,并相应修改相关的参数与方法。)

计算最优策略的估计值,绘制图表,并与第一个最优增长讲座中{ref}`类似练习 <og_ex1>`的相同图表进行视觉比较
计算最优策略的估计值,并绘制其图像。将所得图像与第一讲最优增长模型中{ref}`对应练习 <og_ex1>`的图表进行比较

同时比较执行时间
同时,对比两种实现的运行时间
```

```{solution-start} ogfast_ex2
:class: dropdown
```

这是我们的CRRA版本的`OptimalGrowthModel`:
这是CRRA版本的`OptimalGrowthModel`:

```{code-cell} ipython3
:load: _static/lecture_specific/optgrowth_fast/ogm_crra.py
```

让我们创建一个实例
创建一个实例

```{code-cell} ipython3
og_crra = OptimalGrowthModel_CRRA()
```

现在我们调用`solve_model`,使用`%%time`魔术命令来检查运行时间
调用`solve_model`,使用`%%time`魔术命令来记录运行时间

```{code-cell} ipython3
%%time
Expand All @@ -298,16 +296,13 @@ v_greedy, v_solution = solve_model(og_crra)
fig, ax = plt.subplots()

ax.plot(og.grid, v_greedy, lw=2,
alpha=0.6, label='近似值函数')
alpha=0.6, label='近似价值函数')

ax.legend(loc='lower right')
plt.show()
```

这与我们在非jit代码中得到的解决方案相符,
{ref}`in the exercises <og_ex1>`。

执行时间快了一个数量级。
这与我们在{ref}`练习 <og_ex1>`中使用非jit代码得到的答案相符,但执行时间快了一个数量级。

```{solution-end}
```
Expand All @@ -317,31 +312,30 @@ plt.show()
:label: ogfast_ex3
```

在这个练习中,我们回到原始的对数效用规范
在本练习中,我们回到最初的对数型效用函数设定

一旦给定最优消费策略$\sigma$,收入遵循
当给定最优消费政策 $\sigma$ 后,收入的动态演化如下:

$$
y_{t+1} = f(y_t - \sigma(y_t)) \xi_{t+1}
$$

下图显示了三种不同贴现因子(因此是三种不同策略)下该序列100个元素的模拟
下图展示了该序列在三种不同贴现因子(因而对应三种不同政策)下的模拟结果,每个序列包含 100 个样本点

```{figure} /_static/lecture_specific/optgrowth/solution_og_ex2.png
```

在每个序列中,初始条件是$y_0 = 0.1$。
在每个序列中,初始条件都是 $y_0 = 0.1$。

贴现因子为`discount_factors = (0.8, 0.9, 0.98)`。
贴现因子分别为`discount_factors = (0.8, 0.9, 0.98)`。

我们还通过设置`s = 0.05`稍微降低了冲击的幅度。

除此之外,参数和原始设定与讲座前面讨论的对数线性模型相同
除此之外,参数和原始设定与前面讨论的对数线性模型相同

注意,更有耐心的个体通常拥有更高的财富。


复现该图形,允许随机性。
请在保持随机性结构的前提下,复现该图像。

```{exercise-end}
```
Expand All @@ -350,7 +344,7 @@ $$
:class: dropdown
```

这是一个解决方案
参考答案

```{code-cell} ipython3
def simulate_og(σ_func, og, y0=0.1, ts_length=100):
Expand Down
Loading