☰
拟合优度最高为何预测最差:六类回归模型对比
2026/10/28 2:12:26 网站建设 项目流程

简介:面向统计学课程实验与回归分析入门学习的课程论文文档,围绕人口数量预测这一具体问题,串联指标选择、样本确定、模型建立与诊断的完整流程。文档共1个doc文件,压缩包约442KB,以论文正文形式组织,包含摘要、前言、章节正文、结论与参考文献,便于按目录结构查阅和引用。已有395人学习下载,说明其在课程实验与论文参考场景中具有一定使用价值。内容从一元线性回归入手,涉及总人口与粮食产量散点图、理论模型设定与回归诊断;进而扩展到多元线性回归,涵盖数据中心化标准化、逐步回归、多重共线性检测与主成分分析;并补充曲线回归拟合与Logistic模型等非线性方法。读者可据此理解回归分析在人口预测中的建模思路、指标选择与结果解释,也可作为统计系课程实验报告的写作参考。

1. 拟合优度最高的模型,为什么预测得最不准

六个模型对 2014 年总人口的预测值排在一起看:一元线性回归 142165.8 万,多元全模型 138182.2 万,逐步回归 138506.2 万,主成分回归 142180.5 万,三次曲线 136174.9 万,真实值 136782 万。绝对误差从 172 万到 5398 万,跨了 31 倍。按 R² 排序,三次曲线 0.999 第一,多元全模型 0.944 第二,一元回归 0.826 垫底;按预测误差排序,逐步回归第一,三次曲线第三,一元回归和主成分回归垫底。两张榜单几乎不重叠。

这个错位不是数据脏,是"解释"和"预测"在统计建模里本来就是两个目标。R² 度量模型在已有样本上的压缩能力,预测误差度量模型把结构搬到样本外的能力。1980 到 2014 这 35 个观测,正好把六条建模路径的取舍压成了一张对照表,值得从机制层面一层层拆开。

2. 一元线性回归:0.909 的相关系数是怎么被"时间趋势"喂出来的

2.1 指标选择和基准线思维

影响人口的因素一大堆:经济水平、粮食供给、出生率、死亡率。实验里挑了四个能拿到连续年度数据的指标——粮食产量(万吨)、GDP(亿元)、出生率、死亡率,先让粮食产量和总人口单独跑一遍一元回归。

先做一元不是因为它准,是因为它便宜。一元回归给出一条基准线,后面每加一个变量、每换一种函数形式,都要回答"比基准线好多少"。没有这条线,R²=0.944 到底算优秀还是算凑合就没有参照系。模型选择这件事,本质上是一连串的相对比较,不是一个绝对阈值。

选粮食产量的理由写在散点图上:两个变量同向抬升,样本点大致落在一条直线附近。这个理由本身埋着雷。两个都随时间单调上升的序列,散点图必然近似直线,跟因果没有半点关系。粮食产量高的年份人口也多,不是因为粮食多养了人,是因为两个变量共享同一个"年份"驱动。

2.2 最小二乘的闭式解与系数的真实含义

一元线性回归的理论模型是 ŷ = β₀ + β₁x + ε,最小二乘的解可以写成闭式:

β₁ = Σ(xᵢ - x̄)(yᵢ - ȳ) / Σ(xᵢ - x̄)²,β₀ = ȳ - β₁x̄

这个式子的几何含义是:把 y 向量投影到由 1 和 x 张成的二维子空间上,残差向量与这个子空间正交。换成矩阵写法 β = (XᵀX)⁻¹Xᵀy,"正交"这件事就藏在 Xᵀ(y - Xβ) = 0 里。一元情形手算就行,多元情形才必须上矩阵,因为要对角化一个 p×p 的协方差结构。

import numpy as np import pandas as pd # 列:year, grain(万吨), gdp(亿元), birth, death, total(万人) df = pd.read_csv("population_1980_2014.csv").sort_values("year") X = np.column_stack([np.ones(len(df)), df["grain"].values]) # 设计矩阵,首列全 1 对应截距 y = df["total"].values beta = np.linalg.solve(X.T @ X, X.T @ y) # 正规方程闭式解,比 lstsq 更直观 y_hat = X @ beta resid = y - y_hat n, p = X.shape # n = 35, p = 2 sigma2 = resid @ resid / (n - p) # 残差方差,自由度 n - p se = np.sqrt(np.diag(sigma2 * np.linalg.inv(X.T @ X))) # 系数标准误 r2 = 1 - resid @ resid / ((y - y.mean()) @ (y - y.mean())) print(beta, se, np.sqrt(sigma2), r2) # beta ≈ [53054.404, 1.468] se ≈ [5500.013, 0.117] # 残差标准误 ≈ 4985.997 r2 ≈ 0.826

np.linalg.solve而不是inv,是因为前者做 LU 分解后回代,数值稳定性更好;X.T @ X在变量高度相关时会接近奇异,求逆的误差会被放大,这一点在第 4 章会变成主角。sigma2的分母是 n-p 而不是 n,因为拟合已经消耗掉 p 个自由度,残差平方和的期望要按自由度折算。se的对角线开方就是系数表里的"标准错误",那个被译成"标准偏斜度错误"的列,说的就是它。

代回数据得到 ŷ = 53054.404 + 1.468x。系数 1.468 的字面解释是:粮食产量每增加 1 万吨,总人口增加约 1.468 万人。这个数字在因果上说不通——1 万吨粮食撑不起 1.5 万人的一年口粮。但在统计上它成立,因为两个变量都在涨,1.468 只是两条趋势线斜率的比值。这类系数在计量经济学里有个不太客气的名字:伪回归系数。判断方法很朴素,把时间变量 t 加进模型,看粮食产量的系数会不会崩掉;或者对残差做序列相关检验,残差里如果还残留趋势,说明模型没把时间结构吸收干净。

