实证研究开挂指南:机器学习让你的论文更有说服力【附可用代码】
一文搞懂常用机器学习算法
机器学习正在成为社科研究的重要工具。无论是预测企业创新绩效、识别政策影响,还是进行文本分类,机器学习方法都展现出强大能力。
本文系统梳理社科研究中最常用的机器学习算法,配以Python代码实现,零基础也能快速上手。
一、为什么社科研究者需要学习机器学习?
传统计量经济学的局限:
-
• 强假设:线性关系、独立同分布、完美共线性处理
-
• 预测能力有限:关注因果识别,但预测精度往往不足
-
• 高维数据处理困难:特征过多时容易过拟合
机器学习的优势:
| 方面 | 传统计量 | 机器学习 |
|---|---|---|
| 核心目标 | 因果推断 | 预测与模式识别 |
| 假设要求 | 严格 | 相对宽松 |
| 处理高维数据 | 较弱 | 强大 |
| 非线性关系 | 需要手动设定 | 自动捕捉 |
| 可解释性 | 较强 | 相对较弱 |
典型应用场景:
-
1. 企业创新绩效预测(专利数量、新产品收入)
-
2. 文本分类与情感分析(年报、新闻、社交媒体)
-
3. 政策效果异质性分析(哪些群体受益更大)
-
4. 合成控制法中的反事实预测
二、基础概念:训练集、测试集与交叉验证
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.preprocessing import StandardScaler
np.random.seed(42)
n = 500
data = pd.DataFrame({
'研发投入': np.random.lognormal(10, 1.5, n),
'企业规模': np.random.uniform(3, 8, n),
'融资约束': np.random.uniform(0, 1, n),
'政府补贴': np.random.choice([0, 1], n, p=[0.6, 0.4]),
'行业竞争度': np.random.uniform(0, 1, n),
'知识产权保护': np.random.uniform(0, 1, n),
})
data['专利数量'] = (
0.8 * data['研发投入'] / 10000 +
1.2 * data['企业规模'] +
-0.5 * data['融资约束'] +
0.7 * data['政府补贴'] +
np.random.normal(0, 2, n)
)
X = data.drop('专利数量', axis=1)
y = data['专利数量']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
三、线性回归:社科研究的基石
from sklearn.linear_model import LinearRegression, Ridge, Lasso, ElasticNet
from sklearn.metrics import mean_squared_error, r2_score, mean_absolute_error
lr_model = LinearRegression()
lr_model.fit(X_train_scaled, y_train)
y_pred_lr = lr_model.predict(X_test_scaled)
mse = mean_squared_error(y_test, y_pred_lr)
rmse = np.sqrt(mse)
r2_lr = r2_score(y_test, y_pred_lr)
print(f"线性回归 - RMSE: {rmse:.4f}, R²: {r2_lr:.4f}")
coef_df = pd.DataFrame({
'变量': X.columns,
'系数': lr_model.coef_
}).sort_values('系数', key=abs, ascending=False)
print(coef_df)
四、正则化回归:处理多重共线性的现代武器
# 岭回归(Ridge)
ridge = Ridge(alpha=1.0)
ridge.fit(X_train_scaled, y_train)
y_pred_ridge = ridge.predict(X_test_scaled)
r2_ridge = r2_score(y_test, y_pred_ridge)
# LASSO回归(自动特征选择)
lasso = Lasso(alpha=0.1)
lasso.fit(X_train_scaled, y_train)
y_pred_lasso = lasso.predict(X_test_scaled)
r2_lasso = r2_score(y_test, y_pred_lasso)
# 弹性网络
elastic = ElasticNet(alpha=0.1, l1_ratio=0.5)
elastic.fit(X_train_scaled, y_train)
y_pred_elastic = elastic.predict(X_test_scaled)
r2_elastic = r2_score(y_test, y_pred_elastic)
print(f"岭回归 R²: {r2_ridge:.4f}")
print(f"LASSO R²: {r2_lasso:.4f}")
print(f"弹性网络 R²: {r2_elastic:.4f}")
三种正则化方法对比:
| 方法 | 惩罚项 | 特点 | 适用场景 |
|---|---|---|---|
| 岭回归 | α·Σβ² | 保留所有特征,收缩系数 | 特征高度相关 |
| LASSO | α·Σ | β | |
| 弹性网络 | α·(ρ | β | +(1-ρ)β²/2) |
五、决策树:可解释的分割逻辑
from sklearn.tree import DecisionTreeRegressor, plot_tree
import matplotlib.pyplot as plt
dt_model = DecisionTreeRegressor(
max_depth=4,
min_samples_split=20,
min_samples_leaf=10,
random_state=42
)
dt_model.fit(X_train_scaled, y_train)
y_pred_dt = dt_model.predict(X_test_scaled)
r2_dt = r2_score(y_test, y_pred_dt)
feature_importance = pd.DataFrame({
'变量': X.columns,
'重要性': dt_model.feature_importances_
}).sort_values('重要性', ascending=False)
print(f"决策树 R²: {r2_dt:.4f}")
print(feature_importance)
六、随机森林:集成学习的经典代表
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
rf_model = RandomForestRegressor(
n_estimators=100,
max_depth=6,
min_samples_split=10,
min_samples_leaf=5,
random_state=42,
n_jobs=-1
)
rf_model.fit(X_train_scaled, y_train)
y_pred_rf = rf_model.predict(X_test_scaled)
r2_rf = r2_score(y_test, y_pred_rf)
# 超参数调优
from sklearn.model_selection import GridSearchCV
param_grid = {
'n_estimators': [50, 100, 200],
'max_depth': [4, 6, 8],
'min_samples_leaf': [5, 10]
}
grid_search = GridSearchCV(
RandomForestRegressor(random_state=42),
param_grid,
cv=5,
scoring='r2',
n_jobs=-1
)
grid_search.fit(X_train_scaled, y_train)
print(f"最优参数: {grid_search.best_params_}")
print(f"交叉验证最优R²: {grid_search.best_score_:.4f}")
best_rf = grid_search.best_estimator_
y_pred_best = best_rf.predict(X_test_scaled)
r2_best = r2_score(y_test, y_pred_best)
print(f"调优后随机森林 R²: {r2_best:.4f}")
随机森林的核心思想:
-
• Bagging:对训练数据进行有放回抽样,每棵树用不同样本训练
-
• 特征随机:每次分割只考虑随机选择的特征子集
-
• 集成预测:所有树预测结果的平均值
七、梯度提升树(XGBoost/LightGBM):Kaggle冠军算法
# sklearn原生梯度提升
gb_model = GradientBoostingRegressor(
n_estimators=100,
max_depth=4,
learning_rate=0.1,
random_state=42
)
gb_model.fit(X_train_scaled, y_train)
y_pred_gb = gb_model.predict(X_test_scaled)
r2_gb = r2_score(y_test, y_pred_gb)
# XGBoost
try:
from xgboost import XGBRegressor
xgb_model = XGBRegressor(
n_estimators=100,
max_depth=4,
learning_rate=0.1,
subsample=0.8,
colsample_bytree=0.8,
random_state=42,
n_jobs=-1
)
xgb_model.fit(X_train_scaled, y_train)
y_pred_xgb = xgb_model.predict(X_test_scaled)
r2_xgb = r2_score(y_test, y_pred_xgb)
# LightGBM
from lightgbm import LGBMRegressor
lgbm_model = LGBMRegressor(
n_estimators=100,
max_depth=4,
learning_rate=0.1,
random_state=42,
n_jobs=-1,
verbose=-1
)
lgbm_model.fit(X_train_scaled, y_train)
y_pred_lgbm = lgbm_model.predict(X_test_scaled)
r2_lgbm = r2_score(y_test, y_pred_lgbm)
print(f"梯度提升 R²: {r2_gb:.4f}")
print(f"XGBoost R²: {r2_xgb:.4f}")
print(f"LightGBM R²: {r2_lgbm:.4f}")
except ImportError:
print("请安装:pip install xgboost lightgbm")
r2_xgb = r2_gb
r2_lgbm = r2_gb
八、模型对比汇总
results = pd.DataFrame({
'模型': ['线性回归', '岭回归', 'LASSO', '弹性网络', '决策树',
'随机森林', '梯度提升', 'XGBoost', 'LightGBM'],
'R²': [r2_lr, r2_ridge, r2_lasso, r2_elastic, r2_dt,
r2_rf, r2_gb, r2_xgb, r2_lgbm]
}).sort_values('R²', ascending=False)
print("\n=== 模型性能汇总 ===")
print(results.to_string(index=False))
# 可视化对比
plt.figure(figsize=(10, 6))
colors = ['#2ecc71' if i == 0 else '#3498db' for i in range(len(results))]
bars = plt.barh(results['模型'], results['R²'], color=colors)
plt.xlabel('测试集 R²')
plt.title('机器学习模型性能对比')
plt.xlim(0, 1)
for bar, val in zip(bars, results['R²']):
plt.text(val + 0.01, bar.get_y() + bar.get_height()/2, f'{val:.4f}', va='center')
plt.tight_layout()
plt.savefig('model_comparison.png', dpi=150)
plt.close()
九、实战代码模板
# 社科研究机器学习分析模板
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
from sklearn.linear_model import Ridge
from sklearn.metrics import mean_squared_error, r2_score
# ========== 第一步:数据准备 ==========
# df = pd.read_csv('your_data.csv')
# X = df.drop('outcome_variable', axis=1)
# y = df['outcome_variable']
# ========== 第二步:数据分割 ==========
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# ========== 第三步:特征标准化 ==========
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# ========== 第四步:模型训练与评估 ==========
models = {
'Ridge回归': Ridge(alpha=1.0),
'随机森林': RandomForestRegressor(n_estimators=100, max_depth=6, random_state=42),
'梯度提升': GradientBoostingRegressor(n_estimators=100, max_depth=4, random_state=42)
}
for name, model in models.items():
model.fit(X_train_scaled, y_train)
y_pred = model.predict(X_test_scaled)
r2 = r2_score(y_test, y_pred)
rmse = np.sqrt(mean_squared_error(y_test, y_pred))
print(f"{name}: R²={r2:.4f}, RMSE={rmse:.4f}")
# ========== 第五步:交叉验证 ==========
rf_cv = RandomForestRegressor(n_estimators=100, max_depth=6, random_state=42)
cv_scores = cross_val_score(rf_cv, X_train_scaled, y_train, cv=5, scoring='r2')
print(f"\n随机森林5折交叉验证: {cv_scores.mean():.4f} ± {cv_scores.std():.4f}")
十、结语:机器学习是工具,不是银弹
机器学习为社科研究提供了强大的新工具,但使用时需要注意:
1. 因果推断 vs 预测
-
• 机器学习擅长预测,但因果识别仍需谨慎的识别策略
-
• 不要把预测系数误解为因果效应
2. 可解释性
-
• 社会科学研究强调理论解释
-
• 可以使用SHAP值等方法解释复杂模型
3. 数据质量
-
• 机器学习对数据质量要求很高
-
• Garbage in, garbage out
4. 研究问题导向
-
• 先明确研究问题,再选择合适方法
-
• 不要为了用机器学习而用
更多推荐
所有评论(0)