☰
Logistic与Leslie人口预测:年龄结构、老龄化与MATLAB实现
2026/11/4 21:07:14 网站建设 项目流程

简介:《Leslie人口增长模型》是一份面向人口统计学、数学建模学习者与竞赛参赛者的文档,围绕中国人口总量及年龄结构预测展开,重点解决Logistic阻滞增长模型与Leslie矩阵模型在中期、长期预测中的建模与比较问题。压缩包内含1个doc文件,大小约988KB,便于直接查阅完整推导、数据整理与结果分析。文档以1980—2005年人口数据建立Logistic模型,给出2010、2020、2033年总量预测;又按年龄分布构造Leslie矩阵,讨论劳动年龄人口、老年人口、抚养比、老龄化及育龄妇女人数变化,并完成残差分析、优缺点评价与推广。读者可据此理解两类模型的假设、参数设置、MATLAB实现思路和预测指标口径,也能参考其数据组织与论文式写作框架。目前已有5157人学习,适合需要人口预测案例、数学建模论文范本或课程作业参考的读者。

1. 从“预测一个数”到“预测一张年龄表”:这道题真正要交付什么

拿到人口增长预测这类题目,多数人的第一反应是找条曲线把历年总人口拟合出来,交一个 2030 年的数字就收工。我第一次也是这么做的,直到把题目翻到第二问才发现不对:老龄化、人口抚养比、劳动年龄人口、育龄妇女人数,这些指标没有一个是“总人口”能推出来的。Leslie 人口增长模型 解决的正是这件事——它不预测一个数,而是预测一整个年龄分布,再从这个分布里派生所有结构指标。这套方案适合两类人:要交数学建模课设、统计建模毕设的学生,以及需要用年龄结构做中长期测算的从业者。下面按我实际做下来的顺序拆:数据怎么对齐口径,Logistic 怎么定参数,Leslie 矩阵怎么组装,最后怎么验收答辩。

2. 数据底账与路线分工:把千万、亿和抽样比先对齐

2.1 三份数据的量级差在哪

这道题的数据其实有三层,量级完全不同,混在一起算必然出错。第一层是历年总人口表,1954 年到 2005 年逐年给出,单位是千万,比如 1954 年 60.2、1980 年 98.705、2005 年 130.756,换算成亿就是 6.02 亿、9.8705 亿、13.0756 亿。第二层是 2001 年的人口抽样调查数据,分市、镇、乡给出男女人数:城市男 147907、城市女 147465、镇男 80279、镇女 77976、乡男 394690、乡女 372242,六项加起来 1220559 人。第三层是抽样数据里的各种比率,分年龄女性占比、分年龄生育率、分年龄死亡率、出生性别比,全是比率,没有绝对数。

关键在第一层和第二层之间。1220559 是抽样人数,全国 2001 年总人口是 127.627 千万也就是 12.7627 亿,两者差三个数量级。通常的做法是先用抽样人数算出市、镇、乡各自占抽样的比重,再乘全国总人口,得到三段各自的全国总量。按上面这组数算,城市约占 24.20%、镇约占 12.97%、乡约占 62.83%,对应全国 3.089 亿、1.655 亿、8.019 亿。这个折算步骤一定要单独写成一小节,因为它同时是后面所有分年龄人数计算的入口,口径错一步,Leslie 矩阵整个就是错的。

2.2 两条建模路线各自回答什么问题

维度模型Ⅰ Logistic模型Ⅱ Leslie
状态量总人口一个标量分年龄女性人口向量
核心参数环境容量 K、内禀增长率 r生育女儿数 b、存活率 s
数据需求历年总人口序列分年龄生育率、死亡率、性别比
能回答总量中短期趋势总量、劳动年龄人口、老龄化、抚养比
主要风险外推边界不清数据质量敏感、参数修正争议

两条线不是二选一,是互相校验。Logistic 参数少、可解释性强,但推不出任何结构信息;Leslie 能派生全套指标,可它对生育率的准确性极其敏感,稍有偏差峰值年份就能漂十年。我的做法是让两条线都算总人口,差值控制在 1 个百分点以内就互相当背书,差太多就回去查数据而不是硬写结论。

