ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Leslie人口增长模型:矩阵年龄结构预测与Python实现

2026/10/3 11:18:04 拓冰建站 浏览量
Leslie人口增长模型:矩阵年龄结构预测与Python实现 简介《Leslie人口增长模型》是一份基于MATLAB软件完成的中国人口增长预测建模方案适合数学建模竞赛选手、统计学爱好者及人口研究者学习参考。资源以一份约988KB的doc文档呈现全文包含问题重述、模型假设、符号说明、模型构建与求解等完整章节系统梳理了Logistic人口阻滞增长模型和按年龄分布的Leslie矩阵模型两种经典方法。文档利用1954年至2005年多组历史数据分别建模对比指出1980—2005年数据拟合效果最佳可决系数达0.9987并预测了2010、2020、2033年总人口规模同时借助Leslie模型预测了2002—2050年劳动年龄人口、老年人口、人口抚养比及老龄化趋势并讨论了育龄妇女人数变化与人口调控措施。文中还给出了模型残差分析、优缺点评价及推广方向便于读者直接复现或借鉴完整建模思路。已有5152人学习下载适合用于数模竞赛备赛或人口增长相关课题研究。1. Leslie人口增长模型为什么做人口预测不能只看总人口做人口预测Leslie人口增长模型是比指数拟合和 logistic 更值得优先掌握的矩阵方法。指数模型只能说“总量大概涨到多少”给不出“未来十年劳动年龄人口占比下降几个点”这类结构性问题。Leslie 模型的思路是把人口按年龄分组把生育率和存活率写进一个投影矩阵用矩阵迭代推出每一组人未来的变化。它适合做区域人口预测、教育学位规划、医疗和养老资源配置这类需要分年龄口径的落地工作。这篇按“模型结构 — 参数估计 — 代码实现 — 趋势判定 — 避坑 — 验证”展开新手能照着跑通熟手可以直接对参数口径和边界做核对。先提醒一句这个模型对参数口径极其敏感组宽差一年、性别比少乘一步结果就可能完全不可用。2. 从生育率和存活率到投影矩阵Leslie 模型的结构和参数口径2.1 年龄组与时间步怎么定组宽差一年矩阵差一个规模Leslie 模型的第一步是把人口按年龄组切分。常见做法是女性单性别模型年龄组等宽比如 0-4 岁、5-9 岁、10-14 岁……每组宽度为 h 年那么模型迭代步长就是 h 年一次。为什么强调女性单性别因为生育数据通常只统计母亲年龄出生性别比又相对稳定把总出生数乘上女婴比例折算成“女婴出生数”模型就只需要追踪女性人口省去两性配对等复杂假设。投影矩阵 L 的结构非常固定第一行是分年龄生育率次对角线是分年龄存活率其余位置为 0/ F1 F2 F3 F4 F5 \ | P1 0 0 0 0 | | 0 P2 0 0 0 | | 0 0 P3 0 0 | \ 0 0 0 P4 0 /矩阵维度等于年龄组数量。组宽是建模时的第一个硬参数如果统计年鉴给的是单岁数据你可以建 1 岁组步长就是 1 年但多数区域数据只公布 5 岁组那就老老实实按 5 岁组、5 年一步迭代。组宽不一致是新手最常见的问题后面专门讲。2.2 从人口年鉴到参数向量存活率与生育率的估算口径生育率向量 F 中第 i 组的值表示“该年龄组内每名女性在一个迭代周期内产下的女婴数”。注意三个口径分子只用女婴分母是该组女性人口时间跨度是整个组宽不是一年。如果统计年鉴给出的是“15-19 岁组女性年出生数”而组宽是 5 年就要把 5 年的出生数累计起来再除以该组平均人数否则数量级少 5 倍。存活率向量 P 中第 i 个值表示“第 i 组活到下一个迭代时点并进入第 i1 组的比例”。最可靠来源是生命表的 lx 列存活率等于 lx5 / lx直接避开年度死亡概率换算的问题。如果没有生命表只有年龄别死亡概率 qx注意 qx 是年度概率5 年存活率不是 1-qx而是 (1-qx) 在 5 年内的累计乘积对高龄组这一步误差非常大。2.3 递推公式与符号含义模型的核心只有一行N(th) L · N(t)。N(t) 是各年龄组人数的列向量L 是投影矩阵。每迭代一次新生人口由第一行生育率与当前各年龄组人数内积得到其他组则由上一组的存活人口平移过来。用表格把这几个符号对清楚符号含义估算来源N_i(t)t 时刻第 i 组女性人口人口普查或抽样推算F_i第 i 组每名女性在 h 年内产下的女婴数分年龄出生数 × 女婴比例 ÷ 该组女性人数P_i第 i 组活过 h 年并进入 i1 组的比例生命表 lx5 / lxh年龄组宽度等于迭代步长按数据公布粒度设定到这里模型已经把“人口增长”从一条总曲线拆成了年龄结构的推移过程。这也是 Leslie 模型和指数模型最本质的区别指数模型假设所有年龄的人同步增长Leslie 模型允许生育期人群和老年人群此消彼长从而暴露老龄化这类结构风险。3. 用 Python 把 Leslie 矩阵跑起来最小迭代代码与参数调法3.1 先拿假数据校准参数向量与初始年龄结构的构造在拿真实年鉴数据之前先用一组假数据把计算链路跑通。下面用 5 个年龄组演示组宽 5 年初始每组分 2000 人。生育率放在 15-24 岁两个组存活率给前 4 组最高组不设出口。import numpy as np # 5 个年龄组组宽 5 岁迭代步长 5 年 G 5 # 生育率组内每名女性在 5 年中产下的女婴总数 # 这里假设 0-4 岁和 5-9 岁不生育10-14 岁开始有少量 F np.array([0.0, 0.04, 0.12, 0.08, 0.0]) # 存活率第 i 组在 5 年后进入第 i1 组的比例 # 最高年龄组是开区间存活者不再进入下一组 P np.array([0.85, 0.90, 0.92, 0.85]) # 构造 Leslie 矩阵 L np.zeros((G, G)) L[0, :] F # 第一行放生育率 for i in range(G - 1): L[i 1, i] P[i] # 次对角线放存活率 # 初始人口向量 N0 np.full(G, 2000.0) N N0.copy() # 迭代 6 次覆盖 30 年 for t in range(6): N L N total N.sum() print(f第{(t 1) * 5}年总人口约 {total:.0f}) print(各组占比 .join(f{v / total:.1%} for v in N))这段代码里有两个关键写法。L[0, :] F用行向量整体赋值保证新生人口等于各组人数乘以对应生育率的加权总和L[i 1, i] P[i]把存活率放在次对角线含义是第 i1 组在下一时点的人口来自第 i 组存活者。而N L N每执行一次代表过去 5 年不是一年。如果你只想看人口总量走势上面这段够用但注意它有一个隐藏假设最高年龄组的人一旦到了下一时点就直接消失因为他们没有进入下一组的出口。这样做在演示里没问题但在真实人口预测里必须写明最高组的处理方式否则老年组人口会被系统性低估。3.2 迭代计算与结果解读增长率从特征值来结构从向量来运行上面代码你会看到两个信息总人口在变化但更重要的是各组占比也在变。比如某几期新生人口减少中间年龄组占比先上升后下降这就是 Leslie 模型独有的“年龄结构惯性”——现在的人口结构决定了未来十到二十年的劳动力供给这个结论仅看总量曲线永远得不到。调参时先改生育率整体缩放。把F整体乘 1.1总人口最终会明显放大把P[1]从 0.90 降到 0.80你会看到 5-9 岁这组进入 10-14 岁组的人数减少其影响要等 5 年才显现出来。这类“延迟效应”是年龄结构模型的核心特征也是做资源规划时必须提前十年看的原因。提示迭代次数要覆盖至少一个世代长度通常 30 年到 50 年。只迭代三五次看不出稳定趋势反而容易被初期波动误导。3.3 用 R 做同样事情矩阵逻辑一致包只是加速R 里做 Leslie 模型最常用的路径是把同样逻辑写成矩阵乘法popbio 包虽然提供了现成的 Leslie 矩阵函数但我不建议直接当黑匣子用——你至少要能手动构造矩阵才能在参数出错时排查。G - 5 F - c(0, 0.04, 0.12, 0.08, 0) P - c(0.85, 0.9, 0.92, 0.85) L - matrix(0, G, G) L[1, ] - F for (i in 1:(G - 1)) { L[i 1, i] - P[i] } N0 - rep(2000, G) N - N0 for (t in 1:6) { N - L %*% N print(paste0(第, t * 5, 年, sum(N))) }R 代码的核心和 Python 版完全一致只是矩阵索引从 1 开始。用%*%做矩阵乘法循环体只有一行。真实项目里R 的优势是后续直接调用popbio::eigen.analysis()算特征值和敏感性Python 则要自己写这几行更短的线性代数。4. 从矩阵特征值看人口趋势增长、稳定与衰退的判定方法4.1 主特征值 λ 的含义与 Perron-Frobenius 边界Leslie 矩阵的特征值决定了人口长期增长率但这里有一个很重要的细节不是所有特征值都有实际意义。按 Perron-Frobenius 定理非负不可约矩阵存在一个最大的实特征值它支配长期行为叫做主特征值 λ₁。λ₁ 大于 1人口长期增长等于 1总量趋于稳定小于 1长期衰退。其他特征值如果是复数会带来年龄结构的阻尼振荡但振荡随着时间衰减长期看 λ₁ 说了算。用 numpy 计算时要注意特征值返回的是复数必须取实部再找最大值w, v np.linalg.eig(L) real_w np.real(w) idx np.argmax(real_w) lambda1 real_w[idx] print(f主特征值 λ1 {lambda1:.4f}) # 稳定年龄结构主特征向量归一化后就是长期各组比例 stable np.real(v[:, idx]) stable stable / stable.sum() print(稳定年龄结构占比, .join(f{x:.1%} for x in stable))主特征向量很有用。归一化之后它告诉你如果生育率和存活率长期不变人口年龄结构最终会逼近什么比例。比如稳定结构里 0-4 岁占比如果特别低说明这个人口即使总增长率为正也会长期偏老龄化。4.2 净繁殖率 R0 怎么算为什么不能只看 λ净繁殖率 R0 在人口学里经常被拿来和 λ₁ 一起看。R0 的计算方式是把各年龄组生育率乘上“活到该组的累积存活率”再求和意思是一个女性一生平均产下的女婴数。R0 大于 1、等于 1、小于 1 分别对应世代更替水平以上、刚好更替、以下。# 累计存活率 lxl0 1, l1 l0 * P0, ... l np.zeros(G) l[0] 1.0 for i in range(G - 1): l[i 1] l[i] * P[i] R0 np.dot(F, l) print(f净繁殖率 R0 {R0:.4f}) # 计算世代长度 T用于理解 λ 和 R0 的关系 T np.sum(F * l * np.arange(G)) / R0 print(f平均世代长度约 {T:.2f} 个步长即 {T * 5:.1f} 年)R0 和 λ₁ 的关系大致是 λ₁ ≈ R0^(1/T)T 是世代长度。两个模型即使 R0 相同如果生育年龄分布不同λ₁ 也会不同。比如一个群体生育集中在 15-19 岁另一个集中在 25-29 岁前者的世代更短λ₁ 更大。所以做预测时不能只报告 R0还要看 λ₁因为 λ₁ 才是真正决定每期增长倍数的量。4.3 稳定年龄结构与老龄化信号的量化看趋势不能只看一个数。把 λ₁、R0 和稳定年龄结构放在一张表里对照能快速判断人口处于什么阶段状态λ₁R0稳定年龄结构特点增长型11低龄组占比高金字塔下宽上窄稳定型≈1≈1各组占比基本恒定总量不增不减衰退型11低龄组收缩老年组相对抬升实际项目中我一般会把这套判定做成一个函数输入 F、P输出 λ₁、R0、世代长度和稳定结构占比然后对照区间给出结论。它不能替代完整的人口模拟但能很快回答“这个人口未来是涨是缩、结构是年轻化还是老龄化”这类方向性问题也方便对不同政策参数做横向比较。5. Leslie 模型避坑参数估错和结构误用最常见的 5 个坑这一章是血泪经验。Leslie 模型的数学不复杂复杂的是数据口径。以下坑我都踩过按“现象 → 原因 → 解决”写清楚。5.1 参数口径类性别比折算、组宽与死亡概率的三种错位坑一出生数没乘女婴比例总人口直接高估。现象是预测总人口比统计公报多出约 3%-5%而且越到后面偏差越大。原因是直接把年鉴里的总出生数放进了 F 的分子但 Leslie 矩阵追踪的是女性人口新生向量必须只包含女婴。解决方法是每个 F_i 在计算时都要乘女婴比例一般取 0.485 左右精确值看当地出生性别比统计。这一步是“少乘一步满盘皆输”的典型。坑二把 1 年出生数当成 5 年组宽的生育总量。现象是新生人口数量级差好几倍总人口增长速度离谱。原因是年鉴的“年龄别生育率”多数是年度指标而组宽是 5 年分子没有累计到 5 年。解决方法是先确认每个 F_i 的时间口径如果年鉴给出的是年度出生数就乘以 5 或者换用“累计生育率”口径。更稳妥的做法是直接用年份相邻两次普查的存活组人口反推 P用出生数除以组内女性人数得到平均每人生育数不依赖现成的生育率表。坑三把年度死亡概率 qx 直接当成 5 年死亡概率。现象是老年组人口衰减过快高年龄组人数异常偏少。原因是年鉴里的 qx 是“一年内死亡概率”不是“5 年内死亡概率”。如果直接用1 - qx作为 P_i等于假定 5 年只死一次显然偏乐观。解决方法是查生命表的 lx 列用lx5 / lx作为 P_i如果只有 qx可以用(1 - qx)^5做近似但高龄组误差仍然不小最好结合生命表校正。5.2 结构假设类迁移缺失、最高组开放区间和 R0 误用坑四完全不考虑迁移长期预测系统性偏离。现象是前 10 年预测还不错第 15 年后总人口明显偏离实际且误差方向稳定。原因是 Leslie 矩阵本质是封闭人口的推演只包含出生和死亡不包含迁入迁出。解决方法是给迭代加一个迁移向量 M(t)每次迭代后N L N M(t)其中 M(t) 的分组值来自近年迁移人口年龄结构。区域级预测里这一步几乎省不掉除非你预测的是严格封闭人群。坑五最高年龄组“开区间”处理不一致导致老年人口结果差异巨大。现象是同一份数据两个人跑出来 80 岁以上人口差出几倍。原因是最高组的人存活后去往哪里没有约定。常见处理有两种一种是把最高组设成开放组存活的人继续留在该组适合描述 80 岁以上高龄人口另一种是存活的人直接移出观测窗口适合只关心到某个年龄为止的情况。解决方法是写代码时明确注释这一行为并在报告里说明最高组口径。我习惯用开放口径因为高年龄组医疗资源规划恰好需要这部分人数。注意R0 只能判断世代更替水平不能直接当作增长率。R0 1 只表示平均每个女性生一个女婴但由于世代长度不同每期增长倍数仍可能偏离 1。要回答“每年涨多少”永远看 λ₁。6. 用扰动分析给 Leslie 矩阵做体检找到影响最大的年龄组做完整模型之后下一步不是急着调参数而是先做一次扰动分析。方法是把某个 F_i 或 P_i 单独调高 1%重新计算 λ₁看它变了多少。变化越大的参数说明它对长期人口增长的控制力越强这就是敏感性分析。def compute_lambda(F, P): G len(F) L np.zeros((G, G)) L[0, :] F for i in range(G - 1): L[i 1, i] P[i] return np.max(np.real(np.linalg.eig(L)[0])) base compute_lambda(F, P) for i in range(G): if F[i] 0: dF F.copy() dF[i] * 1.01 print(f生育率组 {i}: λ 变化 {compute_lambda(dF, P) - base:.5f}) for i in range(len(P)): dP P.copy() dP[i] * 1.01 print(f存活率组 {i}: λ 变化 {compute_lambda(F, dP) - base:.5f})这段代码的价值是帮你把有限的政策资源投到最关键的位置。我在第一次做区域人口预测时只盯着生育率调参数结果敏感性分析一跑发现低年龄组的存活率对 λ₁ 的贡献根本不低甚至超过部分生育率项。尤其是婴儿和儿童组存活率改善它的杠杆作用往往被忽略。从那以后我养成了一个习惯任何 Leslie 模型跑完先做敏感性分析再做策略讨论。这个习惯也推荐给你希望帮到你。本文还有配套的精品资源点击获取