ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

Logistic与Leslie双模型人口预测MATLAB实现与避坑

Logistic与Leslie双模型人口预测MATLAB实现与避坑

简介:围绕中国人口增长预测的课程设计与建模文档,面向数学建模学习者、统计与人口研究方向的学生及教师,系统演示如何用 Logistic 阻滞增长模型与 Leslie 年龄结构模型完成中短期及长期人口趋势分析。压缩包仅含 1 个 doc 文件,大小约 988KB,正文按问题重述、问题分析、合理假设、符号说明、模型建立与求解、残差检验、优缺点评价与推广等章节组织,便于按建模流程查阅。现有 5156 人学习。内容给出 1954、1963、1980—2005 年三组数据的拟合对比,1980—2005 年模型可决系数达 0.9987,并预测 2010、2020、2033 年总人口;Leslie 部分构造矩阵预测 2002—2050 年总人口、劳动年龄人口与老年人口,讨论老龄化、抚养比、育龄妇女及人口控制,附 MATLAB 实现思路,可用于复现建模过程、撰写论文与准备竞赛。

1. 从一个绕不开的追问说起

做人口增长预测,很多人上来就推一条 Logistic 人口模型曲线,拟合出可决系数 0.99 以上,觉得活儿干完了。等到答辩或评审现场,被问一句「那老龄化什么时候到顶、抚养比哪一年转折、育龄妇女人数什么时候见峰」,一条只描述总量的 S 曲线就答不上来了——它压根没有年龄结构这个维度。所以这套方案从一开始就定了双模型路线:Logistic 人口模型负责给出总量趋势和峰值量级,Leslie 人口模型按年龄分组把结构拆开,再由此派生出老龄化、抚养比、劳动年龄人口、育龄妇女人数这些指标。整套计算全部落在 MATLAB 里完成,从参数拟合到矩阵递推都能复现。这篇东西适合正在做数学建模毕设、课程设计,或者要给出一份完整人口预测方案的人,照着改数据、改参数就能跑。

2. 数据口径与建模假设:先把手里的原料盘清楚

建模翻车,八成不是翻在公式上,是翻在数据口径上。同一个「总人口」,年鉴口径、抽样推算口径、公安户籍口径能差出几千万,起点年份差一年,峰值年份就能差出好几年。所以动手写第一行代码之前,必须先把三件事钉死:用哪段数据、立什么假设、拿哪些指标去交差。

2.1 三段起点的选择:为什么是 1954、1963、1980

原料是一张按年份排列的总人口序列表,1954 年到 2005 年,单位统一取「千万人」,1954 年 60.2、1990 年 114.333、2005 年 130.756。序列本身完整,但不能一口气全丢进去拟合,因为这条曲线的斜率在几十年里换过好几次性格。

1954—1962 这一段波动剧烈,先是一波出生高峰,随后又出现明显的增长异常年份,随机误差根本不服从正态分布。最小二乘的前提被破坏,拟合出来的曲线只是「平均意义上穿过去」,残差绝对值之和高达 57.9992,这种曲线拿去外推,误差会被指数放大。

1963—1979 这一段相对「自然」,增长基本按自身规律走,外界的大干扰因素少,可以认为随机误差近似正态。从 1963 年起拟合,残差绝对值之和降到 27.8046,图形已经大致关于横轴对称。

1980—2005 这一段,增长方式又换了一次档,出现了持续、稳定的外部干预,斜率被系统性压低。但恰恰因为这种干预是稳定的、没有二次突变,这一段的误差分布反而最规整。从 1980 年起拟合,可决系数 0.9987,残差绝对值之和 10.1699,是三段里最好的。

所以正确的做法不是「选最好的那段、扔掉另外两段」,而是三段都拟、三段都预测、再横向比。三条曲线在 2048 年的预测值分别落在 166.7683、148.5580、150.2775(千万),第一条明显高估、第二条明显低估、第三条与附件 1 研究报告给出的区间最贴近。这个「三选一」的过程本身就是方案的一部分,写进报告里是加分项,跳过它直接给一条曲线才是扣分项。

提示:起点年份的选择不是拍脑袋,判断依据是「该年份之后增长机制是否发生了不可逆的变化」。机制变了就切段,机制没变就别切,切太碎样本量不够,参数估不稳。