2.3 假设清单要写到“能被追问”的程度

原题给了四条假设:社会稳定不发生重大灾害和战争;90 岁以上妇女统一按 90 岁计;较短时间内平均年龄变化较小可认为不变;不考虑移民。这四条不能只是罗列,每条后面都得跟一句它对模型的实际影响。

第一条决定了 Logistic 的 K 在整个预测期内是常数,一旦中途出现大的外部冲击,K 就得重估。第二条是为了把年龄组截断在 91 组,否则矩阵维度不封闭,代价是高龄段的死亡信息被压缩,对老龄化指标的高龄部分会有轻微低估。第三条约束的是生育率和死亡率不随时间变化,这直接导致后面峰值年份可能偏早——因为真实场景里生育率是持续下行的。第四条省掉了迁移项,对全国口径影响不大,但如果换成省市口径这套模型就直接失效。这四条写清楚,答辩时被问到“你的假设合理吗”就有话可接。

3. 模型Ⅰ的落地:Logistic 三段拟合与可决系数选优

3.1 阻滞增长方程的推导与参数含义

Logistic 的出发点是把指数增长里的常数增长率改成一个随人口数量下降的函数。设人口为 x(t),最大容量为 K,则增长率写成 r(1 - x/K),微分方程为:

dx/dt = r·x·(1 - x/K)

分离变量积分后得到解析解:

x(t) = K / (1 + (K/x₀ - 1)·e^(-r·t))

三个参数各管一件事:K 是环境能容纳的人口上限,曲线最终会贴着它走;r 决定上升段的陡峭程度,r 越大越早接近 K;x₀ 是初始年份的人口,把曲线整体平移。拟合的本质就是用最小二乘去搜这三个参数,让曲线和实测点残差平方和最小。

判断拟合好坏用可决系数 R² = 1 - Σ(残差²)/Σ((x - x̄)²),越接近 1 越好。另一个更直观的指标是残差绝对值之和 Σ|残差|,单位跟人口一样是千万,能直接看出平均偏了多少。

3.2 nlinfit 的初值怎么给才收敛

nlinfit做的是非线性最小二乘,它不保证全局收敛,初值给偏了要么报错要么收敛到局部极小。可行的办法是先从曲线上挑两个时间跨度较大的点,反解出 K 和 r 作为初值。下面这段是 1954 年起点那组的写法,思路三段通用,只是换 x₀ 和起止年份:

% 模型Ⅰ:1954—2005 年总人口 Logistic 拟合 t = 0:51; % 1954 记为 t=0 x = [60.2 61.5 62.8 64.6 66 67.2 66.2 65.9 67.3 69.1 ... 70.4 72.5 74.5 76.3 78.5 80.7 83 85.2 87.1 89.2 ... 90.9 92.4 93.7 95 96.259 97.5 98.705 100.1 101.654 ... 103.008 104.357 105.851 107.5 109.3 111.026 112.704 ... 114.333 115.823 117.171 118.517 119.85 121.121 122.389 ... 123.626 124.761 125.786 126.743 127.627 128.453 129.227 ... 129.988 130.756]; % 单位:千万 % 用两个远端点反解初值:t=5 对应 67.2,t=20 对应 90.9 x0 = x(1); syms c d eq1 = c/(1+(c/x0-1)*exp(-5*d)) == 67.2; eq2 = c/(1+(c/x0-1)*exp(-20*d)) == 90.9; sol = solve([eq1, eq2], [c, d]); b0 = [double(sol.c), double(sol.d)]; % 初始参数 fun = @(b,t) b(1)./(1+(b(1)/x0-1).*exp(-b(2).*t)); [b1, r1] = nlinfit(t, x, fun, b0); % b1 为拟合参数,r1 为残差 Rsq = 1 - sum(r1.^2) / sum((x-mean(x)).^2); % 可决系数 W = sum(abs(r1)); % 残差绝对值之和

