import numpy as np
import pandas as pd
from statsmodels.stats.outliers_influence import variance_inflation_factor
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import f1_score
# 1. 构造包含共线性与不平衡标签的数据集
np.random.seed(42)
N = 300
x1 = np.random.normal(10, 2, N)
x2 = x1 * 2.0 + np.random.normal(0, 0.01, N) # x2 与 x1 存在极强共线性!
x3 = np.random.normal(5, 1, N)
y = (x1 + x3 > 16.0).astype(int) # 不平衡标签
df = pd.DataFrame({'x1': x1, 'x2': x2, 'x3': x3})
# 2. 手算/计算 VIF 函数
def calculate_vif(X_df: pd.DataFrame) -> pd.DataFrame:
vif_data = pd.DataFrame()
vif_data["特征"] = X_df.columns
vif_data["VIF"] = [variance_inflation_factor(X_df.values, i) for i in range(X_df.shape[1])]
return vif_data
print("================ 1. 原始特征 VIF 多重共线性诊断 ================")
print(calculate_vif(df))
# 剔除高 VIF 特征 x2
df_clean = df.drop(columns=['x2'])
# 衍生新特征 x4 = x1 / x3 (比率特征)
df_clean['x4_ratio'] = df_clean['x1'] / df_clean['x3']
# 3. 三组消融实验 (Ablation Study)
X_tr0, X_te0, y_tr, y_te = train_test_split(df, y, test_size=0.3, random_state=42)
X_tr2, X_te2, _, _ = train_test_split(df_clean, y, test_size=0.3, random_state=42)
# Baseline 0: 原始特征
m0 = LogisticRegression().fit(X_tr0, y_tr)
f1_0 = f1_score(y_te, m0.predict(X_te0))
# Baseline 1: 剔除共线性特征
m1 = LogisticRegression().fit(X_tr0.drop(columns=['x2']), y_tr)
f1_1 = f1_score(y_te, m1.predict(X_te0.drop(columns=['x2'])))
# Baseline 2: 衍生特征 + 类别权重平衡 class_weight='balanced'
m2 = LogisticRegression(class_weight='balanced').fit(X_tr2, y_tr)
f1_2 = f1_score(y_te, m2.predict(X_te2))
print("\n================ 2. 特征消融实验报告 (Ablation Study) ================")
print(f"Baseline 0 (原始全量特征) - F1-Score: {f1_0:.4f}")
print(f"Baseline 1 (剔除高 VIF 共线性) - F1-Score: {f1_1:.4f} (Δ: {f1_1 - f1_0:+.4f})")
print(f"Baseline 2 (衍生比率+ClassWeight) - F1-Score: {f1_2:.4f} (Δ: {f1_2 - f1_1:+.4f})")