2.2 四条假设与关键符号:把边界写死

假设不是走过场,每一条都对应后面某段代码能不能省。这套方案里立了四条:

社会稳定,不发生重大自然灾害和战争,且这种稳定不随时间改变。这条支撑了「生育率、死亡率不随 t 变化」的简化,也是 Leslie 矩阵能写成常系数矩阵的前提。

超过 90 岁的妇女统一按 90 岁计算。这条解决的是开口组问题——年龄分组必须有限,最后一组得人为封口,否则矩阵维数不定。

较短时间跨度内平均年龄结构变化小,可视为不变。这条限定了外推的合理年限,也解释了为什么长期预测(2050 年以后)只做趋势参考。

不考虑迁移对总人口的影响。这条把人口变动简化为「出生 − 死亡」两个通道,Leslie 递推式才成立。

符号体系要一次定清楚,后面所有公式和代码都靠它对齐:

符号含义来源
x(t)第 t 年总人口附件 2 序列表
r内禀增长率Logistic 拟合输出
xm资源与环境可容纳的最大人口Logistic 拟合输出
n_i(t)t 时刻第 i 年龄组女性人数Leslie 递推
b_i第 i 年龄组单个女性平均生育女儿数生育率 × 女婴比例
s_i第 i 年龄组女性存活率1 − 该组死亡率
LLeslie 矩阵由 b_i、s_i 装配
TFR总和生育率Σb_i
R²可决系数拟合优度口径
W残差绝对值之和拟合优度口径

2.3 交差用的指标体系:老龄化、抚养比、育龄妇女

只报一个总人口数,撑不起一份完整方案。真正让评审信服的是「一组互相关联的指标」,因为它们能互相印证。这套方案里固定输出四类:

人口老龄化。判定线用两条:65 岁及以上占比超过 7%,或 60 岁及以上占比超过 10%,达到任一条即进入老年型。方案里的预测结果是,60 岁以上口径在 21 世纪 40 年代中后期形成高峰平台,规模达 4.45 亿、占比 33.277%;65 岁以上口径达 3.51 亿、占比 25.53%。

人口抚养比。定义为非劳动年龄人口与劳动年龄人口之比,通常按 0—14 岁为少儿、15—64 岁为劳动年龄、65 岁及以上为老年三段计算。要说明的是,劳动年龄取 15—59 还是 15—64,会算出两套不同的抚养比,报告里必须写明用的是哪一套,否则数字对不上。

总和生育率与更替水平。总和生育率是各年龄组生育率之和,含义是「按当前分年龄生育率过完育龄期,平均生育几个子女」。更替水平是指生育的女儿数恰好替代母亲本身,方案里取 1.8。这两个数是 Leslie 矩阵里最敏感的输入。

育龄妇女与生育旺盛期育龄妇女。前者取 15—49 岁,后者取 20—29 岁。这两个量的峰谷位置,直接决定出生人口什么时候出现小高峰,是解释「为什么 2037 年还会有一次回升」的关键。

3. Logistic 阻滞增长模型:把 S 曲线跑出可信度

总量模型的价值不在公式本身——Logistic 方程的解析解是教科书内容——而在于参数怎么估、初值怎么给、结果怎么验。这三步任何一步敷衍,曲线照样画得出来,但外推出去就是错的。

3.1 阻滞项从哪来:把「增长率随人口下降」写成一行

指数增长模型假设增长率恒定,于是人口无限膨胀,这显然不成立。阻滞增长模型的改动只有一处:让增长率变成人口的减函数。

设人口为 x(t),增长率为 r(x)。r(x) 随 x 增大而下降,取最简单的线性形式:

r(x) = r · (1 − x/xm)

其中 xm 是资源与环境能容纳的最大人口,当 x = xm 时增长率为 0,人口停止增长。代入 dx/dt = r(x)·x,得到微分方程:

dx/dt = r · x · (1 − x/xm)

分离变量求解,得到解析解:

x(t) = xm / (1 + (xm/x0 − 1) · e^(−r·t))

