首页 / 资讯中心 / 文章详情

回归分析人口预测实验:从一元线性到Logistic模型边界

回归分析人口预测实验:从一元线性到Logistic模型边界 ★ FEATURED ARTICLE
简介围绕“基于回归分析的人口数量预测”整理的课程实验论文面向统计学、应用统计及数据分析初学者适合作为回归分析课程实验、论文写作与人口预测建模的参考材料。压缩包内共1个doc文件约442KB内容为一份结构完整的实验论文涵盖指标选择与样本确定、一元线性回归散点图与理论模型设定、回归诊断以及多元回归中的数据标准化、逐步回归、多重共线性检测和主成分分析并延伸到曲线回归与Logistic模型。文档按摘要、前言、章节、结论与参考文献组织可帮助读者梳理从变量关系分析到预测建模的完整流程理解模型拟合与诊断的写作呈现方式。已有395人学习下载适合需要参考课程实验框架、补充回归建模思路的读者查阅。1. 从一张散点图开始这套回归分析课程实验到底能落地到什么程度基于回归分析的人口数量预测真正难的不是把公式敲进软件而是先回答三个问题用什么指标解释人口变化、样本期够不够长、模型外推到哪里就该停。这套统计课程实验论文把一元线性回归、多元线性回归、逐步回归、多重共线性、主成分分析、三次曲线和 Logistic 模型串成一条完整链路适合正在做课程设计、区域人口趋势分析或统计建模入门的人。它不承诺一套模型打天下反而把每个模型的失败边界写了出来这一点比单纯追求高 R² 更有参考价值。读者如果手里有一份年度统计表照着它的字段口径和诊断顺序走一遍能少走不少“模型拟合漂亮、预测一塌糊涂”的弯路。2. 一元线性回归从字段口径到回归诊断的四步复现一元线性回归看起来最简单实际最容易在第一步就埋雷。原文用粮食产量作为解释变量、总人口作为因变量先画散点图再设理论模型最后看模型摘要和系数表。这个顺序不能乱字段口径没对齐后面 R² 再高也只是数字好看。下面按“字段检查—散点图—模型估计—诊断读表”四步拆开代码用虚拟数据演示结构换成自己的年度样本时只改字段名和单位。2.1 指标选择和样本确定先把 y 与 x 的统计口径钉死原文的符号体系是x1 粮食产量、x2 GDP、x3 出生率、x4 死亡率y 为总人口。一元回归只取 x1 和 y多元回归再把 x2、x3、x4 放进去。这里第一个坑是单位粮食产量常用万吨GDP 常用亿元出生率和死亡率可能是千分号也可能是百分号总人口可能是万人也可能是人。单位不统一不会让软件报错但会让回归系数变得没法解释甚至把符号带反。样本确定不是“把表里有的年份全塞进去”。样本期要连续缺年要说明怎么补统计口径变化要标记出来。原文样本跨 35 年复现时至少检查三件事年份是否等间隔、字段是否有缺失、异常值是否来自口径变化而不是真实波动。常见做法是先建一张字段字典把角色、单位、来源口径、缺失处理方式写清楚再进模型。字段角色常用单位先检查什么year_index时间索引年序是否等间隔、有无缺年grain自变量 x1万吨统计范围是否一致gdp自变量 x2亿元现价与不变价是否混用birth_rate自变量 x3‰ 或 %小数点和单位death_rate自变量 x4‰ 或 %与出生率同口径population因变量 y万人年末与年均、常住与户籍import numpy as np import pandas as pd rng np.random.default_rng(2024) n 35 t np.arange(1, n 1) # 虚拟样本只演示字段结构不代表任何真实区域数据 grain rng.normal(50000, 6000, n) gdp rng.normal(200000, 80000, n) birth rng.normal(12.5, 1.2, n) death rng.normal(6.8, 0.4, n) population 90000 1.2 * grain - 2500 * birth rng.normal(0, 800, n) df pd.DataFrame({ year_index: t, grain: grain, gdp: gdp, birth_rate: birth, death_rate: death, population: population }) print(df.head()) print(df.isna().sum()) print(df[[grain, gdp, birth_rate, death_rate, population]].describe().T)这段代码先固定随机种子保证每次生成的虚拟样本一致n35 对应原文的样本跨度方便后面模拟逐步回归和主成分分析。describe().T把均值、标准差、最小值、最大值转置显示主要看有没有量纲离谱的字段以及出生率、死亡率是否在同一数量级。参数上rng.normal(均值, 标准差, 个数)只用于造演示数据真实分析时把df换成读取统计年鉴的 DataFrame字段名保持一致即可。提示一元回归只放一个自变量时不要把“R² 高”直接解释成“粮食产量决定人口”。它只说明样本期内这两个序列同向变动遗漏变量、趋势项和口径变化都可能造成高拟合。2.2 散点图与理论模型一元线性式怎么写、参数怎么估原文先绘制总人口与粮食产量的散点图观察样本点是否大致落在一条直线附近再设定理论模型y β0 β1x ε其中 β0 是截距β1 是斜率ε 是随机误差。斜率的经济含义是“粮食产量每增加一个单位总人口平均变化多少”但这个解释只在单位一致、样本期内关系稳定的前提下成立。散点图要看三件事整体是否线性、有没有明显离群点、样本两端是否出现弯曲。如果散点图两头翘、中间平硬套一元线性回归就会把非线性关系压成一条直线残差图一定会报警。import matplotlib.pyplot as plt import statsmodels.api as sm x df[grain] y df[population] plt.scatter(x, y, s18, alpha0.75) plt.xlabel(粮食产量虚拟数据万吨) plt.ylabel(总人口虚拟数据万人) plt.title(粮食产量与总人口的散点图演示数据) plt.show() X sm.add_constant(x) model_1 sm.OLS(y, X).fit() print(model_1.summary())sm.add_constant(x)给设计矩阵补一列常数项否则模型会被强制过原点截距消失系数解释也会变。sm.OLS(y, X).fit()做普通最小二乘估计summary()里重点看 R²、调整 R²、系数、标准误、t 值和 p 值。s18控制点的大小alpha0.75控制透明度点太密时调小一点能看出重叠程度。真实数据里如果散点图出现明显的喇叭形或弯曲先别急着加变量回到字段口径和样本期检查。原文的一元模型摘要里 R 约 0.909、R² 约 0.826系数表里斜率约 1.468、常数约 53054斜率 t 值约 12.5p 值小于 0.05。这个结果说明样本期内粮食产量与总人口同向变动很明显但标准误接近 4986预测误差不能忽略。读表时不要只看 R²标准误和残差分布才决定预测区间有多宽。2.3 回归诊断R²、t 检验、残差图看什么回归诊断不是“看一眼 p 值就结束”。一元线性回归至少要过四关模型整体有没有解释力、系数是不是显著、残差有没有规律、异常点有没有把线拉偏。模型摘要表给 R² 和调整 R²系数表给 B、标准误、Beta、t 和显著性残差图看拟合值和残差的散点是否随机落在 0 附近。残差如果出现弯曲说明线性形式不够残差如果出现喇叭形说明误差方差在变残差如果有个别点离群很远说明样本里可能有口径突变或录入错误。resid model_1.resid fitted model_1.fittedvalues plt.scatter(fitted, resid, s18) plt.axhline(0, colorred, linestyle--) plt.xlabel(拟合值) plt.ylabel(残差) plt.title(残差与拟合值检查非线性与异方差) plt.show() print(残差均值:, resid.mean()) print(残差标准差:, resid.std(ddof1))残差均值应该接近 0残差标准差用来和因变量量纲对比如果残差标准差接近甚至超过因变量的波动模型预测就没有实际意义。ddof1表示样本标准差和统计软件默认口径更接近。红线是 0 基线残差点应该围绕它随机散开不能形成明显的 U 形或漏斗形。出现 U 形时优先考虑加时间项、二次项或改用曲线回归出现漏斗形时考虑对数变换或稳健标准误。原文一元模型对末期样本的预测值偏高误差在千级。这个结果不奇怪一元模型只用了粮食产量一个变量样本期内的趋势被高 R² 掩盖外推时误差会被放大。实际写报告时除了 R²还要给残差标准差、预测误差和预测区间否则读者无法判断这个预测能不能用。2.4 用 SPSS 22.0 对照输出表系数表和模型摘要怎么读原文用 SPSS 22.0 做回归操作路径不复杂分析 → 回归 → 线性因变量放 population自变量放 grain统计量里勾选估计值、模型拟合、共线性诊断图里把 ZRESID 放 Y 轴、ZPRED 放 X 轴保存里勾选未标准化预测值和残差。跑完之后重点看三张表模型摘要、系数、残差统计。模型摘要看 R、R²、调整 R²、估计标准误系数表看非标准化系数 B、标准误、标准化 Beta、t 和显著性共线性诊断留到多元回归再看。非标准化系数 B 用来写预测公式标准化 Beta 用来比较变量相对重要性两者不能混着解释。常数项的显著性在很多教材里被忽略但预测时它直接决定基线水平。SPSS 输出里的“标准偏斜度错误”就是估计标准误数值越小样本点围绕回归线越紧。原文一元模型的标准误约 4986意味着点预测附近仍有不小的波动报告里不能只写一个点预测值。注意SPSS 里“显著性”一列就是 p 值小于 0.05 只说明在当前样本和模型设定下系数不为零不代表变量之间有因果方向。做预测报告时把模型形式、样本期、单位、缺失处理和异常点处理一起写出来否则别人没法复现。3. 多元线性回归中心化标准化、逐步回归与共线性排查一元回归把问题简化成一个解释变量多元回归才进入这套论文的主战场。原文把粮食产量、GDP、出生率、死亡率一起放进模型先做数据中心化和标准化再建多元回归然后用逐步回归筛变量接着用 VIF 和条件指数查多重共线性最后用主成分分析降维。这条链路不是每個步骤都必须做但每一步都在回答同一个问题变量多了以后系数还能不能信、预测还能不能稳。3.1 数据中心化与标准化量纲不同时先做什么中心化是每个变量减去均值标准化是在中心化之后再除以标准差。公式是 z (x - mean) / std。中心化不改变变量之间的相对关系只把坐标原点移到均值处标准化把不同量纲的变量拉到同一尺度方便比较系数大小也方便主成分分析和正则化。普通最小二乘回归在有截距的情况下对自变量做中心化不会改变拟合值和残差只会改变截距标准化会改变系数尺度但拟合值仍然等价。from sklearn.preprocessing import StandardScaler features [grain, gdp, birth_rate, death_rate] X_raw df[features] scaler StandardScaler() X_std pd.DataFrame( scaler.fit_transform(X_raw), columns[c _z for c in features] ) print(X_std.describe().T[[mean, std]])StandardScaler默认with_meanTrue、with_stdTrue做的是 z-score。输出里均值应该接近 0标准差接近 1如果某个字段标准差为 0说明它是常数列回归时会被自动丢弃或报共线性。标准化后的系数不能再按“原单位变化一单位”解释只能按“标准差变化一单位”解释。写报告时要么用原始变量建模、用标准化系数比较重要性要么全用标准化变量建模并明确说明尺度。原文在多元回归前做中心化和标准化目的是消掉量纲差异带来的数值误差。这个做法在变量量级差得远时很有用比如 GDP 是十万级、出生率是十级设计矩阵的条件数会变大。标准化之后再做 VIF 和主成分分析数值稳定性会好一些。但标准化不是万能的它不能修复样本口径不一致也不能把强共线性变没。3.2 多元回归模型建立字段矩阵和基准模型多元线性回归的形式是y β0 β1x1 β2x2 … βpxp ε原文把四个自变量一起放进模型模型摘要里 R 约 0.972、R² 约 0.944F 检验显著系数表里粮食产量和出生率显著GDP 和死亡率的 p 值大于 0.05。这个结果说明模型整体解释力很强但不是每个变量都该留在方程里。GDP 的系数很小、显著性不够死亡率的系数方向也需要结合业务判断不能因为模型整体显著就把所有变量都当成有效解释。X_multi sm.add_constant(df[features]) model_multi sm.OLS(df[population], X_multi).fit() print(model_multi.summary()) from statsmodels.stats.outliers_influence import variance_inflation_factor vif pd.DataFrame({ feature: X_multi.columns, VIF: [ variance_inflation_factor(X_multi.values, i) for i in range(X_multi.shape[1]) ] }) print(vif)X_multi里保留了常数项VIF 表里常数项那一行可以忽略重点看四个自变量的 VIF。经验阈值是VIF 大于 10 说明共线性较强5 到 10 需要关注小于 5 相对安全。VIF 的本质是 1/(1-Rj²)Rj² 是第 j 个自变量对其他自变量回归的 R²共线性越强Rj² 越接近 1VIF 越大。VIF 大不是“模型错了”而是系数估计方差变大显著性检验容易失真。原文多元模型里 GDP 和死亡率没有通过显著性检验接着用逐步回归做变量筛选。这里要提醒一句多元回归的系数符号和大小受其他变量影响单看某个变量的 p 值就删变量可能会把业务上必须的控制变量删掉。比较稳妥的做法是同时报告全变量模型、逐步回归模型和留出样本误差让读者看到筛选前后的差异。3.3 逐步回归法有进有出的变量筛选逐步回归的基本思想是“有进有出”先逐个把变量引入模型每引入一个就检查已引入变量是否还显著不显著就剔除直到没有变量可进也没有变量可出。原文用逐步回归剔除了 GDP保留了出生率、粮食产量和死亡率并报告了每一步的系数和显著性。逐步回归适合变量多、样本少、需要快速找子集的场景但它对样本量和共线性很敏感不能当成因果筛选工具。def stepwise_ols(data, y_col, candidate_cols, threshold_in0.05, threshold_out0.10): selected [] remaining candidate_cols[:] while True: changed False # 前向尝试加入当前最显著的变量 pvals {} for col in remaining: X sm.add_constant(data[selected [col]]) p sm.OLS(data[y_col], X).fit().pvalues[col] pvals[col] p if pvals: best min(pvals, keypvals.get) if pvals[best] threshold_in: selected.append(best) remaining.remove(best) changed True # 后向检查已选变量是否不再显著 if selected: X sm.add_constant(data[selected]) fit sm.OLS(data[y_col], X).fit() p_series fit.pvalues.drop(const) worst_p p_series.max() if worst_p threshold_out: worst p_series.idxmax() selected.remove(worst) remaining.append(worst) changed True if not changed: break final_fit sm.OLS( data[y_col], sm.add_constant(data[selected]) ).fit() return selected, final_fit selected, final_fit stepwise_ols( df, population, features, threshold_in0.05, threshold_out0.10 ) print(保留变量:, selected) print(final_fit.summary())threshold_in0.05是入模阈值threshold_out0.10是出模阈值出模阈值通常比入模阈值宽一点避免变量反复进出。函数返回保留变量列表和最终模型方便把系数、p 值和 VIF 一起报告。这段代码是教学版逐步回归真实项目里还要加最大迭代次数、变量共线性检查和异常样本检查。样本量很小时逐步回归的筛选结果可能换一批样本就变所以不要只报“最优子集”要把候选模型一起列出来。原文对比了一般多元回归和逐步回归的预测结果发现逐步回归不一定让预测更准。这个反直觉结论很重要逐步回归优化的是样本内显著性不是样本外误差被剔除的变量可能包含对外推有用的信息。写课程实验时可以把两种模型的预测误差并排放解释为什么“变量少”不等于“预测稳”。3.4 多重共线性检测VIF、条件指数和特征值多重共线性是指解释变量之间存在精确或高度相关关系导致系数估计失真、标准误变大、显著性检验失去意义。原文用了三个信号特征值接近 0、条件指数大于 10、相关系数矩阵里某些变量接近 1。SPSS 的共线性诊断表会给出特征值、条件指数和方差比例VIF 则在系数表里单独一列。三个信号要一起看不能只盯 VIF。指标经验阈值说明VIF大于 10 强共线性5 到 10 关注越小越好容忍度小于 0.1 强共线性VIF 的倒数条件指数大于 10 可能大于 30 严重看设计矩阵病态程度特征值接近 0提示维度退化原文剔除 GDP 后剩余变量的 VIF 全部小于 10说明共线性压力下降。但要注意VIF 小于 10 不代表没有共线性只代表在当前样本下没有强到让系数爆炸。如果变量之间有业务上的同步趋势比如经济指标和粮食产量同时上升VIF 可能被样本期长度掩盖。更稳的做法是看系数符号是否符合常识、标准误是否异常大、增加或删除一个样本后系数是否大幅跳动。处理共线性常见有三条路删变量、主成分回归、正则化回归。删变量最直接但可能丢掉业务信息主成分回归能压共线性但主成分解释困难正则化回归岭回归、Lasso适合预测优先的场景系数会有偏但方差更小。原文走的是“逐步回归 剔除 GDP 看 VIF”的路线适合课程实验不适合直接套到所有区域数据上。3.5 主成分分析降维之后为什么预测误差反而变大主成分分析用正交变换把相关变量转成不相关的主成分方差大的主成分排在前面。原文用 SPSS 22.0 做主成分分析前两个主成分累计贡献率约 94%于是用前两个主成分建回归模型。这个做法能降维、能缓解共线性但主成分是原始变量的线性组合解释起来比原始变量模糊。累计贡献率高只说明前几个主成分保留了大部分方差不说明它们一定保留了预测因变量最有用的信息。from sklearn.decomposition import PCA pca PCA(n_components2) Z pca.fit_transform(X_std) print(解释方差比:, pca.explained_variance_ratio_) print(累计解释方差:, pca.explained_variance_ratio_.cumsum()) components pd.DataFrame( pca.components_, columnsfeatures, index[PC1, PC2] ) print(components)n_components2是手动指定主成分个数实际项目里也可以设n_components0.85让累计解释方差达到 85% 后自动截断。components_是载荷矩阵每一行是一个主成分在各原始变量上的权重用来判断主成分的业务含义。载荷绝对值大的变量对主成分贡献大如果 PC1 在粮食产量和 GDP 上权重都很大它更像“经济规模综合因子”而不是某一个具体指标。主成分回归的系数不能直接解释成原变量效应报告里要写清楚这一点。原文用前两个主成分建回归后预测误差反而比某些原变量模型更大。原因不复杂主成分按方差大小排序不是按与因变量的相关性排序被丢掉的小方差主成分可能包含对外推有用的局部信息。主成分分析适合处理强共线性和高维变量不适合把“降维”当成默认动作。课程实验里可以保留 PCA 作为对照模型但最终选模型要看留出样本误差不是看累计贡献率。4. 非线性模型三次曲线与 Logistic 的适用边界人口序列很少是严格直线。样本期内可能先快后慢也可能出现阶段性的平台期。原文在非线性部分试了曲线回归和 Logistic 模型三次曲线对时间 t 的拟合非常好Logistic 模型则因为上限估计和初值问题失败。这一章的重点不是“哪个模型更高级”而是“哪个模型的外推边界更清楚”。4.1 曲线回归总人口对时间 t 的三次函数拟合原文以时间 t 为自变量以总人口为因变量先画总人口对 t 的散点图观察趋势大致符合三次函数形式再拟合y β0 β1t β2t² β3t³三次曲线能描述“先加速、后减速、再趋平”的趋势比一元直线灵活。原文三次模型的 R 接近 1R² 约 0.999标准误约 365整体 F 检验显著。但系数表里三次项的 p 值约 0.371说明最高次项在统计上并不显著模型的高拟合更多来自时间趋势和低次项。这个细节很重要R² 很高不代表每个高次项都有必要。coef3 np.polyfit(df[year_index], df[population], deg3) print(三次项系数高次到常数:, coef3) pred3 np.polyval(coef3, df[year_index]) resid3 df[population] - pred3 ss_res np.sum(resid3 ** 2) ss_tot np.sum((df[population] - df[population].mean()) ** 2) r2_3 1 - ss_res / ss_tot print(三次曲线 R²:, r2_3) t_next df[year_index].max() 1 print(下一期预测:, np.polyval(coef3, t_next))np.polyfit(..., deg3)返回的系数按高次到常数排列依次是 t³、t²、t、常数项。np.polyval用这组系数算拟合值和预测值。R² 用手工公式算一遍是为了和软件输出对照避免拿错模型对象。t_next只外推一期超过样本期太远时三次项会把预测拉得很快出现不合常理的上翘或下坠。真实项目里先把 t 中心化比如用t - t.mean()可以降低高次项的数值不稳定。注意三次曲线对时间外推很敏感样本期外的预测值可能迅速发散。报告里不要只给一个点预测至少给最近几期的滚动误差和预测区间。4.2 Logistic 模型初值、上限与收敛失败Logistic 增长模型的形式是p(t) a / (1 b * exp(-k * (t - t0)))其中 a 是上限规模b 是形状参数k 是增长率t0 是基准期。原文用 MATLAB 的fittype和fit做拟合初值取[2000 127627 1]模型表达式写成a/(1b*exp(-k*(x-1980)))。拟合结果里 a 约 1.217e5b 约 1.176e5k 约 13.21但置信区间非常宽b 和 k 的区间甚至跨到负值说明参数不可识别。更关键的是样本末期实际值已经超过拟合上限 a模型在样本内就失效了。from scipy.optimize import curve_fit def logistic(t, a, b, k): # a: 上限b: 形状参数k: 增长率t0 固定为 1 return a / (1 b * np.exp(-k * (t - 1))) p0 [df[population].max() * 1.2, 10.0, 0.05] bounds ([0, 0, 0], [np.inf, np.inf, 1.0]) params, pcov curve_fit( logistic, df[year_index], df[population], p0p0, boundsbounds, maxfev20000 ) print(a,b,k , params) pred_log logistic(df[year_index], *params) print(Logistic 残差平方和:, np.sum((df[population] - pred_log) ** 2))p0是初值a给样本最大值的一点二倍b给 10k给 0.05目的是让曲线从低位开始向上走。bounds把 a、b 限制为非负把 k 限制在 0 到 1避免拟合出负增长或爆炸参数。maxfev20000增大迭代次数收敛失败时先看初值和边界不要一味调大迭代。pcov是参数协方差矩阵对角线开根号就是标准误标准误过大说明参数估计不稳。Logistic 模型适合有明确上限的增长过程比如某个封闭区域的人口容量。它不适合样本期短、上限不可识别、样本内已经接近或超过上限的数据。原文的失败点很典型初值里 b 给得太大k 没有合理约束时间轴没有中心化导致参数空间很平拟合器找不到唯一解。复现时先把 t 中心化给 a 一个靠近样本最大值的初值再设边界收敛成功率会高很多。4.3 模型对比R² 高不等于外推可靠把一元线性、多元线性、逐步回归、主成分回归、三次曲线和 Logistic 放在一起比较最容易犯的错是只看样本内 R²。三次曲线的 R² 可以接近 1本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站