计量小课:计量经济学基础
计量经济学计量小课

虚拟变量一定要比定性变量的类别数少一个吗?什么情况下可以例外?这和机器学习的 One-Hot Encoding 一样吗?

你在 Stata 里跑一个包含\"地区\"(东/中/西三类)的回归:

作者:计量科研导航站发布:2026-07-29★★

一、开篇:Stata 自动帮你丢了一个虚拟变量——你知道它丢的是哪个、为什么丢吗?

你在 Stata 里跑一个包含"地区"(东/中/西三类)的回归:

reg y x i.region

Stata 输出里只出现了两个地区虚拟变量——比如 _Iregion_2(中部)和 _Iregion_3(西部)。东部消失了。

你翻了一下计量的教科书——"对于 k 个类别的定性变量,只需要放入 k−1 个虚拟变量,否则会陷入虚拟变量陷阱(Dummy Variable Trap)。"你知道 Stata 替你丢了一个,但你有没有想过:

  • 为什么是 k−1?不是 k−2? 丢两个也不行吗?
  • Stata 默认丢的是哪一个? 是以字母顺序最小的那个为基准,还是你能指定?
  • 有没有什么情况下可以把 k 个虚拟变量全放进去? 如果有,系数该怎么解读?
  • 这和机器学习里的 One-Hot Encoding 是一回事吗? 为什么在 OLS 里必须丢一个,但在 LASSO 和神经网络里似乎所有类别都有对应的参数?

核心信息:虚拟变量必须比类别数少一个的原因是——模型包含截距项时,如果把所有 k 个虚拟变量都放进去,它们和截距项之间会形成完美的线性依赖(k 个虚拟变量之和恒等于 1,恰好等于截距项所乘的常数 1)。这就是"虚拟变量陷阱"——OLS 在数学上无法求解,因为 X'X 矩阵不可逆。解决方式有两种:去掉一个虚拟变量(保留截距项),或者去掉截距项(保留所有虚拟变量)。机器学习的 One-Hot Encoding 在数学上和虚拟变量是完全相同的操作——但在不同算法中的处理方式不同:OLS 必须解决共线性问题(丢一个或去截距),而加了正则化的模型(LASSO、Ridge)和树模型对共线性的敏感度不同,有时可以保留所有类别编码。


二、虚拟变量陷阱的数学——为什么是 k−1?

2.1 完美共线性的生成机制

假设你有一个定性变量"地区",有 3 个类别:东部(East)、中部(Central)、西部(West)。

方案 A(全放进去)

Y=β0+β1East+β2Central+β3West+εY = \beta_0 + \beta_1 \cdot \text{East} + \beta_2 \cdot \text{Central} + \beta_3 \cdot \text{West} + \varepsilon

其中 East = 1 如果在东部否则 0,Central 和 West 同理。但注意——对于每一个观测:

East+Central+West=1(对所有人恒成立)\text{East} + \text{Central} + \text{West} = 1 \quad \text{(对所有人恒成立)}

而截距项 β₀ 乘以的也是一个恒为 1 的"隐式变量"。所以:

β01=β0(East+Central+West)\beta_0 \cdot \mathbf{1} = \beta_0 \cdot (\text{East} + \text{Central} + \text{West})

这意味着截距列等于三个虚拟变量列之和。X 矩阵的列之间存在完美的线性依赖——X'X 不可逆,OLS 无法求解。 Stata 会检测到这个依赖,并自动丢弃其中一个虚拟变量(或报错)。

方案 B(丢一个——标准做法)

丢掉 East,模型变为:

Y=β0+β2Central+β3West+εY = \beta_0 + \beta_2 \cdot \text{Central} + \beta_3 \cdot \text{West} + \varepsilon

现在:

  • 东部(基准组):Central = 0, West = 0 → E[Y | East] = β₀
  • 中部:Central = 1, West = 0 → E[Y | Central] = β₀ + β₂
  • 西部:Central = 0, West = 1 → E[Y | West] = β₀ + β₃