其中 x0 是初始年份的人口。这个式子里只有三个待估参数:x0(由数据给定)、xm、r。拟合的本质就是找一对 (xm, r),让曲线穿过历史数据时残差平方和最小。

需要强调的是,xm 不是「真实上限」,而是一个拟合参数。它没有直接的物理含义,只是让曲线形状对上历史段。所以不同数据段拟出来的 xm 差异很大——第一段 180.9871、第二段 151.4513——这不是矛盾,是正常的,因为每段数据描述的「增长机制」本来就不同。

3.2 用 nlinfit 做非线性最小二乘:初值给不好就发散

MATLAB 的nlinfit是高斯-牛顿类算法,对初值极其敏感。xm 和 r 这两个参数高度相关,初值随手给 [200, 0.02],轻则迭代几百次不收敛,重则直接报「矩阵接近奇异」。稳妥的办法是先用两端点解一个二元方程组,把初值锁在合理邻域内。

% 模型Ⅰ:以 1980 年为初始年的 Logistic 拟合 % t 为自 1980 年起的年数,x 为对应年份总人口(单位:千万) t = 0:25; x = [98.705 100.100 101.654 103.008 104.357 105.851 107.500 109.300 ... 111.026 112.704 114.333 115.823 117.171 118.517 119.850 121.121 ... 122.389 123.626 124.761 125.786 126.743 127.627 128.453 129.227 ... 129.988 130.756]; % 第一步:用 t=5 和 t=20 两个点解方程组,给出 (xm, r) 的初值 % 目的是把初值限制在收敛域内,避免直接猜初值导致 nlinfit 发散 syms c d eq1 = c/(1 + (c/98.705 - 1)*exp(-5*d)) == 104.357; eq2 = c/(1 + (c/98.705 - 1)*exp(-20*d)) == 117.171; [c0, d0] = solve(eq1, eq2, c, d); b0 = [double(c0), double(d0)]; % 初值向量,b0(1)=xm, b0(2)=r % 第二步:定义目标函数并做非线性最小二乘 % 注意 x0 固定为 98.705,只估 xm 和 r 两个参数 fun = @(b,tt) b(1) ./ (1 + (b(1)/98.705 - 1) .* exp(-b(2).*tt)); [b1, r1] = nlinfit(t, x, fun, b0); % b1 为估计参数,r1 为残差向量 % 第三步:用两个口径评估拟合优度 R2 = 1 - sum(r1.^2) / sum((x - mean(x)).^2); % 可决系数 W = sum(abs(r1)); % 残差绝对值之和 fprintf('xm = %.4f, r = %.6f, R2 = %.4f, W = %.4f\n', b1(1), b1(2), R2, W); % 第四步:外推关键年份 t_pred = [30 40 53]; % 对应 2010、2020、2033 年 y_pred = fun(b1, t_pred); disp(y_pred);

这段代码有三个地方值得说明。syms那两行用两个已知数据点解出 (xm, r) 的粗估,本质是把「两点确定一条曲线」的思路当预处理,solve在符号工具箱里能直接给解析解;如果手头没有符号工具箱,退化成网格搜索也行——把 xm 从 100 到 200 以 1 为步长、r 从 0.01 到 0.08 以 0.001 为步长扫一遍,取残差平方和最小的一组,效果一样。

第二步里x0被硬编码成 98.705,这是因为 nlinfit 只估 b(1) 和 b(2) 两个参数,x0 如果也放进参数向量,会造成三个参数共线、矩阵奇异。

第三步同时算 R² 和 W 两个口径,是有意为之。R² 对大数据量样本天然友好,样本越长越容易接近 1,容易给人虚假的安全感;残差绝对值之和 W 是绝对量,不带样本量修正,对「曲线在哪一段偏得厉害」更敏感。两个一起看,才不会被单一指标骗过去。

参数 b1(1)、b1(2) 拿回来后,代回解析解就是预测方程。以 1980 年起拟合的曲线外推,得到 2010 年 135.5357、2020 年 141.8440、2033 年 147.0172(千万),与附件 1 研究报告给出的区间基本吻合。

3.3 三段拟合横向对比:可决系数高不等于预测准

把三段分别跑一遍,结果摆在一起看:

