40. 就业的湖泊模型#
40.1. 大纲#
除了 Anaconda 中包含的内容外,本讲座还需要以下库:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
FONTPATH = "fonts/SourceHanSerifSC-SemiBold.otf"
mpl.font_manager.fontManager.addfont(FONTPATH)
plt.rcParams['font.family'] = ['Source Han Serif SC']
40.2. 湖泊模型#
这个模型有时被称为湖泊模型,因为存在两个工人群体:
当前就业的工人。
当前失业但正在寻找工作的工人。
两个”湖泊”之间的”流动”如下:
工人以
的比率退出劳动力市场。新工人以
的比率进入劳动力市场。就业工人以
的比率与工作分离。失业工人以
的比率找到工作。
下图说明了湖泊模型。

Fig. 40.1 湖泊模型的示意图#
40.3. 动态变化#
设
工人总人口为
因此,失业和就业工人的数量按以下方式变化:
我们可以将(40.1)整理为矩阵形式的线性方程组
假设在
那么,
因此,该系统的长期结果可能取决于初始条件
我们关心
失业率和就业率从长期来看会如何变化?
长期结果是否取决于初始值
40.3.1. 可视化长期结果#
让我们首先绘制失业率
class LakeModel:
"""
求解湖泊模型并计算失业存量和失业率的动态变化。
参数:
------------
λ:标量
当前失业工人的找到工作的比率
α:标量
当前就业工人的解雇率
b:标量
进入劳动力市场的比率
d:标量
退出劳动力市场的比率
"""
def __init__(self, λ=0.1, α=0.013, b=0.0124, d=0.00822):
self.λ, self.α, self.b, self.d = λ, α, b, d
λ, α, b, d = self.λ, self.α, self.b, self.d
self.g = b - d
g = self.g
self.A = np.array([[(1-d)*(1-λ) + b, α*(1-d) + b],
[ (1-d)*λ, (1-α)*(1-d)]])
self.ū = (1 + g - (1 - d) * (1 - α)) / (1 + g - (1 - d) * (1 - α) + (1 - d) * λ)
self.ē = 1 - self.ū
def simulate_path(self, x0, T=1000):
"""
模拟就业和失业的序列
参数
----------
x0:数组
包含初始值 (u0,e0)
T:整数
模拟的周期数
返回值
----------
x:迭代器
包含就业率和失业率的序列
"""
x0 = np.atleast_1d(x0) # 重新转换为数组
x_ts= np.zeros((2, T))
x_ts[:, 0] = x0
for t in range(1, T):
x_ts[:, t] = self.A @ x_ts[:, t-1]
return x_ts
lm = LakeModel()
e_0 = 0.92 # 初始就业
u_0 = 1 - e_0 # 给定初始 n_0 = 1 的情况下的初始失业率
lm = LakeModel()
T = 100 # 模拟时长
x_0 = (u_0, e_0)
x_path = lm.simulate_path(x_0, T)
fig, axes = plt.subplots(3, 1, figsize=(10, 8))
axes[0].plot(x_path[0, :], lw=2)
axes[0].set_title('失业')
axes[1].plot(x_path[1, :], lw=2)
axes[1].set_title('就业')
axes[2].plot(x_path.sum(0), lw=2)
axes[2].set_title('劳动力')
for ax in axes:
ax.grid()
plt.tight_layout()
plt.show()
不出所料,我们观察到劳动力
这与只有一个流入源(新进入者池)流向失业和就业池的事实相吻合。
从长期来看,劳动力市场系统的流入和流出是由劳动力市场的恒定退出率和进入率决定的。
具体来说,令
我们可以得出
因此,
此外,失业和就业的时间序列似乎在长期内以某些稳定的速率增长。
40.3.2. 佩龙-弗罗贝尼乌斯定理的应用#
从直觉上讲,如果我们将失业池和就业池视为一个封闭系统,其增长应该与劳动力相似。
接下来我们要问,
如果我们应用佩龙-弗罗贝尼乌斯定理,答案将更加清晰。
佩龙-弗罗贝尼乌斯定理的重要性源于以下事实:
首先,在现实世界中,我们遇到的大多数矩阵都是非负矩阵。
其次,许多重要模型只是线性迭代模型,它们从初始条件
这个定理有助于描述主特征值
40.3.2.1. 主导特征向量#
现在我们学习如何运用佩龙-弗罗贝尼乌斯定理来帮助我们分析湖泊模型。
由于
谱半径
是 的一个特征值,其中
任何其他特征值
的绝对值都严格小于 : ,存在唯一且处处正的右特征向量
(列向量)和左特征向量 (行向量):
如果进一步假设
是正的,那么当 时,我们有
最后一个陈述意味着长期来看,
因此,长期来看,
回想一下,谱半径受列和的约束:对于
注意,对于
令
佩龙-弗罗贝尼乌斯定理意味着存在唯一的正特征向量
由于
这个主特征向量在确定长期结果方面起着重要作用,如下所示。
def plot_time_paths(lm, x0=None, T=1000, ax=None):
"""
绘制模拟的时间序列图。
参数
----------
lm : 类
湖泊模型
x0 : 数组
包含一些不同的初始值。
T : 整数
要模拟的周期数
"""
if x0 is None:
x0 = np.array([[5.0, 0.1]])
ū, ē = lm.ū, lm.ē
x0 = np.atleast_2d(x0)
if ax is None:
fig, ax = plt.subplots(figsize=(10, 8))
# 绘制线$D$
s = 10
ax.plot([0, s * ū], [0, s * ē], "k--", lw=1, label='设置$D$')
# 设置通过原点的坐标轴
for spine in ["left", "bottom"]:
ax.spines[spine].set_position("zero")
for spine in ["right", "top"]:
ax.spines[spine].set_color("none")
ax.set_xlim(-2, 6)
ax.set_ylim(-2, 6)
ax.set_xlabel("失业人群")
ax.set_ylabel("就业人群")
ax.set_xticks((0, 6))
ax.set_yticks((0, 6))
# 绘制时间序列
for x in x0:
x_ts = lm.simulate_path(x0=x)
ax.scatter(x_ts[0, :], x_ts[1, :], s=4,)
u0, e0 = x
ax.plot([u0], [e0], "ko", ms=2, alpha=0.6)
ax.annotate(f'$x_0 = ({u0},{e0})$',
xy=(u0, e0),
xycoords="data",
xytext=(0, 20),
textcoords="offset points",
arrowprops=dict(arrowstyle = "->"))
ax.plot([ū], [ē], "ko", ms=4, alpha=0.6)
ax.annotate(r'$\bar{x}$',
xy=(ū, ē),
xycoords="data",
xytext=(20, -20),
textcoords="offset points",
arrowprops=dict(arrowstyle = "->"))
if ax is None:
plt.show()
lm = LakeModel(α=0.01, λ=0.1, d=0.02, b=0.025)
x0 = ((5.0, 0.1), (0.1, 4.0), (2.0, 1.0))
plot_time_paths(lm, x0=x0)
由于
这个集合
图中说明了对于两个不同的初始条件
这表明所有这样的序列在长期内都具有很强的相似性,由主特征向量
40.3.2.2. 负增长率#
在上面说明的例子中,我们考虑的参数使得劳动力的总体增长率
现在假设我们面临
这意味着
现在迭代序列
这在下面进行了可视化。
因此,虽然迭代序列仍然朝着主特征向量
这是由于
这引导我们到下一个结果。
40.3.3. 性质#
由于
佩龙-弗罗贝尼乌斯理论告诉我们
因此,对于任何
当
我们看到,在长期内,
此外,长期失业和就业是
后者意味着
具体来说,当
为了说明这些比率的动态,令
比率的动态遵循
注意
我们可以验证
此外,对于任何
我们用下面的代码来说明
lm = LakeModel()
e_0 = 0.92 # 初始就业
u_0 = 1 - e_0 # 给定初始 n_0 = 1 的情况下的初始失业率
lm = LakeModel()
T = 100 # 模拟时长
x_0 = (u_0, e_0)
x_path = lm.simulate_path(x_0, T)
rate_path = x_path / x_path.sum(0)
fig, axes = plt.subplots(2, 1, figsize=(10, 8))
# 绘制稳态 ū 和 ē
axes[0].hlines(lm.ū, 0, T, 'r', '--', lw=2, label='ū')
axes[1].hlines(lm.ē, 0, T, 'r', '--', lw=2, label='ē')
titles = ['失业率', '就业率']
locations = ['lower right', 'upper right']
# 绘制失业率和就业率
for i, ax in enumerate(axes):
ax.plot(rate_path[i, :], lw=2, alpha=0.6)
ax.set_title(titles[i])
ax.grid()
ax.legend(loc=locations[i])
plt.tight_layout()
plt.show()
为了能更直观地理解收敛性,我们在下面不使用佩龙-弗罗贝尼乌斯定理进一步解释收敛过程。
假设
令
比率的动态遵循
考虑
那么,我们有
因此,我们得到
由于
因此,收敛过程遵循
由于
在这种情况下,
40.4. 练习#
Exercise 40.1 (失业率和就业率的演化)
如果分离率
这个结果是否符合你的直觉?
绘制图表来说明直线
Solution to Exercise 40.1 (失业率和就业率的演化)
方程 (40.3) 表明,如果
首先假设
假设
下图说明了直线
fig, ax = plt.subplots(figsize=(10, 8))
lm = LakeModel(α=0.01, λ=0.1, d=0.02, b=0.025)
plot_time_paths(lm, ax=ax)
s=10
ax.plot([0, s * lm.ū], [0, s * lm.ē], "k--", lw=1, label='固定 $D$, α=0.01')
lm = LakeModel(α=0.04, λ=0.1, d=0.02, b=0.025)
plot_time_paths(lm, ax=ax)
ax.plot([0, s * lm.ū], [0, s * lm.ē], "r--", lw=1, label='固定 $D$, α=0.04')
ax.legend(loc='best')
plt.show()