ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

人口预测模型实战:Logistic拟合与Leslie矩阵的MATLAB实现

人口预测模型实战:Logistic拟合与Leslie矩阵的MATLAB实现

简介:一份面向数学建模竞赛参与者与人口统计研究者的中文技术文档,主题是中国人口增长预测建模。文档系统介绍了两种经典模型:Logistic人口阻滞增长模型与按年龄分布的Leslie模型,并运用MATLAB软件进行数据处理与模型求解。其中Logistic模型利用1954年至2005年多组总人口数据对比拟合效果,得出1980-2005年数据可决系数达0.9987,并预测2010年、2020年、2033年总人口分别约13.55亿、14.18亿、14.70亿;Leslie模型则按年龄结构构建矩阵,预测出人口峰值约14.985亿出现在2023年前后,并分析了老龄化与人口抚养比趋势。压缩包内仅含1个Word文档,大小988KB,内容包含问题重述、模型假设、符号说明、模型建立与求解、残差分析与改进建议等完整章节。目前已有5154人学习浏览,既有理论推导又有数据演示,适合作为建模论文写作、课程设计或备赛研读的参考。

1. 人口预测模型的两种实现:从Logistic拟合到Leslie矩阵

人口增长预测是数学建模里绕不开的经典题型,也是很多量化分析课程的实战项目。这套《Leslie人口增长模型》同时覆盖了Logistic人口阻滞增长模型和按年龄分布的Leslie矩阵模型,预测时间跨度从2001年到2050年,输出指标包括总人口、劳动年龄人口、老年人口占比、人口抚养比和育龄妇女人数。和网上那些只给一个公式的Demo不同,这份资料里有完整的建模思路、数据表、可决系数、残差分析和灵敏度分析,适合正在备赛的学生,也适合需要用MATLAB做时序预测的从业者。模型I用三组不同起始年份的数据拟合,模型II从生育率修正到Leslie矩阵构造全流程走通,我能说清楚每一步在算什么、参数卡在哪、结果为什么和专家预测有偏差。

2. 阻滞增长模型的拟合套路:三组数据对比与参数标定

2.1 Logistic方程的核心逻辑

人口增长不能永远按指数走,自然资源和环境容量会给增长率踩刹车。Logistic模型的做法是把人口增长率写成人口的减函数,最常见的是线性递减假设。

设人口数量为x(t),最大容量为x_m,方程可以写成:

dx/dt = r * x * (1 - x / x_m)

这个方程的解是:

x(t) = x_m / (1 + (x_m / x_0 - 1) * exp(-r * t))

这里x_0是初始年份的人口数,r是内禀增长率,x_m是环境容纳量。关键在于,这个模型只需要三个参数就能描述一条S形增长曲线,但参数对初始数据极其敏感。原题里先用了1954年到2005年的全量数据拟合,可决系数虽然看着不错,残差绝对值之和却高达57.9992,而且残差分布根本不服从正态分布——1959年到1961年那段特殊时期的数据把曲线带偏了。我一般会把数据分段尝试,找出随机误差服从正态分布的那段区间,拟合结果才可信。

2.2 三组数据拟合的MATLAB实现

用nlinfit做非线性最小二乘拟合,关键是给好初始参数。原项目用solve解方程粗估了x_m和r的初值,这一步很实用,能避免nlinfit陷入局部最优。

% 令1980年为初始年份,t=0对应1980年 t = 0:25; % 1980年到2005年全国总人口数据,单位:千万 x = [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]; % 用前两个点粗估初值:c是容纳量x_m, d是增长率r [c, d] = solve('c/(1+(c/98.705-1)*exp(-5*d))=105.851', ... 'c/(1+(c/98.705-1)*exp(-15*d))=117.171', 'c', 'd'); % 初值带入nlinfit b0 = [241.9598, 0.02985]; fun = inline('b(1)./(1+(b(1)/98.705-1).*exp(-b(2).*t))', 'b', 't'); [b1, r1, j1] = nlinfit(t, x, fun, b0); % 用拟合参数写预测方程 y = b1(1) ./ (1 + (b1(1)/98.705 - 1) .* exp(-b1(2) .* t)); % 可决系数 R^2 R2 = 1 - sum(r1.^2) / sum((x - mean(x)).^2); fprintf('可决系数 R^2 = %.4f\n', R2); fprintf('残差绝对值之和 = %.4f\n', sum(abs(r1)));

这段代码的要点有两处。一是初值b0的获取方式,先用solve代入两个年份的人口数解出近似参数,这是原项目里很聪明的做法,直接拿全量数据跑nlinfit容易被初始值带偏。二是可决系数R²的计算公式,用残差平方和除以总平方和,数值越接近1说明拟合越好。用1980年到2005年数据拟合,R²达到0.9987,残差绝对值之和只有10.1699,明显优于前两组。

2.3 用拟合曲线做外推预测

拟合完成之后,预测未来某一年的人口就是纯数学代入了。需要先把年份转换成相对t值,再代入拟合好的方程。