拟合段样本区间xmrR²W
1954 起1954—2005180.98710.0336—57.9992
1963 起1963—2005151.45130.0484—27.8046
1980 起1980—2005程序输出程序输出0.998710.1699

前两段的 R² 没有单独列出,因为这两段的残差明显不满足正态性假设,R² 这个数在此时已经失去解释力,真正能说明问题的是 W 和残差散点图的形状。

看 W 的走势:57.9992 → 27.8046 → 10.1699,逐段下降一个量级。再看残差图,第一段的残差在横轴上下大幅摆动且不对称,第二段已经大致对称,第三段基本贴着横轴、正负分布均衡。残差图比 R² 更能说明「模型是否用对了」,这一点在答辩时最好主动讲。

再看外推结果。三条曲线对 2048 年的预测分别是 166.7683、148.5580、150.2775(千万)。第一条明显偏高,因为它把 1954—1962 那段高增长也当成模型的一部分学了进去,等于假设「高增长机制会一直延续」;第二条偏低,因为 1963—1979 的自然增长阶段增长率偏高、基数偏小;第三条最贴近研究报告的区间,因为它学的是最近二十多年真实起作用的增长机制。

这里有个容易踩的坑:拿第三段的 R² = 0.9987 去和第一段的 R² 比,然后宣布「第三段更好」,这个论证是不成立的。第一段的 R² 之所以低,不是因为模型不好,而是因为那段数据本身就混着异常年份,跟任何光滑曲线都贴不上。正确的表述是:「第三段数据的生成机制更接近当前及未来的机制,且误差结构更规整,因此用第三段建模外推的可信度最高。」这是逻辑上的推理,不是数值上的比拼。

4. Leslie 矩阵:把年龄结构装进矩阵里

Logistic 只回答「多少人」,Leslie 要回答「哪些人」。这一步的核心是把人口按年龄切成若干组,用一个矩阵把「今年的分年龄女性人数」映射成「明年的分年龄女性人数」。矩阵一装配好,剩下全是矩阵乘法,快得离谱,但装配过程极其琐碎,数据清洗占八成工作量。

4.1 初始向量怎么造:城乡拆分再按年龄汇总

方案里的初始年份取 2001 年,总人口 127.627(千万)。手里有的是分城乡的抽样数据,不是全量数据,所以要先把抽样比换算成总量比。

抽样数据里,城市男 147907、城市女 147465、镇男 80279、镇女 77976、乡男 394690、乡女 372242。城市合计 295372,镇合计 158255,乡合计 766932,总计 1220559。于是三级人口占比分别是:

  • 城市 295372 / 1220559 ≈ 0.24200
  • 镇 158255 / 1220559 ≈ 0.12966
  • 乡 766932 / 1220559 ≈ 0.62834

三者相加恰好为 1,说明抽样结构自洽。用总人口 127.627 分别乘这三个比例,得到 2001 年城市约 30.886(千万)、镇约 16.548(千万)、乡约 80.195(千万),合计 127.629,与总量吻合,误差来自四舍五入。

接着按年龄组把三级女性人数汇总成初始向量。设female(i,j)表示第 j 类(市/镇/乡)第 i 年龄组的女性人数占该类总人口的比例,则第 i 年龄组的女性总人数为:

n_i(0) = Σ_j P_j · female(i,j)

这一步的关键在于三级的年龄结构差异很大,城市的老龄化程度高、乡的少儿比例高,如果图省事直接拿全国平均年龄结构乘总人口,后面算出来的老龄化和抚养比会系统性偏低。城乡分开算,再按人口加权合成,这一步不能省。

4.2 生育率修正:把 TFR 拉回更替水平

按抽样数据直接算出来的分年龄生育率,加总得到的 TFR 明显低于 1.8,跟参考资料给出的更替水平差得远。原因通常是抽样样本对育龄妇女的覆盖不足,或者生育率统计口径只覆盖了部分孩次。不管哪种,直接拿去递推,人口会以肉眼可见的速度塌下去。

处理办法是按比例缩放,把 TFR 强行拉到 1.8:

b_i' = b_i × (1.8 / TFR)

