Sherry_z
发布于

论文复现 | CEO特质与企业数字化转型:QUBO模型变量选择 + 模拟退火求解


一、论文想解决什么问题?

传统实证研究经常遇到一个问题:解释变量很多,但文章篇幅和理论解释能力有限。

以 CEO 特质为例,至少可以分成三类:


维度变量
性别是否为女性 CEO
年龄31-40、41-50、51-60
职能背景生产、研发、设计、人力资源、管理、金融、市场、财务、法律

如果全部放进机制分析,文章会非常散;如果只挑其中几个,又容易被质疑"为什么选它们,不选别的"。

所以论文先做变量选择,再进入机制研究。核心思想是:用模型帮助研究者识别哪些 CEO 特质更重要,再围绕这些变量展开经济解释。



二、本次复现的主要输出


final_panel_logrd.csv
ols_results_logrd.txt
qubo_selection_results_sa_logrd.csv
table5_qubo_logrd.csv
table7_lag_regression_logrd.csv
table8_psm_regression_logrd.csv
table9_ceo_change_logrd.csv
paper_tables_5_7_8_9_logrd.xlsx

三、第一步:构造 CEO 特质变量

CEO 特质来自 CSMAR 的上市公司人物特征数据。复现中将 TMTP=1 或 TMTP=3 视为 CEO 样本,并从性别、年龄和职业背景中构造 0/1 变量。

职能背景的处理也很直观。CSMAR 中 Funback 是职业背景编码:

def has_funback(value, code):
    if pd.isna(value):
        return 0
    parts = [p.strip() for p in str(value).replace(",", ",").split(",")]
    return int(str(code) in parts)

df["ceo_produce"]  = df["Funback"].apply(lambda x: has_funback(x, 1))
df["ceo_research"] = df["Funback"].apply(lambda x: has_funback(x, 2))
df["ceo_design"]   = df["Funback"].apply(lambda x: has_funback(x, 3))
df["ceo_hr"]       = df["Funback"].apply(lambda x: has_funback(x, 4))
df["ceo_manage"]   = df["Funback"].apply(lambda x: has_funback(x, 5))
df["ceo_market"]   = df["Funback"].apply(lambda x: has_funback(x, 6))
df["ceo_finance"]  = df["Funback"].apply(lambda x: has_funback(x, 7))
df["ceo_account"]  = df["Funback"].apply(lambda x: has_funback(x, 8))
df["ceo_law"]      = df["Funback"].apply(lambda x: has_funback(x, 9))

如果同一公司同一年存在多个 CEO 记录,0/1 特质取最大值,年龄取均值:

agg_dict = {v: "max" for v in ceo_vars}
agg_dict["ceo_age"] = "mean"
out = df.groupby(["stock_code", "year"], as_index=False).agg(agg_dict)


四、第二步:先做 OLS,得到"全变量模型"的系数

QUBO 模型不是凭空构造的。论文的做法是先估计一个包含所有 CEO 特质、控制变量、行业固定效应和年份固定效应的 OLS 模型:

formula = "DT ~ " + " + ".join(ceo_vars + control_vars)
formula += " + C(industry_code) + C(year)"
model = smf.ols(formula=formula, data=panel).fit()

因变量 DT 是数字化转型指数。控制变量包括资产负债率、资产周转率、独董占比、董事人数、高管持股比例、无形资产比例、固定资产比例、研发投入等。

研发投入的处理:

rd_raw = to_num(df["RDExpenses"])
"rd_investment": np.log1p(rd_raw.clip(lower=0))

即使用 log(1 + RDExpenses),避免研发费用分布过度偏斜。

OLS 的作用有两个:

  1. 1. 给出各变量对数字化转型的基础估计。
  2. 2. 为 QUBO 模型提供系数,把"选不选变量"转化为"启用不启用 OLS 系数"。


五、第三步:QUBO 是什么?

QUBO 的全称是:

Quadratic Unconstrained Binary Optimization

中文通常称为"二次无约束二值优化模型"。它有两个特点:

  1. 1. 决策变量只能是 0 或 1。
  2. 2. 目标函数可以写成二次型:min x'Qx

这非常适合变量选择。因为"某个变量是否被选中"天然就是一个 0/1 问题:

  • • x_j = 1:第 j 个 CEO 特质进入模型
  • • x_j = 0:第 j 个 CEO 特质不进入模型

本次复现的决策变量为:

Intercept, Female,
age31_40, age41_50, age51_60,
Produce, Research, Design, HR, Manage, Finance, Market, Account, Law


六、第四步:把残差平方和写成 QUBO

论文借鉴 OLS 的思想,仍然以残差平方和最小为目标。区别在于,CEO 特质部分要乘上 0/1 选择变量。

names = ["Intercept"] + ceo_vars
beta0 = model.params.get("Intercept", 0.0)
beta_ceo = np.array([model.params.get(v, 0.0) for v in ceo_vars])
beta_qubo = np.concatenate([[beta0], beta_ceo])

X_ceo = panel[ceo_vars].values
X_qubo = np.column_stack([np.ones(len(panel)), X_ceo])

y_hat_total = model.fittedvalues.values
ceo_part = X_qubo @ beta_qubo
control_fe_part = y_hat_total - ceo_part

构造 QUBO 的二次型矩阵:

y = panel["DT"].values
residual_target = y - control_fe_part
weighted_x = X_qubo * beta_qubo

q_objective = weighted_x.T @ weighted_x
linear_term = -2 * (residual_target @ weighted_x)
q_objective = q_objective.copy()
np.fill_diagonal(q_objective, np.diag(q_objective) + linear_term)

这一步是从"回归问题"走向"QUBO 问题"的关键。