% 预测2010年、2020年、2033年人口,1980年为t=0 t_predict = [30, 40, 53]; % 对应2010、2020、2033 x_predict = b1(1) ./ (1 + (b1(1)/98.705 - 1) .* exp(-b1(2) .* t_predict)); disp('预测结果(单位:千万):'); disp(x_predict);

算出来2010年13.55357亿、2020年14.18440亿、2033年14.70172亿,这和附件1里专家预测的13.6亿、14.5亿、峰值15亿左右非常接近。这套结果直接拿去和官方数据做对比表,就能在报告里形成论据闭环。

2.4 三组拟合的残差特征对比

三组数据拟合后的表现差异很大。1954年起步的全量拟合,残差绝对值之和57.9992,图形上残差不在零轴两侧对称分布,那段历史波动直接破坏了模型假设。1963年起步的拟合,残差绝对值之和27.8046,分布接近对称,但1970年代的人口政策干预还是留下了一些痕迹。1980年起步的拟合最干净,残差绝对值之和10.1699,图形基本关于坐标轴对称,说明这段时间的随机误差确实服从正态分布。

所以说,Logistic拟合不是数据越多越好。我一般会观察残差的分布形态,如果残差绝对值之和特别大,而且序列有明显系统偏差,就该换时间段重跑。

3. Leslie矩阵的构建:按年龄分组的核心算法

3.1 为什么需要按年龄分组

Logistic模型的输出只有一个总数,看不出年龄结构。但人口问题的关键恰恰在结构:20岁女性的一胎概率和40岁女性完全不同,65岁以上老人的死亡率也远高于中年人。原题用2001年数据构造Leslie矩阵,把人口按1岁间隔分成年龄组,把时间也按同样单位离散化,这样就能递归预测未来任何一年的分年龄人口分布。

核心递推公式是:

x(k+1) = L * x(k)

其中x(k)是年龄分布向量,L是Leslie矩阵。L的第一行是各年龄组的生育率(生女孩率),次对角线是存活率,其余位置是0。

3.2 生育率计算与修正过程

这是整个模型里最容易踩坑的环节。附件2给出的原始育龄妇女生育率算出来的总和生育率只有1.42,和专家给出的更替水平1.8差了很远,直接导致人口峰值预测年份提前了10年。原项目做了一个关键修正:先按附件2算出各个年龄段的生育率结构,再用专家给出的1.8作为总和生育率目标值,把整体生育率放大修正。

修正的逻辑是这样的。先算城市、镇、乡分年龄段的生育率,结合男女出生性别比把总生育数折算成女婴数,得到每个女性平均生育女儿数。然后算总和生育率,发现偏低,就把每个年龄段的生育率按比例调整,让总和生育率逼近1.8。这个修正思路在真实项目中非常常用——抽样数据往往有偏差,需要用权威目标值校准。

3.3 Leslie矩阵构造的MATLAB实现

% 构造Leslie矩阵 % 以2001年为初始年份,一岁一组,0到90岁共91组 n = 91; L = zeros(n, n); % 第一行填入各年龄段的生育率 b(i),已折算为女婴出生率 % b数组为修正后的生育率,15-49岁有值,其他为0 L(1, :) = b; % 次对角线填入存活率 s(i) = 1 - d(i),d(i)为死亡率 for i = 1:n-1 L(i+1, i) = s(i); end % 初始年龄分布向量,2001年各年龄女性人口数 x0 = w; % w为91维列向量,单位:人 % 递归预测2002年到2050年 years = 2002:2050; N = length(years); X = zeros(n, N); X(:, 1) = L * x0; for k = 2:N X(:, k) = L * X(:, k-1); end % 总人口 = 女性各年龄组加总 / 女性占比 total_population = sum(X) ./ female_ratio;

这套代码的核心价值在于,X矩阵每一列就是某一年完整的91维年龄分布,可以随时取任意年龄段做汇总——比如15到64岁是劳动年龄人口,65岁以上是老年人口。做人口抚养比、老龄化率等衍生指标,都从这个矩阵出发计算,不需要重新跑模型。

3.4 矩阵可逆性与长期预测

Leslie矩阵的特征值决定了长期预测的收敛形态。主特征值大于1,人口持续增长;等于1,人口保持稳定;小于1,人口走向衰减。在k=1.8修正后的矩阵里,主特征值略小于1,所以2023年达到峰值后总人口缓慢下降,这个趋势和官方预测的高峰期基本吻合。

但长期预测有个问题:生育率和死亡率被假设为不随时间变化,这在20年以上的时间跨度里不太现实。原项目的灵敏度分析用k=1.6、1.8、2.0、2.2四组不同生育率分别跑预测,就是为了观察参数波动对结果的影响。我一般会把这种批量扫描做成循环脚本,一次性输出多组预测曲线。

4. 从人口矩阵到决策指标:老龄化、抚养比和育龄妇女预测

4.1 劳动年龄人口与总人口的双线走势