这个修正的合理性在于:它假设「各年龄组生育率的相对形状是对的,只是整体水平被低估了」。这是个可辩护的假设,比逐组硬调要干净得多。同时它留了一个天然的灵敏度分析接口——把 1.8 换成 1.6、2.0、2.2,就能看不同生育水平下人口总量的分化。

还有一步不能少:生育率数据通常含男女,而 Leslie 矩阵只递推女性,所以要乘上女婴比例。若出生性别比以「女 = 100」计,则女婴比例为 1/(1 + 性别比/100)。这一步漏掉,等于凭空多算了近一倍的新生女婴。

4.3 装配与递推:从 2001 推到 2050

把生育项和存活项拼成矩阵,形式是:第一行放各年龄组的 b_i,下方次对角线放各组的 s_i,其余位置全 0。

% Leslie 模型主流程:从 2001 年递推到 2050 年 nAge = 91; % 0-90 岁,90 岁及以上并入最后一组(开口组) % ---- 步骤 1:由抽样比推算 2001 年市、镇、乡三级人口(单位:千万)---- samp = [147907+147465, 80279+77976, 394690+372242]; share = samp / sum(samp); % 三级人口占比 P2001 = 127.627; % 2001 年区域总人口 P3 = P2001 * share; % 市、镇、乡总人口 % ---- 步骤 2:合成初始女性分布向量 n0(nAge×1)---- % female(i,j) 为第 j 类第 i 年龄组女性占该类总人口的比例 n0 = zeros(nAge, 1); for j = 1:3 n0 = n0 + P3(j) * female(:, j); end % ---- 步骤 3:合成生育率并做 TFR 修正 ---- raw = zeros(nAge, 1); for j = 1:3 raw = raw + P3(j) * fert(:, j) / sum(P3); % 按人口加权合成生育率(含男女) end girl = 1 ./ (1 + sexratio / 100); % 出生女婴比例 b = raw .* girl; % 每个女性平均生育女儿数 tfr = sum(b); b = b * (1.8 / tfr); % 按比例缩放到更替水平 1.8 % ---- 步骤 4:合成存活率 ---- d = zeros(nAge, 1); for j = 1:3 d = d + P3(j) * death(:, j) / sum(P3); end s = 1 - d; s(end) = 0; % 开口组不再向下转移,避免人口凭空累积 % ---- 步骤 5:装配 Leslie 矩阵并逐年递推 ---- L = diag(s(1:nAge-1), -1); % 次对角线放存活率 L(1, :) = b'; % 第一行放生育率 N = zeros(nAge, 51); % 2001-2051 共 51 个时点 N(:, 1) = n0; for k = 1:50 N(:, k+1) = L * N(:, k); end % ---- 步骤 6:按分年龄结果反推总量、劳动年龄人口、老年人口 ---- total = sum(N, 1) / female_share; % 除以女性占比折算总人口 labor = sum(N(16:65, :), 1) / female_share; elder60 = sum(N(61:end, :), 1) / female_share; elder65 = sum(N(66:end, :), 1) / female_share;

代码里有几个参数需要单独交代。nAge = 91对应 0—90 岁共 91 个年龄组,第九十组是开口组,超过 90 岁的全部并进去,所以s(end)必须置 0,否则每一轮都会有一批「90 岁以上的人」被再次转移出去,人口总量会缓慢虚增——这个 bug 极其隐蔽,跑出来的曲线只会偏高一点点,肉眼很难发现。

female_share是女性占总人口的比例,因为 Leslie 矩阵只递推女性,要还原总人口必须除以这个比例。如果这个比例本身也随时间变化,严格做法是每一轮都重新计算,简化做法是取一个固定值,报告里要注明做了这个简化。

L(1,:) = b'必须转置,因为b是列向量而矩阵行要横着放,这个转置漏掉,MATLAB 会直接报维度不匹配,算是友好的错误;真正的坑是某些写法下维度恰好对得上但数据错位,跑出来的曲线形状奇怪但不报错——这种就是典型的黑匣子式翻车。

递推跑完,把结果落到报告里,得到这组数:总人口在 2010 年达 142.609(千万,即 14.2609 亿),2020 年达 149.513(千万),2023 年前后达到峰值 149.85(千万),2033 年回落到 147.455(千万)。劳动年龄人口 2010 年 104.421(千万),2013 年前后见峰 104.852(千万),之后缓慢下行。

