現(xiàn):從年齡結(jié)構(gòu)到長期預(yù)測)
簡介這份資源圍繞中國人口增長預(yù)測展開面向數(shù)學(xué)建模學(xué)習(xí)者、參賽選手及人口研究入門者重點(diǎn)解決如何用Logistic阻滯增長模型與Leslie年齡結(jié)構(gòu)模型進(jìn)行中短期和長期人口趨勢預(yù)測的問題。壓縮包內(nèi)共1個(gè)doc文檔約988KB完整收錄了模型建立、參數(shù)估計(jì)、殘差分析與優(yōu)缺點(diǎn)評價(jià)等核心內(nèi)容并借助MATLAB完成數(shù)據(jù)處理與預(yù)測計(jì)算。文檔中詳細(xì)對比了1954年、1963年、1980年至2005年三組數(shù)據(jù)建模的效果指出以1980—2005年數(shù)據(jù)擬合的可決系數(shù)達(dá)0.9987并給出2010年、2020年、2033年總?cè)丝陬A(yù)測值Leslie模型部分則預(yù)測了2002—2050年總?cè)丝?、勞動年齡人口與老年人口分析了老齡化加速、人口撫養(yǎng)比上升及育齡婦女人數(shù)變化等指標(biāo)。目前已有5152人學(xué)習(xí)下載適合需要參考完整建模思路、指標(biāo)預(yù)測方法與MATLAB實(shí)現(xiàn)細(xì)節(jié)的讀者。1. Leslie人口增長模型從年齡結(jié)構(gòu)到長期預(yù)測的那條主線人口預(yù)測這件事很多人第一反應(yīng)是拿歷史總?cè)丝跀M合一條曲線外推。做過幾年數(shù)據(jù)的人都知道這種玩法在短期還行一旦拉到二三十年尺度就會翻車——因?yàn)樗讶丝谧詈诵牡臇|西丟掉了年齡結(jié)構(gòu)。同樣是一億人一半是兒童和一半是勞動年齡人口未來二十年的走向完全相反。Leslie人口增長模型解決的正是這個(gè)問題它把人口按年齡分組用生育率和存活率構(gòu)造一個(gè)矩陣逐年迭代就能推出年齡結(jié)構(gòu)和總量的演化。它屬于離散時(shí)間的矩陣人口學(xué)模型和Logistic那種只盯總量、靠環(huán)境容量約束的連續(xù)模型是兩條路子。這篇面向的是想用MATLAB把Leslie模型真正跑起來的人需要什么數(shù)據(jù)、矩陣怎么填、參數(shù)從哪來、結(jié)果怎么讀、哪里最容易出錯(cuò)。新手能照著復(fù)現(xiàn)熟手能對著參數(shù)和邊界挑刺。2. Leslie矩陣的構(gòu)造邏輯與數(shù)據(jù)準(zhǔn)備2.1 為什么是矩陣而不是一條擬合曲線Leslie模型的核心假設(shè)很樸素把人口按等長的年齡區(qū)間切成若干組比如每5歲一組0-4、5-9、……、直到最高年齡組。每個(gè)年齡組的女性人數(shù)構(gòu)成一個(gè)列向量記為 $n_t$。下一時(shí)刻的向量 $n_{t1}$ 由當(dāng)前向量左乘一個(gè)矩陣 $L$ 得到$$n_{t1} L \cdot n_t$$這個(gè) $L$ 就是Leslie矩陣它的結(jié)構(gòu)分兩部分。主對角線下方的那條次對角線放的是各年齡組的存活率 $s_i$含義是第 $i$ 組的女性活到第 $i1$ 組的比例第一行放的是各年齡組的生育率 $f_i$含義是第 $i$ 組女性在單位時(shí)間內(nèi)生育并存活到第0組的女兒數(shù)。矩陣長這樣以 $k$ 個(gè)年齡組為例L [ f_0 f_1 f_2 ... f_{k-1} ] [ s_0 0 0 ... 0 ] [ 0 s_1 0 ... 0 ] [ 0 0 s_2 ... 0 ] [ ... ... ... ... ... ] [ 0 0 0 ... 0 ]為什么用女性而不是總?cè)丝谝驗(yàn)樯袨橛捎g女性決定用女性單性別建模能把生育率定義得干凈避免兩性數(shù)據(jù)口徑打架。這是人口學(xué)里的通行做法不是偷懶。選它而不是Logistic的理由也很直接Logistic給不出年齡結(jié)構(gòu)做不了學(xué)齡人口、勞動力、老齡化的分年齡預(yù)測而這些恰恰是政策場景真正關(guān)心的。2.2 數(shù)據(jù)從哪來怎么對齊年齡組跑Leslie模型最少需要三類數(shù)據(jù)分年齡組的女性人口、分年齡組的女性存活率、分年齡組的女性生育率。常見來源是人口普查或統(tǒng)計(jì)年鑒的分年齡表通常按5歲分組。這里第一個(gè)坑就是年齡組的對齊——普查數(shù)據(jù)的分組邊界、你建模用的分組邊界、生育率數(shù)據(jù)的分組邊界三者必須完全一致否則矩陣填進(jìn)去就是錯(cuò)的。我一般會先把原始數(shù)據(jù)整理成三張表用MATLAB的table讀進(jìn)來再做一次顯式的對齊檢查。下面是一個(gè)最小可跑的數(shù)據(jù)準(zhǔn)備腳本假設(shè)你已經(jīng)有分年齡女性人口pop_f、存活率surv、生育率fert三個(gè)列向量長度都是k% 年齡組參數(shù)每5歲一組從0歲到100共21組 k 21; age_edges 0:5:105; % 分組邊界長度 k1 % 假設(shè)從外部讀入這里用占位數(shù)據(jù)演示結(jié)構(gòu) pop_f rand(k,1) * 1e5; % 各年齡組女性人口 surv 0.98 * ones(k,1); % 各年齡組存活率最后一組通常置0 fert zeros(k,1); % 各年齡組女性生育率 fert(4:8) [0.02 0.08 0.10 0.07 0.03]; % 15-19到35-39歲育齡段示例 % 對齊檢查三個(gè)向量長度必須一致 assert(numel(pop_f)k numel(surv)k numel(fert)k, ... 年齡組數(shù)不一致檢查分組邊界); % 存活率最后一組無法存活到下一組強(qiáng)制置0 surv(end) 0;這段代碼的關(guān)鍵不在計(jì)算而在那個(gè)assert。血淚經(jīng)驗(yàn)是數(shù)據(jù)來源一多長度對不上是最高頻的低級錯(cuò)誤早檢查早省事。age_edges的長度必須是k1因?yàn)樗沁吔绮皇墙M數(shù)很多人在這里差一位。生育率只填育齡段其余為0這是模型定義決定的不是可選項(xiàng)。2.3 生育率與存活率的換算口徑原始數(shù)據(jù)里的生育率往往是總和生育率或分年齡生育率單位是「每個(gè)女性一生生育的孩子數(shù)」或「千分比」而Leslie矩陣第一行要的是「每個(gè)女性單位時(shí)間生育的女兒數(shù)」。換算要過兩道一是除以2假設(shè)性別比接近1只取女兒二是按時(shí)間步長縮放。如果時(shí)間步是5年而生育率是年度的就要乘以5。存活率同理。普查給的通常是某年齡組的存活比例如果時(shí)間步是5年直接用即可如果時(shí)間步是1年就要把5年存活率開5次方近似成年存活率。這個(gè)換算不做迭代幾輪后總量會明顯偏離而且偏離方向還不直觀屬于典型的玄學(xué)偏差。提示性別比明顯偏離1的地區(qū)女兒比例不要簡單除以2用出生性別比單獨(dú)算否則長期預(yù)測會系統(tǒng)性偏高或偏低。3. 用MATLAB把Leslie模型跑起來3.1 構(gòu)造矩陣與逐年迭代的最小實(shí)現(xiàn)數(shù)據(jù)齊了構(gòu)造矩陣就是填兩個(gè)位置。下面這段是完整的迭代核心輸入是初始女性人口向量和三個(gè)參數(shù)向量輸出是每年每步的總?cè)丝诤湍挲g結(jié)構(gòu)function [N_total, N_hist] leslie_run(pop_f, surv, fert, steps) % pop_f : k×1 初始各年齡組女性人口 % surv : k×1 各年齡組存活率 % fert : k×1 各年齡組生育率 % steps : 迭代步數(shù) k numel(pop_f); L zeros(k, k); L(1, :) fert(:); % 第一行生育率 for i 1:k-1 L(i1, i) surv(i); % 次對角線存活率 end N_hist zeros(k, steps1); N_hist(:,1) pop_f(:); for t 1:steps N_hist(:, t1) L * N_hist(:, t); end N_total sum(N_hist, 1); % 每步女性總?cè)丝?end邏輯說明L(1,:)一次性把生育率鋪到第一行for循環(huán)把存活率放到次對角線這是Leslie矩陣的標(biāo)準(zhǔn)形態(tài)。迭代部分就是反復(fù)左乘沒有別的花樣。N_hist存的是每一步的完整年齡結(jié)構(gòu)不只是總量——這一點(diǎn)很重要因?yàn)長eslie模型的價(jià)值恰恰在結(jié)構(gòu)只存總量等于白跑。參數(shù)說明steps是迭代步數(shù)如果時(shí)間步是5年steps10就是預(yù)測50年。surv的最后一組在上一節(jié)已經(jīng)置0所以矩陣最后一行全0意味著最高年齡組的人下一步全部退出這是合理的封閉人口假設(shè)。3.2 主特征值與長期趨勢的讀法Leslie矩陣有個(gè)漂亮的性質(zhì)當(dāng)?shù)綌?shù)足夠多人口結(jié)構(gòu)會收斂到一個(gè)穩(wěn)定的年齡分布總量按矩陣的主特征值 $\lambda_1$ 等比增長。$\lambda_1 1$ 長期增長$1$ 長期衰減$1$ 穩(wěn)定。這個(gè)特征值就是長期增長率對應(yīng)的特征向量就是穩(wěn)定年齡結(jié)構(gòu)。[V, D] eig(L); lambda diag(D); [lambda_max, idx] max(real(lambda)); stable_struct real(V(:, idx)); stable_struct stable_struct / sum(stable_struct); % 歸一化為比例 fprintf(主特征值 lambda1 %.4f\n, lambda_max); fprintf(長期年增長率約 %.2f%%\n, (lambda_max^(1/5)-1)*100); % 步長5年換算這里有個(gè)容易忽略的點(diǎn)eig返回的特征值可能是復(fù)數(shù)取實(shí)部再找最大是常規(guī)操作因?yàn)長eslie矩陣是非負(fù)矩陣由Perron-Frobenius定理主特征值一定是正實(shí)數(shù)。換算年增長率時(shí)如果步長是5年要開5次方再減1直接拿 $\lambda_1-1$ 當(dāng)年度增長率是錯(cuò)的會高估好幾倍。3.3 結(jié)果可視化與結(jié)構(gòu)演化光看總量曲線不夠Leslie模型最該看的是年齡結(jié)構(gòu)怎么隨時(shí)間變形。我一般畫兩張圖一張總量隨時(shí)間的曲線一張用熱力圖或堆疊面積圖展示各年齡組占比的演化。figure; subplot(1,2,1); plot(0:steps, N_total, LineWidth, 1.5); xlabel(時(shí)間步每步5年); ylabel(女性總?cè)丝?; title(總量演化); grid on; subplot(1,2,2); prop N_hist ./ sum(N_hist, 1); % 各年齡組占比 imagesc(prop); colorbar; xlabel(時(shí)間步); ylabel(年齡組); title(年齡結(jié)構(gòu)演化);prop那一步是逐列歸一化得到每個(gè)時(shí)間點(diǎn)上各年齡組的占比。熱力圖能一眼看出老齡化是不是在加劇、育齡段占比是不是在萎縮。這比單看總量有信息量得多也是Leslie相對Logistic的核心優(yōu)勢所在。4. 參數(shù)敏感性、情景對比與常見誤用4.1 生育率假設(shè)怎么設(shè)才不拍腦袋Leslie模型最容易被質(zhì)疑的就是生育率假設(shè)——它直接決定長期結(jié)果而未來生育率誰也說不準(zhǔn)。穩(wěn)妥做法是不設(shè)單一情景而是設(shè)高、中、低三檔跑出包絡(luò)區(qū)間。中檔可以取當(dāng)前水平或略降高檔假設(shè)政策激勵(lì)見效回升低檔假設(shè)繼續(xù)下滑。三檔跑完結(jié)論表述成「在低方案下2050年總量為X高方案為Y」而不是給一個(gè)點(diǎn)估計(jì)。fert_low fert * 0.7; fert_mid fert; fert_high fert * 1.3; [~, ~, N_low] deal(0); % 占位實(shí)際調(diào)用 leslie_run [Nt_low, ~] leslie_run(pop_f, surv, fert_low, steps); [Nt_mid, ~] leslie_run(pop_f, surv, fert_mid, steps); [Nt_high, ~] leslie_run(pop_f, surv, fert_high, steps); plot(0:steps, Nt_low, --, 0:steps, Nt_mid, -, 0:steps, Nt_high, --); legend(低方案,中方案,高方案);三檔的倍數(shù)不是隨便定的要結(jié)合歷史波動幅度。如果過去二十年生育率波動在正負(fù)30%以內(nèi)那用0.7和1.3就是合理的包絡(luò)如果波動更大包絡(luò)要相應(yīng)放寬。這一步的嚴(yán)謹(jǐn)程度直接決定結(jié)論可信度。4.2 存活率隨時(shí)間的改進(jìn)要不要建模很多入門實(shí)現(xiàn)把存活率當(dāng)成常數(shù)跑幾十年不變。這在短期可以長期會低估壽命改善帶來的老年人口累積。常見做法是給存活率加一個(gè)隨時(shí)間緩慢上升的改進(jìn)因子比如每年提升0.1%到0.3%或者直接引用權(quán)威機(jī)構(gòu)的分年齡死亡率預(yù)測。加改進(jìn)因子后矩陣每步都要重建不能再用一個(gè)固定 $L$ 迭代到底。surv_t surv; for t 1:steps surv_t min(surv_t * 1.002, 0.999); % 每年存活率改進(jìn)0.2% L build_leslie(fert, surv_t); % 每步重建矩陣 N_hist(:, t1) L * N_hist(:, t); endmin(..., 0.999)是防止存活率被改進(jìn)到超過1這種物理上不可能的值。這個(gè)細(xì)節(jié)不注意跑幾十步后會出現(xiàn)存活率大于1的荒謬結(jié)果然后總量爆炸排查起來很費(fèi)時(shí)間。4.3 和Logistic混用的邊界在哪有人會想能不能把Leslie和Logistic結(jié)合用Logistic的環(huán)境容量去約束Leslie的總量可以但要清楚代價(jià)。Leslie本身是線性模型不含密度制約長期要么指數(shù)增長要么指數(shù)衰減。加容量約束相當(dāng)于在每步迭代后按Logistic方式壓縮總量這會破壞年齡結(jié)構(gòu)的自洽性——壓縮是均勻施加還是按年齡加權(quán)結(jié)果差別很大而且沒有公認(rèn)標(biāo)準(zhǔn)。我的建議是如果研究期在二三十年以內(nèi)純Leslie夠用如果非要引入容量明確寫出壓縮規(guī)則并做敏感性分析別默認(rèn)它無害。5. 避坑與排查Leslie模型跑出來不對勁時(shí)先看這幾條5.1 總量第一步就跳變現(xiàn)象初始向量代進(jìn)去第一步總量就和初始值差很多。原因生育率或存活率的單位口徑和步長不匹配比如年度生育率沒乘步長或者存活率用了千分比沒除以1000。解決把L打印出來逐行核對第一行的量級和次對角線的取值范圍存活率必須在0到1之間生育率量級要和人口數(shù)匹配。5.2 迭代若干步后出現(xiàn)負(fù)數(shù)或NaN現(xiàn)象跑著跑著人口出現(xiàn)負(fù)值或NaN。原因存活率被改進(jìn)因子推過1或者生育率里混入了負(fù)值或者初始向量里有NaN沒清理。解決迭代前加assert(all(surv0 surv1))和assert(all(fert0))把非法值擋在門外比事后排查省事得多。5.3 主特征值和總量曲線對不上現(xiàn)象算出來的 $\lambda_1$ 大于1但總量曲線卻在下降。原因多半是迭代步數(shù)太少還沒進(jìn)入主特征值主導(dǎo)的穩(wěn)定段前期的結(jié)構(gòu)瞬態(tài)還在起作用。解決把步數(shù)拉長到50步以上再看趨勢或者直接看最后若干步的比值是否收斂到 $\lambda_1$。5.4 年齡結(jié)構(gòu)占比之和不為1現(xiàn)象歸一化后的年齡結(jié)構(gòu)加起來不是1。原因N_hist某列全為0導(dǎo)致除零或者歸一化時(shí)用了錯(cuò)誤的維度。解決歸一化前檢查sum(N_hist,1)是否全為正用prop N_hist ./ sum(N_hist,1)而不是手動循環(huán)維度對不上會直接報(bào)錯(cuò)而不是靜默出錯(cuò)。5.5 預(yù)測結(jié)果對初始年齡結(jié)構(gòu)過度敏感現(xiàn)象只微調(diào)初始年齡結(jié)構(gòu)長期總量就明顯變化。原因如果初始結(jié)構(gòu)和穩(wěn)定結(jié)構(gòu)差得遠(yuǎn)前期會有較大的瞬態(tài)振蕩這是模型本身的特性不是bug。解決報(bào)告結(jié)果時(shí)區(qū)分短期受初始結(jié)構(gòu)影響大和長期受生育率存活率主導(dǎo)別把短期波動當(dāng)成長期趨勢。6. 把Leslie模型做成可復(fù)用的預(yù)測工具跑通一次不難難的是讓它變成一個(gè)換數(shù)據(jù)就能用、換情景就能比的小工具。我自己的習(xí)慣是把整個(gè)流程拆成三個(gè)函數(shù)prepare_data負(fù)責(zé)讀數(shù)據(jù)和對齊年齡組build_leslie負(fù)責(zé)構(gòu)造矩陣leslie_run負(fù)責(zé)迭代和輸出。主腳本只做參數(shù)設(shè)定和調(diào)用不摻計(jì)算邏輯。這樣換一個(gè)地區(qū)的數(shù)據(jù)只改prepare_data里的讀取路徑和分組邊界其余不動。再進(jìn)一步把情景對比也封裝起來。下面這個(gè)函數(shù)接收一組生育率情景返回每個(gè)情景的總量矩陣方便直接畫包絡(luò)圖function Nt_all leslie_scenarios(pop_f, surv, fert_base, steps, factors) % factors: 情景倍數(shù)向量如 [0.7 1.0 1.3] n_scen numel(factors); Nt_all zeros(steps1, n_scen); for j 1:n_scen [Nt, ~] leslie_run(pop_f, surv, fert_base*factors(j), steps); Nt_all(:, j) Nt(:); end end驗(yàn)證方法上我一般做兩件事。一是拿歷史數(shù)據(jù)回測用十年前的初始結(jié)構(gòu)和當(dāng)時(shí)的生育率存活率跑十年和實(shí)際人口對比看偏差在不在可接受范圍。二是做守恒檢查在沒有生育、存活率全為1的極端設(shè)定下總量應(yīng)該保持不變?nèi)绻兞苏f明矩陣構(gòu)造有錯(cuò)。這兩個(gè)檢查花不了多少時(shí)間但能擋掉大部分低級錯(cuò)誤。一個(gè)具體技巧是給結(jié)果加時(shí)間戳和參數(shù)快照。每次跑完把fert、surv、steps和結(jié)果一起存成.mat文件文件名帶上日期。過幾個(gè)月回頭看某個(gè)結(jié)論能立刻知道當(dāng)時(shí)用的什么參數(shù)不用靠記憶。這個(gè)習(xí)慣救過我很多次尤其是當(dāng)同一批數(shù)據(jù)被不同人改過之后。說到底Leslie模型的價(jià)值不在矩陣本身——它簡單到幾行代碼就能實(shí)現(xiàn)——而在于它逼你把年齡結(jié)構(gòu)、生育率、存活率這些真正決定人口走向的量擺到臺面上而不是用一條擬合曲線糊弄過去。參數(shù)怎么設(shè)、情景怎么分、結(jié)果怎么讀這些判斷才是功夫所在。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取