几点说明。第一行t = 0:51里 0 对应 1954 年,所以 2005 年是 t=51,共 52 个点,和 x 的长度必须一致,少一个 MATLAB 直接报维度不匹配。syms那三行是反解初值,新版 MATLAB 的solve必须先声明符号变量,老版本可以直接传字符串,这里按新语法写。nlinfit返回三个值,第三个是雅可比矩阵,实际用不上,只取前两个。Rsq这里对残差平方和取了sum,如果照抄某些写法直接写1 - r1.^2/(x-mean(x)).^2得到的是一个向量,那是个典型翻车点,后面会讲。

1954 年这组跑出来 K≈180.9871、r≈0.0336,残差绝对值之和 57.9992。

3.3 三个起点为什么结论差这么多

换起点重跑同一套代码,1963 年起点得到 K≈151.4513、r≈0.0484,残差绝对值之和 27.8046;1980 年起点残差绝对值之和降到 10.1699,可决系数 0.9987。三组结果放在一张表里看:

拟合起点数据跨度残差绝对值之和可决系数判断
195452 年57.9992未单列残差非正态,拟合不可靠
196343 年27.8046未单列残差大致对称,效果较好
198026 年10.16990.9987最优,采用

差距的根源不在算法,在数据本身。1954 到 1962 这一段,前期有一次出生高峰,中间几年人口数据出现明显回落,随机误差压根不服从正态分布,而最小二乘法恰恰依赖这个前提,所以拟合再漂亮也不能用。1963 年之后增长基本遵循自然规律,误差分布接近对称,但那时段的生育行为和后面差别太大,混在一起会把曲线拉偏。1980 年以后生育行为进入相对稳定的阶段,没有大的外部扰动,残差围绕零轴上下波动,图形基本对称,这才是最小二乘能发挥的前提。

提示:换起点不是为了凑一个好看的可决系数,而是为了让“随机误差服从正态分布”这个前提成立。先画残差图再决定用哪段数据,顺序不能反。

3.4 外推边界与专家报告对表

用 1980 年那组参数外推,得到 2010 年 13.55357 亿、2020 年 14.18440 亿、2033 年 14.70172 亿。附件 1 的研究报告给出的参照值是 2010 年 13.6 亿、2020 年 14.5 亿、2033 年前后达峰 15 亿左右。2010 年差 0.05 亿,2020 年差 0.32 亿,2033 年差 0.3 亿,相对误差都在 2% 出头。

这个误差量级是可以接受的,但必须说清楚它的性质:Logistic 给的是趋势上限,不是年度精确值。它的强项是告诉你“大概什么时候增速会明显放缓”,弱项是它完全看不到年龄结构,一旦生育行为在预测期内发生跳变,曲线就只会在错误的 K 上平移。所以这个结果在方案里的定位是交叉校验项,真正的结构指标要靠下一个模型。

4. 模型Ⅱ的落地:Leslie 矩阵组装、迭代与结构指标派生

4.1 年龄组划分与女性状态向量

Leslie 的核心是把人口按年龄切成等宽的小段,只跟踪女性。这个选择不是偷懒:决定下一代数量的是育龄妇女的人数和她生几个女儿,男性数量不直接进入生育方程,用女性单性别模型就能闭环。男性人口靠出生性别比和对应存活率另算,或者直接用女性占比反推总人口,后者简单但会损失一点精度。

划分上,按 1 岁一组切 0 到 90 岁,90 岁以上统一并入最后一组,一共 91 个年龄组。状态向量 v(t) 的第 i 个分量表示 t 时刻第 i 年龄组的女性人数,时间步长取 1 年,和年龄组宽度一致。为什么不按 5 岁或 10 岁分组?因为育龄妇女的高峰年龄段集中在 20 到 29 岁,组宽一旦到 5 岁,这个峰的形态就被抹平了,而后面判断“生育旺盛期育龄妇女峰值出现在哪一年”恰恰依赖这个峰的细节。

4.2 生育率折算:从“生育率”到“平均生育女儿数”

附件给的是分年龄生育率,含义是某年龄组每个妇女平均生育的孩子数,这里面男女都有。Leslie 矩阵第一行要的是“每个女性平均生育的女儿数”,中间差一个出生性别比的折算。