对照一下两个模型:Logistic 给 2010 年 135.5357、2020 年 141.8440,Leslie 给 2010 年 142.609、2020 年 149.513,前者系统性偏低约 5%—7%。这个差异不是谁算错了,而是口径不同——Logistic 学的是历史总量的轨迹,Leslie 学的是分年龄结构的惯性。评审问起差异原因,能把这层讲清楚,比强行让两个模型对上更有说服力。

老龄化这条线上,60 岁以上人口在 40 年代中后期形成 4.45 亿的高峰平台,占比 33.277%;65 岁以上达 3.51 亿,占比 25.53%。抚养比全程单调上升,主要推力是老年人口规模的绝对增长,其次是少儿人口在部分年份的回升。育龄妇女人数在 2010 年前后见峰后转降,而生育旺盛期育龄妇女(20—29 岁)在 2012 年见峰、2025 年前后进入低谷、2037 年前后再出现一个小高峰——这个小高峰来自 2012 年出生高峰队列进入生育旺盛期,是队列惯性,不是生育水平回升。

5. 避坑清单:五个最容易翻车的地方

这一节是血泪经验合集。下面五条都是这套方案里真实存在、且极易被忽略的问题,每一条都按「现象 → 原因 → 解决」拆开写。

5.1 拟合区间一刀切,峰值年份对不上

现象:用全部年份一起拟合,画出来的曲线在历史段看着还行,一外推就说「2048 年总人口还有 166.7683(千万)」,跟研究报告的区间差了一大截,被追问「为什么你的模型预测人口一直涨」。

原因:把 1954—1962 那段高增长当成模型的一部分学了进去。最小二乘在拟合时对每个样本一视同仁,早期的大斜率会把 xm 抬高、把 r 拉低,最终曲线的形状偏向「高上限、慢收敛」。这不是拟合算法的问题,是数据生成机制变了而模型不知道。

解决:按机制变化切段,三段都拟、三段都外推、三段横向比。判断切段的标准是「该年份之后增长机制是否发生不可逆的变化」,写进报告时要把这个判断依据讲出来。切完之后不要用 R² 排序选优,要用残差图形态 + 外推结果与权威区间的贴合度双重判断。

5.2 生育率没修正,峰值提前十年

现象:Leslie 跑出来的峰值年份比研究报告早了约十年,总量峰值也偏低,老龄化和抚养比曲线全部左移。

原因:按抽样数据直接算出的 TFR 明显低于更替水平,甚至低到 1.42 这个量级。参考资料给出的更替水平是 1.8,两者相差近 0.4。生育率每低一点,二十年后就少一整批育龄妇女,人口峰值自然提前。根源在于抽样数据对育龄妇女的覆盖有偏,或者生育率统计口径不完整。

解决:按比例把 b_i 缩放到 TFR = 1.8,即 b_i' = b_i × (1.8 / TFR)。这个修正假设「各年龄组生育率的相对形状可信、整体水平偏低」,是可辩护的。同时把 1.8 作为基准做灵敏度分析,取 1.6、2.0、2.2 各跑一遍:k 很小时人口达峰后快速负增长,k 很大时人口持续膨胀、老龄化被稀释,只有 k 适中时总量与结构才都稳定。这组对比图放进报告,等于主动回答了「你的结论对参数有多敏感」这个必问题。

5.3 开口组没封口,人口悄悄虚增

现象:递推跑完,总人口比预期高出一两个百分点,逐年看差异还不大,五十年累积下来就很明显,但代码不报任何错。

原因:Leslie 矩阵的次对角线放的是存活率,如果最后一组的存活率没有置 0,每一轮都会有一批「90 岁以上的人」被转移出去,而这些人本应留在开口组里。这是纯逻辑错误,不是数值错误,所以 MATLAB 一句警告都不会给。

解决:装配矩阵后立刻把s(end) = 0,并且在报告里写明「90 岁及以上并入最后一组,不再向下转移」。同时在代码里加一行断言做自检——如果开口组存活率不为 0 就直接报错停下。这类问题靠肉眼看曲线根本发现不了,只能靠断言守住。