β₂ 的含义:中部和东部(基准组)在 Y 上的均值差异。 β₃ 的含义:西部和东部(基准组)在 Y 上的均值差异。

方案 C(丢截距——另一种合法方案)

Y=β1East+β2Central+β3West+εY = \beta_1 \cdot \text{East} + \beta_2 \cdot \text{Central} + \beta_3 \cdot \text{West} + \varepsilon

现在每一个 β 直接等于该组的 Y 的条件均值:

β1=E[YEast],β2=E[YCentral],β3=E[YWest]\beta_1 = \mathbb{E}[Y \mid \text{East}], \quad \beta_2 = \mathbb{E}[Y \mid \text{Central}], \quad \beta_3 = \mathbb{E}[Y \mid \text{West}]

方案 B 和方案 C 在数学上等价(拟合值完全相同),但系数的解读不同。 方案 B 里的 β₂ 和 β₃ 是"相对于基准组的差异";方案 C 里的 β₁, β₂, β₃ 是"各组的绝对均值"。

2.2 为什么是 k−1,不是更少?

丢一个虚拟变量足以打破完美共线性。丢两个以上不会让模型更"正确"——它只会让你丢失信息。如果你有 3 个类别但只放了 1 个虚拟变量(比如只区分"东部与否"),你等于把"中部"和"西部"合并到了一个组里——这可能是合理的如果它们之间确实没有差异,但你不是通过"丢变量"来实现这一点,而是通过重新编码(把中部和西部合并成一个"非东部"类别)。

结论:k−1 是恰好足以打破完美共线性且保留所有类别信息的数量。少一个 → 共线性打破。少两个 → 信息丢失,且不是因为"必须这样做",而是因为你主动选择了合并类别。


三、什么情况下可以例外?——四种可以放 k 个虚拟变量的场景

3.1 例外一:去掉截距项(回归过原点)

如上所述,模型去掉截距项后,k 个虚拟变量可以全部放入:

Y=β1D1+β2D2++βkDk+εY = \beta_1 D_1 + \beta_2 D_2 + \cdots + \beta_k D_k + \varepsilon

在 Stata 中:

reg y i.region, noconstant   // 去掉截距项,k 个虚拟变量全部保留

什么时候用?

  • 理论上 Y 在 X = 0 时应该为零(如"没有投入就没有产出")。
  • 你想直接得到每个类别的均值而不是相对于基准组的差异。
  • 在某些固定效应模型中,当你已经用 i.id 吸收了所有个体固定效应时,去掉截距项并将所有个体虚拟变量放入在计算上更方便(虽然 xtreg, fereghdfe 会自动处理)。

注意事项:去掉截距项后,R² 的计算方式和通常不同(不再是"相对于均值的变异被解释的比例"),Stata 输出的 R² 可能异常高——这在 noconstant 回归中是正常的,不代表模型更优。

3.2 例外二:多重定性变量——每个变量各自遵守 k−1 规则

当你同时放入多个定性变量时,每个定性变量各自丢一个虚拟变量,而不是所有虚拟变量总数减一。

例如:模型包含"地区"(3 类)和"行业"(5 类)。

  • 地区:放 2 个虚拟变量(丢东部)
  • 行业:放 4 个虚拟变量(丢农业)
  • 总共放了 2 + 4 = 6 个虚拟变量,加上截距项 → 没问题

为什么不是 2 + 4 = 6 导致共线性? 因为地区虚拟变量之和恒等于 1,行业虚拟变量之和恒等于 1,但地区虚拟变量之和 ≠ 行业虚拟变量之和——两组虚拟变量之间没有完美的线性依赖。共线性只存在于"同一个定性变量生成的一组虚拟变量"内部,不存在于不同组之间。

3.3 例外三:带有正则化的模型——LASSO 和 Ridge