% 1) 生育率折算为“每个女性平均生育的女儿数” % fr(i): 第 i 年龄组的分年龄生育率(含男婴),有效区间为 15~49 岁 % sr(i): 第 i 年龄组的出生性别比,口径为“女=100 时的男婴数” girl_ratio = 100 ./ (100 + sr); % 女婴占出生人数的比例 b_raw = fr .* girl_ratio; % 每个女性平均生育的女儿数 % 2) 与更替水平对齐做整体修正 tfr = sum(fr); % 原始总和生育率 scale = 1.8 / tfr; % 目标是更替水平 1.8 b = b_raw * scale; % 3) 补零到 91 维,只有 15~49 岁非零 b_full = zeros(1, 91); b_full(16:50) = b; % 索引 16 对应 15 岁

这段的关键在第二步。按原始生育率算出来的总和生育率明显低于 1.8,直接拿去迭代,人口会以不合理的速度塌下去。更替水平 1.8 是外部给定的参照,把整条生育率曲线按比例缩放到这个水平,是常见的修正做法。但修正要有边界:缩放是等比例的,意味着假设各年龄组生育率被同等程度低估,这在数据整体偏低时勉强成立,如果只是某个年龄段异常,就得逐段修而不是整体乘系数。这一点在答辩时很容易被追问。

注意:b_full(16:50) = b这个索引对应关系必须和后面计算抚养比时的年龄切分严格一致,错一位整个结果都不可信。索引 1 代表 0 岁,索引 16 代表 15 岁,这个约定要在代码开头写死。

4.3 存活率与 Leslie 矩阵的组装

存活率等于 1 减死亡率,市、镇、乡三套数据按人口占比加权合并:

% s(i): 第 i 年龄组女性活到 i+1 岁的存活率 s_city = 1 - dr_city; s_town = 1 - dr_town; s_vil = 1 - dr_vil; w = [P_city, P_town, P_vil] / (P_city + P_town + P_vil); % 三段人口权重 s = w(1)*s_city + w(2)*s_town + w(3)*s_vil; % 组装 Leslie 矩阵:91×91 n = 91; L = zeros(n); L(1, :) = b_full; % 第一行:各年龄组女性的生育女儿数 for i = 2:n L(i, i-1) = s(i-1); % 次对角线:上一组活到下一组的存活率 end

矩阵的结构很固定:第一行全是生育项,次对角线全是存活项,其余位置全零。合法性条件是所有 b ≥ 0、所有 s 落在 0 到 1 之间,且至少有一个 b 大于零,满足这三条它才是一个合格的 Leslie 矩阵,否则迭代出来的人数会出现负数。组装完可以用sum(L(1,:))快速核对总和生育率有没有落在合理区间。

按月或按岁迭代就是把矩阵反复左乘初始向量:

v = v0; % 2001 年女性分年龄人数,91×1 列向量 T = 49; % 预测到 2050 年 V = zeros(n, T+1); V(:,1) = v; for k = 1:T V(:,k+1) = L * V(:,k); % 逐年推进 end female_share = 0.4897; % 2001 年女性占总人口比例 total = sum(V, 1) / female_share; % 反推总人口,单位:人

v0的来源是把 4.2 里的分年龄女性占比乘上三段各自的全国人口再合并,这一步涉及的中间表比较长,通常用 Excel 先整理成 91 行再导进 MATLAB,比在脚本里硬拼可读性好得多。female_share取 0.4897 是按抽样数据里女性人数 597683 除以总抽样人数 1220559 得来的,用它作常数反推总人口是简化处理,误差在 1% 量级,写进假设里就行。

4.4 结构指标派生:老龄化、抚养比与育龄妇女

有了逐年分年龄女性人数,题目要的所有指标都能从同一个矩阵里切出来:

for k = 1:T+1 vk = V(:,k); child = sum(vk(1:15)); % 0~14 岁 labor = sum(vk(16:65)); % 15~64 岁 old60 = sum(vk(61:end)); % 60 岁及以上 old65 = sum(vk(66:end)); % 65 岁及以上 dep(k) = (child + old65) / labor; % 总抚养比 ratio60(k) = old60 / sum(vk); % 60 岁以上占比 ratio65(k) = old65 / sum(vk); % 65 岁以上占比 fertile(k) = sum(vk(16:50)); % 15~49 岁育龄妇女 peak(k) = sum(vk(21:30)); % 20~29 岁生育旺盛期 end

跑出来的结果:总人口 2010 年 14.2609 亿、2020 年 14.9513 亿、2023 年达峰 14.985 亿、2033 年回落到 14.7455 亿。15 到 64 岁劳动年龄人口 2010 年 10.4421 亿,2013 年达到高峰 10.4852 亿后转降。老龄化方面,2001 年 60 岁以上 1.5538 亿占 11.5693%,2020 年升到 2.907 亿占 19.443%,65 岁以上 2020 年 2.0628 亿占 13.797%;本世纪 40 年代中后期进入老龄高峰平台,60 岁以上达 4.45 亿占 33.277%,65 岁以上达 3.51 亿占 25.53%。抚养比全程呈上升趋势。

这里有个必须解释的偏差:Leslie 给出的峰值年份比附件报告早了大约十年。排查下来有两条原因,一是出生性别比里女性占比偏小,二是反算出的总和生育率只有 1.42 左右,离专家给的 1.8 差得远,说明原始分年龄生育率数据本身偏低,修正后峰值自然前移。这个偏差要在报告里主动写出来,而不是藏起来。

4.5 生育率灵敏度:k 取 1.6 到 2.2 会怎样

把所有分年龄生育率整体乘上一个系数,让总和生育率分别等于 1.6、1.8、2.0、2.2,重跑四遍迭代,能看出政策的敏感区间:

for k = [1.6, 1.8, 2.0, 2.2] Lk = L; Lk(1,:) = b_full * (k / 1.8); % 按目标总和生育率整体缩放 Vk = zeros(n, T+1); Vk(:,1) = v; for j = 1:T Vk(:,j+1) = Lk * Vk(:,j); end total_k = sum(Vk,1) / female_share; % 同一套循环里顺手算老龄化和抚养比,存到不同列 end

k=1.6 时人口增长缓慢,达峰后很快转入较明显的负增长,同期老龄化速度最快;k=2.2 时总量一路膨胀,峰值推后且回落平缓,年龄结构反而更稳。只有 k 落在 1.8 附近,总量和结构才同时处在可接受区间。这组对比是整篇里最有说服力的部分,因为它直接回答了“政策该往哪个方向调”——只看总量控制会把老龄化推快,只看老龄化放任增长又会让资源环境承压,中间那个平衡点就是靠这四条曲线夹出来的。

顺着这个思路还能往下改一步:把矩阵第一行写成 b_i = β·h_i,其中 β 是平均生育胎数、h_i 是归一化后的生育模式,通过调整结婚年龄和两胎间隔去改 h_i 的形状,就能在不改总量的前提下微调年龄结构。这一步属于模型推广,写进报告的“改进方向”里比硬塞进主模型更合适。

5. 避坑与排查:五个让预测结果翻车的典型场景

5.1 建模阶段的三个坑

坑一:可决系数算出来是一个向量。

现象是Rsq打印出来一片小数,几百个数,看着像出错又不像。原因是照抄了1 - r1.^2/(x-mean(x)).^2这种向量化写法,MATLAB 按元素逐个相除,得到的当然是向量。解决是把分子分母都聚合成标量:1 - sum(r1.^2)/sum((x-mean(x)).^2)。这个坑的隐蔽之处在于向量里的数看起来也像那么回事,不检查维度根本发现不了。

坑二:换起点后参数不收敛,报“迭代次数超限”。

现象是nlinfit直接抛错或者给出明显离谱的 K,比如负数。原因几乎都是初值给偏了,尤其 K 的初值如果比实测最大值还小,函数会在迭代中撞到奇异点。解决是先用两个远端数据点反解初值,或者干脆把 K 的初值设成实测最大值的 1.2 到 1.5 倍,r 给 0.02 到 0.05 之间,再让算法自己找。