5.4 把可决系数当免检章,残差图一张没画

现象:报告里写了一行「可决系数 0.9987,拟合效果很好」,评审随口问「残差分布什么样」,答不上来。

原因:R² 这个数对样本量天然友好,样本越长越容易接近 1,而且它只反映「解释了多大比例的方差」,不反映「误差是否独立同分布」。用最小二乘估参数的前提是误差服从正态、均值零、方差齐,这些条件 R² 一个都测不出来。

解决:拟合完必须画残差散点图,横轴年份、纵轴残差,看三件事——是否大致对称分布在零线两侧、有没有明显的趋势或周期、有没有几个孤立的大残差点。这套方案里三段的残差绝对值之和分别是 57.9992、27.8046、10.1699,配合三张残差图一起放,说服力比单独一个 R² 强得多。R² 和 W 两个口径并列写,是因为一个做相对比较、一个做绝对量级判断,互相补位。

5.5 单位口径混乱,千万和亿混着写

现象:报告里一会儿写「总人口 130.756」,一会儿写「总人口 13.5 亿」,读者完全不知道这两个数是不是一回事,评审也没法快速核对。

原因:原始数据的单位是千万人(130.756 千万 = 13.0756 亿),但人习惯用「亿」来表述。两种写法混在一份文档里,稍不留神就会把 135.5357 千万写成 135.5357 亿,差了一个数量级。

解决:全流程固定一个计算单位(这套方案统一用千万),只在最终呈现给读者的表格里换算成亿,并显式标注「单位:亿人」。代码里所有变量的单位在注释第一行写清楚,输出时用fprintf带上单位标签,避免人工誊抄时出错。看起来是小事,但这种错误一旦被评审抓到,会直接动摇对整份报告数据可信度的判断。

6. 验收与答辩:三张表把结论钉死

这类方案的验收,不能靠「我觉得跑通了」,要靠可复现的检查清单。我通常会准备三张表,答辩前逐项打勾。

第一张是参数与拟合优度表,把三段拟合的 xm、r、R²、W 全部列出来,同时附三张残差图。评委随手翻到哪一段都能对上号,不用现场解释「这个数是哪来的」。

第二张是双模型预测对照表,把 Logistic 和 Leslie 对同一批关键年份的预测值并排放:

关键年份Logistic 预测(千万)Leslie 预测(千万)差异率
2010135.5357142.609约 5.2%
2020141.8440149.513约 5.4%
2033147.0172147.455约 0.3%

差异率要算出来并写进表里,因为评委一定会问「两个模型为什么不一样」。答案已经备好:Logistic 学的是总量轨迹,Leslie 学的是分年龄结构惯性,前者在中短期偏低是因为它没有把「育龄妇女基数仍在高位」这个结构性因素考虑进去,而到 2033 年两者趋近,是因为总量增长趋缓、结构因素被总量约束吃掉。

第三张是灵敏度对照表,把 TFR 取 1.6、1.8、2.0、2.2 四种情形下的人口峰值年份、峰值规模、2050 年老龄化占比列成四行。这张表的杀伤力在于:它主动暴露了模型的敏感性,等于替评委把「你的结论稳不稳」这个问题回答了。凡是主动做灵敏度分析的方案,可信度天然高一档。

代码复现这块,我会额外做一件事:把主流程脚本改成参数化函数,主脚本只负责传参和画图。这样评委说「你把生育率改成 2.0 再跑一遍」,三十秒就能出图,不用现场改代码。现场改代码是答辩大忌,手一抖改错一个索引,前面攒的所有信任瞬间清零。

最后说一个教训。早年做这类建模,我总想着把公式推得漂亮、把图做得好看,参数估计随手一给,拟合不收敛就换个初值再试,试到能跑为止。有一次被问到「你这个初值是怎么定的」,我张口结舌——因为答案是「试出来的」。从那以后我每次做非线性拟合,都强制先用两个端点解一遍方程组把初值锁死,再进nlinfit,初值的来历必须能一句话说清楚。这个习惯后来救了我很多次,也让整个拟合过程从玄学变成了工程。希望帮到你。

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

RELATED READING

延伸阅读

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