2.3 回归诊断:四个数字各管一摊

统计软件输出了一张模型摘要和一张系数表,关键数字就四个:

指标数值它到底在管什么
R0.909两个变量的线性相关强度,开方前的原始尺度
R²0.826样本内被解释的方差比例,加变量只会升不会降
调整 R²0.821按变量个数惩罚后的解释比例,用于模型间比较
标准误4985.997残差的尺度,预测误差的量级下界

R=0.909 说明线性关系不弱,但 R²=0.826 同时说明还有 17.4% 的方差没被解释。这两句话经常被混着说,含义完全不同:前者是相关强度,后者是解释比例。

真正值得盯的是标准误 4985.997。它和后面 2014 年的预测误差 5383.8 处于同一量级,这不是巧合。残差标准误是"平均而言单点预测会偏多少"的估计,任何超出这个量级很多的预测误差,要么说明模型在端点外推,要么说明数据本身有结构突变。

系数表里两个 t 检验都显著(常数项 t=9.646,粮食产量 t=12.513,sig 都是 0.000)。显著只说明"这个系数不太可能是 0",不说明"这个模型有用"。35 个样本、两个参数,t 值大是常态。回归诊断最容易翻车的地方,就是把显著性当成拟合质量,把 R² 当成预测精度,两个都不对。

3. 多元线性回归:四个变量上桌后,系数为什么开始互相打架

3.1 中心化与标准化:量纲差五个数量级时会发生什么

四个自变量的量纲完全不在一个世界:粮食产量 6 万量级,GDP 到 63 万量级(亿元),出生率 12 上下,死亡率 7 上下。最大和最小差着五个数量级。

正规方程 XᵀX 的条件数会被这个差异直接放大。条件数是最大特征值和最小特征值的比值,量纲差 10⁵,条件数就可能到 10¹⁰,双精度浮点只有 16 位有效数字,求逆时误差能吃掉一半精度。标准化的作用就是把每个变量压到均值 0、标准差 1,让 XᵀX 退化成相关矩阵,条件数只由变量间的相关性决定,跟量纲无关。

中心化和标准化是两个动作。中心化只减均值,改变截距的含义;标准化再除标准差,连斜率也一起改。标准化后得到的系数叫标准化系数(系数表里的 Beta 列),解释是"自变量每变动一个标准差,因变量变动多少个标准差",它跟非标准化系数之间差一个 σy/σx 的换算。

这里有个高频误用:拿标准化系数直接写预测方程。标准化系数作用在 z 分数上,代原始数值进去算出来的结果没有任何意义。统计软件同时给出 B 列和 Beta 列,就是让人各取所需,写方程只能用 B 列。

3.2 多元 OLS 的矩阵形式和系数的可信度

四个变量一起进模型,矩阵形式和一元完全一样,只是 X 多了三列:

import numpy as np from scipy import stats def ols_full(X, y): Xd = np.column_stack([np.ones(len(X)), X]) # 补截距列,p = 自变量数 + 1 beta = np.linalg.solve(Xd.T @ Xd, Xd.T @ y) resid = y - Xd @ beta n, p = Xd.shape sigma2 = resid @ resid / (n - p) # 自由度 n - p cov = sigma2 * np.linalg.inv(Xd.T @ Xd) # 系数协方差矩阵 se = np.sqrt(np.diag(cov)) t = beta / se pval = 2 * stats.t.sf(np.abs(t), n - p) # 双尾 p 值 return {"beta": beta, "se": se, "t": t, "p": pval, "rmse": np.sqrt(sigma2)}

这里的自由度是 35 - 5 = 30,√sigma2 算出来是 2967.568,和模型摘要里的标准误一字不差。这个对应关系值得记牢:软件报的标准误不是拍脑袋估的,就是残差平方和除以自由度再开方。变异数分析表里 SSE=264193847.616,除以 30 得 8806461.587,开方 2967.568,链条完全闭合。

拟合结果 R=0.972、R²=0.944、调整 R²=0.936,F=126.295 且 sig=0.000,整体显著。方程是:

ŷ = 124574.667 + 1.045x₁ - 0.005x₂ - 1460.798x₃ - 4060.272x₄

逐个看系数就开始不对劲了。GDP 的系数 -0.005,意思是 GDP 每增加 1 亿元,人口减少 0.005 万人,也就是 50 人。这个数字既小得离谱,符号还是负的。出生率 -1460.798,出生率每上升 1 个单位人口减少 1460 万,量级勉强说得过去,但出生率的实际波动范围只有 11.9 到 23.3,一个单位的变动几乎不会发生。死亡率 -4060.272,同样的问题。

再看显著性:粮食产量 sig=0.000,出生率 sig=0.000,GDP sig=0.531,死亡率 sig=0.275。后两个都没通过。四个变量里有两个是摆设,而这两个恰好都是量级最大和共线性最强的。这不是巧合,是多重共线性在系数层面的典型症状——估计量方差被放大,t 值被压小,符号可能翻转。

3.3 逐步回归:有进有出的贪心搜索

逐步回归的思路很直白:变量一个一个进,每进一个就回头把已进的逐个复查,不显著的踢出去。整个过程是贪心的,每一步只看当前最优,不保证全局最优,但在变量数不多的时候够用。

这份实验跑出三步:

第一步只进出生率,常数 165146.388,系数 -2687.949,t=-12.794; 第二步进粮食产量,出生率系数变成 -1534.270,粮食产量 0.816; 第三步进死亡率,方程定格在 ŷ = 134678.878 + 1.012x₁ - 1366.202x₃ - 5681.557x₄。

有意思的地方在死亡率:它在全模型里 sig=0.275

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

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

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

立即咨询