七、第五步:把约束也写进 QUBO

论文中 CEO 特质分为三个维度:性别、年龄、职能背景。设置如下约束:

  • • Intercept 必选
  • • Female 必选
  • • 年龄变量选择 b 个,b in {1, 2}
  • • 职能背景变量选择 c 个,c in {1, ..., 8}

QUBO 是"无约束"优化,不能直接把约束丢给求解器。解决方法是把约束改写成惩罚项。

def add_cardinality_penalty(q, indices, target, weight):
    """Add weight * (sum(x_i) - target)^2 to a QUBO matrix."""
    q = q.copy()
    diag_add = weight * (1 - 2 * target)
    for i in indices:
        q[i, i] += diag_add
    for pos, i in enumerate(indices):
        for j in indices[pos + 1:]:
            q[i, j] += weight
            q[j, i] += weight
    return q

完整约束:

q = add_cardinality_penalty(q, [0], 1, penalty_weight)
q = add_cardinality_penalty(q, [1], 1, penalty_weight)
q = add_cardinality_penalty(q, age_indices, b, penalty_weight)
q = add_cardinality_penalty(q, bg_indices, c, penalty_weight)


八、第六步:用模拟退火求解

模拟退火可以理解为一种"带有随机跳跃能力的搜索算法"。它不是从一开始就死盯局部最优,而是在高温阶段允许接受一些更差的解,以便跳出局部最优;随着温度下降,算法逐渐收敛到较优解。

本次复现使用的参数:

ANNEAL_READS   = 300
ANNEAL_SWEEPS  = 1800
ANNEAL_SEED    = 20260428
def anneal(q, b, c, seed):
    rng = np.random.default_rng(seed)
    best_feasible_x = None
    best_feasible_loss = np.inf

    t_start = max(1.0, float(np.nanpercentile(
        np.concatenate([diag, off_diag]), 95
    )))
    t_end = max(1e-6, t_start * 1e-4)

    for _ in range(ANNEAL_READS):
        x = make_initial_state(rng, b, c)
        energy = qubo_energy(q, x)

        for sweep in range(ANNEAL_SWEEPS):
            temperature = t_start * (t_end / t_start) ** (
                sweep / max(ANNEAL_SWEEPS - 1, 1)
            )
            k = int(rng.integers(0, len(x)))
            candidate = x.copy()
            candidate[k] = 1 - candidate[k]
            candidate_energy = qubo_energy(q, candidate)
            delta = candidate_energy - energy

            if delta <= 0 or rng.random() < math.exp(
                -delta / max(temperature, 1e-12)
            ):
                x = candidate
                energy = candidate_energy

            if constraint_violation(x, b, c) == 0:
                rss = loss(x)
                if rss < best_feasible_loss:
                    best_feasible_loss = rss
                    best_feasible_x = x.copy()

    return best_feasible_x, best_feasible_loss

约束检查函数:

def constraint_violation(x, b, c):
    return (
        (int(x[0]) - 1) ** 2
        + (int(x[1]) - 1) ** 2
        + (int(x[2:5].sum()) - b) ** 2
        + (int(x[5:14].sum()) - c) ** 2
    )

最终 16 组 (b, c) 的 constraint_violation 都为 0,说明求解结果满足论文设定的维度约束。



九、复现结果:QUBO 表 5

本次运行的最终可回归样本为 15420 条。模拟退火输出的表 5 风格结果如下:


bc31-4041-5051-60ProduceResearchDesignHRManageFinanceMarketAccountLaw
11010000010000
12010010010000
13010010010100
14010010110100
15010010110110
16010010111110
17010010111111
18010010111111
21011000010000
22011000010100
23011000010101
24011010010101
25011010110110
26011011110101
27011110110111
28011110111111

结果分析:

第一,年龄维度里,41-50 稳定出现;当允许选择两个年龄变量时,51-60 也进入模型。这与论文关于"大龄 CEO 更能解释数字化转型"的结论方向一致。

第二,职能背景中,Manage 几乎是最稳定的变量。也就是说,从"全局解释力"的角度看,管理背景 CEO 对企业数字化转型具有较强解释能力。

第三,随着允许选择的职能背景数量增加,Research、HR、Market、Account 等变量逐步进入模型。这说明 QUBO 不是简单地给变量排一个固定名次,而是在不同约束下寻找整体残差平方和更小的组合。



十、方法小结:为什么这套方法值得学?

OLS 回归回答的是:在控制其他因素后,每个 CEO 特质和数字化转型有什么统计关系?

LASSO 回答的是:哪些变量的影响更显著、更不容易被压缩为 0?

QUBO 回答的是:在给定变量数量约束下,哪一组 CEO 特质能让整体解释误差更小?

所以 QUBO 的优势不是替代 OLS,而是提供一种新的变量选择视角。它尤其适合这种"变量很多、变量有分组、每组想选固定数量"的研究场景。



十一、复现后的几点理解

第一,机器学习变量选择并不意味着放弃经济学解释。模型只是帮助我们更客观地缩小变量范围,真正的研究价值仍然来自后续机制解释。

第二,QUBO 的关键不是"量子"二字,而是把问题转写成适合 0/1 优化的形式。即使没有量子计算机,也可以先用模拟退火等经典算法求解。

第三,对论文复现来说,照着结果表做出来还不够。更重要的是理解原文为什么这样建模。如果只是用穷举得到类似表格,结果可能相近,但方法已经偏离了论文。

这次复现最大的收获也在这里:从"找一个最优组合"回到"构造一个 QUBO 模型",才算真正抓住了原文的方法核心。




浏览 (33)
点赞
收藏
删除
评论