用Leslie模型预测的分年龄数据,可以直接聚合出劳动年龄人口。按15到64岁定义劳动年龄人口,模型显示2010年达到10.4421亿,2013年达到高峰10.4852亿,之后转入下降通道。这个结论的言外之意是:短期内劳动力数量不缺,缺的是结构性调整——比如高龄劳动力占比上升,新增劳动力供给下降的趋势已经在路上。

4.2 老龄化和抚养比的计算口径

老龄化指标有两种统计口径,60岁以上和65岁以上,判断标准不同,原始资料里两种都做了。2001年60岁以上老年人口1.5538亿,占总人口11.5693%;2020年预计达到2.907亿,比重19.443%;本世纪40年代中后期形成高峰平台,60岁以上达4.45亿人、比重33.277%,65岁以上达3.51亿人、比重25.53%。

人口抚养比的计算公式是:

抚养比 = (0到14岁人口 + 65岁及以上人口) / 15到64岁人口

用MATLAB对每年的年龄分布向量分段求和,就能得到一条随时间变化的抚养比曲线。结果显示抚养比呈持续上升趋势,主要驱动力是老龄人口占比扩大,儿童抚养比相对平稳。

4.3 预测合成的对比表

指标2010年2020年峰值年份峰值数值
总人口(亿)14.260914.9513202314.985
劳动年龄人口(亿)10.4421持续下降201310.4852
60+老年人口(亿)约2.02.9072040s4.45
总抚养比约0.38约0.45持续上升超过0.55

这张表可以直接放进论文的结果分析部分,把模型输出和官方报告预测放在一起做对比,能节省大量整理数据的时间。

5. 避坑指南:数据修正、参数初值与模型边界

5.1 总和生育率偏低导致峰值提前

现象:用附件2原始数据算出的总和生育率只有1.42,Leslie模型预测的人口峰值年份比官方报告提前了10年。

原因:抽样数据里城市、镇、乡的生育率加权后明显偏低,和专家评估的更替水平1.8不一致。

解决:用专家给定的总和生育率1.8做目标值,对分年龄生育率按比例修正,重新构造Leslie矩阵。峰值年份从提前10年修正到基本与官方预测吻合。

5.2 初值估算不到位导致拟合结果飘

现象:nlinfit直接跑全量数据经常收敛到奇怪的参数,可决系数甚至出现负值。

原因:非线性最小二乘对初值敏感,全局最优解可能被局部最优掩盖。

解决:先用solve代入两个已知年份的数据解出x_m和r的近似值,把解出来的参数作为nlinfit的初值。我一般会先画散点图观察数据形态,再决定初值范围。

5.3 时间跨度过长导致预测失真

现象:1954年到2005年的全量拟合残差绝对值之和57.9992,图形上残差明显不对称。

原因:包含了特殊历史时期的大幅波动,线性假设和正态分布假设被破坏。

解决:分段时间窗口做拟合,选择1980到2005年这种政策稳定、随机误差服从正态分布的区间。

5.4 死亡率恒定的假设不适用于超长期

现象:预测到2050年以后,老年人数和总人口比出现明显偏差。

原因:模型假设各年龄组死亡率不随时间变化,实际医疗水平提高会降低死亡率。

解决:把模型定位为中短期预测工具,或者引入时变死亡率参数做扩展,参考女性占比的变化动态修正Leslie矩阵中的存活率。

5.5 数据口径不一致导致计算混乱

现象:城市、镇、乡的抽样总人口比例不同,各年龄段女性占比直接相加会重复计算。

原因:没有先按抽样比例换算成实际总人口,就直接混合使用了不同口径的比率数据。

解决:先用抽样数据算出市、镇、乡人口占全国总人口的比率,再分别乘以2001年全国总人口数得到各区域实际人口,最后加权计算年龄分布。

6. 参数扫描技巧:用生育率k值标定模型边界

模型做完之后,不能只给一组预测结果就收工。原项目的灵敏度分析用k=1.6、1.8、2.0、2.2四组总和生育率分别扫描总人口和老龄化趋势,这个方法值得完全照搬。

具体做法是写一个外层循环,每次用不同的k值替换Leslie矩阵第一行的生育率向量,其余参数保持不变,重新跑完整的2001到2050年预测,最后把所有k值对应的总人口曲线和老年占比曲线画在同一张图上。从图11可以看出,k=1.6时人口达到峰值后快速负增长,k=2.2时人口持续膨胀且下降缓慢,k=1.8时增长最稳定。从图12可以看到,k越小老龄化速度越快,k越大年龄结构越稳定。

这个扫描的意义在于标定模型边界——政策制定者能直观看到生育率每变化0.2,总人口和老龄化会发生多大变化。把这段扫描代码附在论文附录里,能显著提升模型的可信度和分析深度。

另外我给一个建议:每次跑完一组k值预测,把年龄分布矩阵X保存下来,后续算抚养比、育龄妇女人数这些衍生指标时不需要重跑模型,直接对X做聚合就行。我就是因为刚开始每次都从头跑整套流程,改了参数就要重新整理数据,浪费了大量时间。从那以后我每次建人口预测模型都会把年龄分布矩阵缓存下来,方便随时取数。希望这些经验能帮你把这个模型跑通,少走弯路。

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

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进