在机器学习的广义线性模型中,如果加了 L1(LASSO)或 L2(Ridge)正则化,你可以把 k 个虚拟变量全放进去——即使存在完美共线性,正则化项也会让 X'X 矩阵可逆(因为加了一个正定矩阵 λI 到 X'X 上)。

但这并不意味着你应该这样做——全放进去的代价是系数的解读变得依赖于正则化参数 λ 的选择。在 LASSO 中,某个类别对应的系数可能被压缩到零——但"哪个类别被压到零"取决于 λ 的选择和数据的微小变动,而不是你主动选择的基准组。

实际操作中:在 Python 的 sklearn.linear_model.LassoRidge 中,即使你做了 One-Hot Encoding 保留了 k 列,模型也能跑——不是因为数学原理变了,而是因为正则化在 X'X 上加了一个对角矩阵,打破了奇异性。但这和 OLS 中去掉截距项的逻辑是不同的——它依赖于一个外部的惩罚参数。

3.4 例外四:树模型和基于距离的模型——共线性几乎不影响

在决策树、随机森林、梯度提升树(GBDT、XGBoost、LightGBM)中,完美共线性不会导致数学上的不可解——因为这些模型是一次只使用一个变量来做分割,而不是同时求解所有系数的线性方程组。k 个虚拟变量全放进去,树模型可能会选择其中一些、忽略另一些——多出来的虚拟变量不会让算法崩溃。

类似地,在 K-Nearest Neighbors 或支持向量机(SVM)中,全放 k 个虚拟变量会导致距离计算中某几个维度的信息被重复计数——但这通常不致命,只是不优雅。

但要注意:如果你在树模型中使用 One-Hot Encoding,类别数量很多时会导致维度爆炸(比如"城市"有 300 个类别 → 299 个虚拟变量)。这会让树模型在每个节点上需要搜索的分割数膨胀,降低效率。此时,标签编码(Label Encoding)或目标编码(Target Encoding)可能更好——但这是机器学习中的另一个话题了。


四、虚拟变量(Dummy Variable)和独热编码(One-Hot Encoding)——一样吗?

4.1 数学上是一回事——但"丢一列"的选择不同

虚拟变量编码和 One-Hot Encoding 在数学上完全相同:都是将 k 个类别的定性变量转化为 k 个 0/1 二值列。

但在实际操作中:

计量经济学(Stata) 机器学习(sklearn/pandas)
命名 Dummy Variable / Indicator Variable One-Hot Encoding
默认操作 自动丢一个(k−1 列),保留截距项 默认生成 k 列(pd.get_dummies(drop_first=False)
可以生成 k 列吗? 可以(加 noconstant 可以(默认行为)
可以生成 k−1 列吗? 默认行为 可以(pd.get_dummies(drop_first=True);sklearn 的 OneHotEncoder(drop='first')
为什么默认不同? 计量回归几乎总是包含截距项,必须丢一个避免共线性 ML 模型不一定有显式截距项,或正则化/树结构让共线性不是致命问题

核心结论:虚拟变量和 One-Hot Encoding 是同一种编码方式,只是两个领域的默认参数不同。在计量经济学中,默认 drop='first',因为模型默认有截距项。在机器学习中,默认 drop=None,因为模型不一定有显式截距项,且预处理管道(pipeline)通常把编码和建模分开,编码器不知道下游模型是否包含截距项。

4.2 Dummy Encoding vs One-Hot Encoding——中文翻译的锅

中文里常说的"哑变量编码"和"独热编码"被很多人当成两种不同的方法——这是翻译造成的人为分裂。实际上:

  • Dummy Variable Encoding(哑变量编码)通常指 k−1 列的版本(统计学/计量经济学的默认)。
  • One-Hot Encoding(独热编码)通常指 k 列的版本(机器学习的默认)。

但在英文统计和计量文献中,dummy variable, indicator variable, binary variable 经常混用,且并不默认 k−1——是"带截距的线性模型"这个具体场景要求了 k−1。编码本身无所谓 k 还是 k−1——它只是"把类别变成 0/1 列"的操作。 k 或 k−1 的选择取决于你如何建模截距项。

4.3 一个对比实例——Stata vs Python

Stata(计量经济学的标准操作)

reg y x i.region              // 自动丢一个 → 2 个虚拟变量
reg y x ibn.region, noconstant // 全放 → 3 个虚拟变量

Python(机器学习的标准操作)

# pandas
pd.get_dummies(df['region'], drop_first=False)  # 默认 3 列
pd.get_dummies(df['region'], drop_first=True)   # 等价于 Stata 默认:2 列
 
# sklearn
from sklearn.preprocessing import OneHotEncoder
OneHotEncoder(drop=None)      # 默认 3 列
OneHotEncoder(drop='first')   # 等价于 Stata 默认:2 列

R(可以两边都走)

lm(y ~ x + region, data)         # 自动丢一个 → k−1
lm(y ~ x + region - 1, data)     # 全放,去掉截距 → k

五、基准组的选择——被丢掉的不是"不重要",而是你的"比较锚点"

5.1 基准组怎么选——三条原则

因为 k−1 个虚拟变量的系数都是相对于被丢掉的基准组来解释的,你选择哪个类别作为基准组,直接决定了所有虚拟变量系数的含义。

原则一:选择在理论上最自然的"控制状态"或"默认状态"。

  • 研究"某政策对 GDP 的影响" → 基准组 = "未实施该政策的地区"。
  • 研究"学历对工资的影响" → 基准组 = "小学及以下"或"初中"(最低学历)。
  • 研究"治疗对健康的影响" → 基准组 = "未接受治疗的对照组"。

原则二:选择一个样本量足够大的组作为基准。

如果某个类别只有 10 个观测,把它作为基准组——所有其他组的系数都在和这 10 个观测的均值做比较——标准误会非常大("锚"自身就不稳)。

原则三:在论文中明确报告基准组是什么,以及为什么选它。

不要写"地区虚拟变量已控制"就完事。你应该写"地区虚拟变量以东部地区为基准组(该组样本量最大、且为政策的参照对象)"。

5.2 可以在 Stata 中指定基准组吗?

可以。Stata 默认以编码最小的那个值为基准组。用 ib 可以指定:

* 以"西部"为基准组(假设 region = 3 是西部)
reg y x ib3.region
 
* 以编码最小的组为基准(Stata 默认)
reg y x i.region
 
* 以编码最大的组为基准
reg y x ib(last).region
 
* 以频数最多的组为基准
reg y x ib(freq).region

六、常见误区和注意事项

6.1 误区一:把虚拟变量也做标准化

虚拟变量(0/1)不应该被标准化。标准化的虚拟变量不再是 0/1,其系数无法解读为"组间均值差异"——你等于把一个干净的组别标识变成了一个不知所云的值。

6.2 误区二:在交互项中忘记考虑虚拟变量的基准组

如果 M 是一个虚拟变量(M = 1 女性,M = 0 男性基准),X × M 的系数解读为"X 对 Y 的效应在女性中比男性多多少"。如果你把虚拟变量全放进去了(k 个),交互项 X × 每一个类别虚拟变量的系数含义就变成了"X 在该类别的效应"——解读不同,但信息等价。

6.3 误区三:认为"丢一个虚拟变量"损失了信息

不损失。k−1 个虚拟变量 + 截距项恰好等于 k 个虚拟变量 + 无截距项的所有信息。两组系数的关系可以互相转化——"相对于基准组的差值"和"各组的绝对均值"包含了完全相同的信息量,只是表述方式不同。


七、总结

虚拟变量的四条核心知识

  1. k 类定性变量 = k−1 个虚拟变量(在有截距的模型中)。 不是"少一个更简洁",而是"多一个模型就死了"——k 个虚拟变量之和恒等于截距列,导致 X'X 不可逆。

  2. 三种合法例外:去掉截距项(noconstant)→ 可以放 k 个;多重定性变量 → 每个变量各自遵守 k−1 规则;正则化模型(LASSO/Ridge)/树模型 → 允许共线性,模型不会崩溃,但解读方式不同。

  3. Dummy Variable = One-Hot Encoding,只是默认参数不同。 计量的默认是 drop='first'(因为模型默认有截距),ML 的默认是 drop=None(因为编码器不知道下游模型有没有截距)。编码本身一样的——0/1 列的分配完全等价。

  4. 基准组的选择不是任意的。 它决定了所有虚拟变量系数的含义——"相对于谁"。选最自然的控制状态、选样本量足够大的组、并在论文中明确报告。


一句话收尾

"虚拟变量陷阱的本质不是'编码方法不对',而是'你的线性模型已经有一个隐式的 1 在截距项里——不需要另一个显式的 1 从虚拟变量里跑出来和它打架'。计量经济学丢一个虚拟变量,机器学习保留所有列然后加正则化——两种做法的目标完全一致:让模型有唯一解。殊途同归,手段不同。"


八、B站/公众号呈现建议

  • B站视频:建议用"三个灯开关控制一盏灯"的比喻。开场画面:一盏灯(Y),墙上有三个开关(East, Central, West)。三个开关的线路串联在一起——无论你怎么拨开关,只要知道其中两个的位置,第三个就被决定了。旁白:"三个开关,看起来你可以独立控制它们——但实际上,其中一个永远是另外两个的'影子'。这就是虚拟变量陷阱——不是数学上的高深问题,而是'三个变量加在一起恒等于 1'这个简单事实。"然后转场到 Stata 输出:reg y i.region 只显示了两个系数。动画展示——第三个系数不是被"删除了",而是被"吸收进了截距项"。接下来展示去掉截距项的版本——三个系数全出来了,但它们的含义变成了"各组的均值"而不是"相对于基准组的差异"。最后对比 Python 的 One-Hot Encoding 和 Stata 的 Dummy Variable——同一个编码,不同的默认参数——"两边做的是同一件事,只是计量经济学的默认做法假设你的模型有截距项,机器学习不假设。"
  • 公众号:三种方案(k−1 虚拟变量 + 截距 / k 虚拟变量 + 无截距 / k 虚拟变量 + 正则化)的对比表建议做成三列信息图。虚拟变量 vs One-Hot Encoding 的对照表建议放在第四节核心位置。基准组选择的三原则做成卡片。Stata/Python/R 三种软件的代码对比做成横向代码块。
  • 推荐标题
    • 主标题:《虚拟变量一定要比类别数少一个吗?——从虚拟变量陷阱到 One-Hot Encoding》
    • 备选标题:《为什么 Stata 自动丢了一个虚拟变量?——k−1 规则的数学原理与四种例外》
    • 新媒体标题:《虚拟变量 vs One-Hot Encoding:计量经济学和机器学习的不同默认,做的是同一件事》
  • 金句提炼

    "虚拟变量陷阱的本质:你的模型已经在截距项里藏了一个'全1列'——k 个虚拟变量再加进来,等于把同一个 1 写了两次。数学上不可逆,逻辑上多余。"

    "丢一个虚拟变量不损失任何信息——它只是把其中一个组'钉'在了截距上,其他所有组在和它比较。被丢掉的那个不是被忽略——它成了比较的锚。"

    "Dummy Variable 和 One-Hot Encoding 是同一件事。区别只有一个:计量经济学默认你有一个截距项,所以先帮你丢了一列;机器学习不默认你有截距项,所以先帮你全保留了。两边的工程师知道自己在做什么——你需要知道为什么。"