坑三:Leslie 迭代几轮之后人数变成负数。

现象是V里出现负值,后面所有指标全废。原因通常是存活率算错了,比如把死亡率当成存活率直接用,或者某年龄组死亡率因为数据缺失被填成了大于 1 的值。解决是在组装矩阵前加一道断言:assert(all(s >= 0 & s <= 1) && all(b_full >= 0)),把非法值挡在迭代之外。另外 90 岁以上合并那一组的存活率要单独设,不能沿用普通组的公式。

5.2 实现与结果解读的两个坑

坑四:年龄组索引整体错一位。

现象是老龄化比例看起来偏低或偏高,但曲线形状又很合理,很难一眼看出问题。原因是“索引 1 代表 0 岁”这个约定在生育率补零、抚养比切分、育龄妇女统计三处没有统一,某处用了 1 代表 1 岁。解决是把年龄切分写成一组常量放在脚本开头,所有地方引用常量而不是写死数字,比如IDX_CHILD = 1:15; IDX_LABOR = 16:65;,改一处全局生效。

坑五:拿 Logistic 的年度值去和 Leslie 的年度值逐点比较。

现象是两条曲线在个别年份差了零点几亿,就被判定为“模型有严重问题”。原因是两个模型的性质根本不同:Logistic 是在平滑趋势上外推,Leslie 是在年龄结构上做递推,后者会因为某一年的出生高峰在二十年后传导出一个劳动力高峰,前者完全看不到这种波动。正确的比较口径是看长期趋势和达峰年份,或者看两者在 2020、2030 这类节点上的相对偏差是否在 5% 以内。

提示:这五条里前三条会让程序跑不出结果,后两条会让结果看起来正常但结论是错的。后者更危险,因为没有人会去复查一个“跑通了”的程序。

6. 验收与答辩:用三张表把模型的可信度讲清楚

验收这类方案,我一般不看代码有多长,只看三张表能不能拿出来。

第一张是参数表。Logistic 那边列清楚三个起点的 K、r、残差绝对值之和、可决系数;Leslie 那边列清楚总和生育率修正前后的值、女性占比、矩阵维度和合法性检查结果。这张表的作用是证明“我的每个参数都有来源”,而不是随手填的。

第二张是预测对照表。把两个模型在 2010、2020、2030、2033、2040 这几个节点上的总人口预测值并列,再把附件报告给的参照值放在第三列,最右边加一列相对偏差。偏差超过 3% 的年份要能当场解释原因,比如“这个年份 Leslie 偏高是因为 1985 到 1990 年的出生高峰在二十年后传导成了育龄妇女高峰”。

第三张是结构指标表。60 岁以上占比、65 岁以上占比、总抚养比、劳动年龄人口、育龄妇女人数,每个指标给 2001 年实测、2020 年预测、峰值年份预测三列。这张表是评委最爱追问的地方,因为它直接对应题目第二问,把这张表讲透,基本就赢了一半。

答辩环节最常见的四个追问,提前准备好答案:为什么选 1980 年作起点——因为要保证随机误差服从正态分布,前两段数据里有明显的外部扰动;可决系数 0.9987 是不是过拟合——26 个数据点拟合 2 个参数,自由度足够,而且残差图对称,不是靠加参数堆出来的;Leslie 为什么只用女性——生育方程只依赖育龄妇女,男性靠性别比和存活率另算;生育率整体缩放修正合理吗——合理的前提是各年龄组被同等程度低估,这一点要主动说明是假设,并给出灵敏度分析作为佐证。

还有一个技巧值得单独说:把“两模型总人口预测差值”做成一张对照图,答辩时直接摊开讲。差值小的地方说明两条独立路线互相印证,差值大的地方就是模型分歧点,主动指出分歧比等评委指出来强得多。我吃过一次亏,当时把一个 5% 的偏差藏在了附录里,结果被翻出来问了十分钟,从那以后我每次做多模型对照,都强制把差值单独画一张图放在正文,宁可自己先承认,也不给别人挖的机会。

希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询