Day 14:第二周复习与多模型综合对比

📋 目录

  1. 第二周知识点回顾
  2. 模型评估与选择方法论
  3. 量化交易中的模型评估框架
  4. 多模型融合策略
  5. 完整编程实战(4大模型综合对比)

第一部分:第二周知识点回顾(2小时理论)

1.1 Day 8:随机森林(Random Forest)

核心原理

  • Bagging:Bootstrap采样 + 聚合
  • 特征随机:每次分裂随机选择特征子集
  • OOB评估:利用袋外样本进行验证

关键参数

参数 作用 典型值
n_estimators 树的数量 100-500
max_depth 最大深度 10-30
min_samples_split 分裂最小样本数 2-10
max_features 特征子集大小 n\sqrt nn

优点:抗过拟合、可解释性强(特征重要性)
缺点:预测速度较慢、内存占用大

1.2 Day 9:随机森林调参

调参顺序

第1步:固定学习率,确定 n_estimators(观察OOB误差收敛)
第2步:调整 max_depth 和 min_samples_split
第3步:调整 min_samples_leaf 进一步正则化
第4步:调整 max_features 增加多样性

时间序列交叉验证

from sklearn.model_selection import TimeSeriesSplit
tscv = TimeSeriesSplit(n_splits=5)  # 训练集始终在测试集之前

1.3 Day 10:Boosting(AdaBoost & GBDT)

核心思想:串行训练,每次关注上一轮错误的样本

AdaBoost

  • 调整样本权重和模型权重
  • 指数损失函数
  • 基学习器通常是决策树桩

GBDT

  • 拟合负梯度(伪残差)
  • 支持多种损失函数
  • 学习率 $ \nu $ 控制每棵树贡献

关键公式
Fm(x)=Fm−1(x)+ν⋅γmhm(x)F_m(x)=F_{m−1}(x) + \nu \cdot \gamma_mh_m(x)Fm(x)=Fm1(x)+νγmhm(x)

1.4 Day 11:XGBoost & LightGBM

XGBoost核心创新

  • 二阶泰勒展开(更精确)
  • 内置正则化(gamma, lambda, alpha)
  • 并行计算支持

XGBoost目标函数
$ Obj = \sum L(y_i,\hat{y}_i) + \gamma T + 12\lambda |w|^2 $

LightGBM核心创新

  • 直方图算法(速度↑,内存↓)
  • Leaf-wise生长策略
  • GOSS采样(减少样本)
  • EFB特征捆绑

1.5 Day 12:SVM

核心原理

  • 最大间隔超平面
  • 软间隔(C参数)
  • 核技巧(RBF最常用)

关键参数

参数 作用 影响
C 惩罚系数 大→复杂,小→平滑
gamma RBF核参数 大→过拟合,小→欠拟合

重要提醒:SVM对特征缩放极其敏感,必须标准化!

1.6 Day 13:朴素贝叶斯

核心原理

  • 贝叶斯定理
  • 特征条件独立假设(朴素)

三种模型

模型 适用数据 分布假设
高斯NB 连续特征 正态分布
多项式NB 计数/频数 多项分布
伯努利NB 二值特征 伯努利分布

拉普拉斯平滑P(xi∣y=c)=Nic+αNc+α⋅KP(x_i|y=c) = \frac{N_{ic} + \alpha}{N_c + \alpha \cdot K}P(xiy=c)=Nc+αKNic+α


第二部分:模型评估与选择方法论

2.1 评估维度

维度 指标 说明
预测性能 准确率、AUC、F1 模型预测能力
训练效率 训练时间 模型构建速度
推理效率 预测时间 实时应用能力
稳定性 CV标准差 对数据变化的鲁棒性
可解释性 定性评估 能否理解决策过程
内存占用 模型大小 部署资源需求

2.2 模型选择决策树

数据规模?
├── 小数据(<1万)
│   ├── 需要可解释性 → 决策树/朴素贝叶斯
│   └── 追求精度 → SVM(RBF核)
│
├── 中数据(1万-10万)
│   ├── 需要可解释性 → 随机森林
│   └── 追求精度 → XGBoost/GBDT
│
└── 大数据(>10万)
    ├── 追求速度 → LightGBM
    ├── 追求精度 → XGBoost/LightGBM
    └── 实时预测 → 朴素贝叶斯/逻辑回归

2.3 量化交易模型选择考量

考量因素 说明
过拟合风险 金融数据信噪比低,优先选择正则化强的模型
推理速度 实时交易需要毫秒级响应
可解释性 风控合规可能需要解释决策
非线性关系 市场存在非线性,需要核函数或树模型
时间序列特性 必须使用时间序列交叉验证

第三部分:量化交易中的模型评估框架

3.1 评估指标选择

场景 主要指标 次要指标
涨跌预测 AUC、F1 准确率
极端事件预警 召回率 精确率
策略回测 夏普比率 最大回撤
实时风控 推理时间 内存占用

3.2 交叉验证策略

# 时间序列交叉验证(必须!)
from sklearn.model_selection import TimeSeriesSplit
tscv = TimeSeriesSplit(n_splits=5)

# 带间隔的交叉验证(防止短期依赖泄露)
tscv_gap = TimeSeriesSplit(n_splits=5, gap=5)

3.3 统一的评估框架

def evaluate_model(model, X_train, y_train, X_test, y_test, name):
    """统一的模型评估框架"""
    start = time.time()
    model.fit(X_train, y_train)
    train_time = time.time() - start
    
    start = time.time()
    y_pred = model.predict(X_test)
    predict_time = time.time() - start
    
    # 获取概率(如果支持)
    if hasattr(model, 'predict_proba'):
        y_proba = model.predict_proba(X_test)[:, 1]
    else:
        y_proba = None
    
    return {
        'model': name,
        'accuracy': accuracy_score(y_test, y_pred),
        'precision': precision_score(y_test, y_pred),
        'recall': recall_score(y_test, y_pred),
        'f1': f1_score(y_test, y_pred),
        'auc': roc_auc_score(y_test, y_proba) if y_proba is not None else None,
        'train_time': train_time,
        'predict_time': predict_time
    }

第四部分:多模型融合策略

4.1 融合方法

方法 原理 适用场景
投票法 多数投票 模型性能相近
加权投票 根据性能加权 模型差异明显
Stacking 元学习器组合 追求最高精度
Blending 预留验证集训练元模型 数据量充足

4.2 简单投票融合

def ensemble_voting(predictions_list):
    """多数投票融合"""
    predictions = np.array(predictions_list)
    return np.round(np.mean(predictions, axis=0))

4.3 Stacking融合

from sklearn.ensemble import StackingClassifier

stacking = StackingClassifier(
    estimators=[('rf', rf), ('xgb', xgb), ('svm', svm)],
    final_estimator=LogisticRegression()
)

第五部分:完整编程实战(4大模型综合对比)

实战目标

  1. 复习第二周学习的4个核心算法
  2. 在同一金融数据集上系统对比模型性能
  3. 从多个维度评估模型优劣
  4. 总结不同算法在量化预测中的适用场景
  5. 实现多模型融合策略

%% [markdown]

5.1. 导入必要的库

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import time
import warnings
warnings.filterwarnings('ignore')
from pathlib import Path

# 模型库
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.svm import SVC
from sklearn.naive_bayes import GaussianNB
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import StackingClassifier, VotingClassifier

# XGBoost
import xgboost as xgb

# 预处理和评估
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import TimeSeriesSplit, cross_val_score
from sklearn.metrics import (
    accuracy_score, precision_score, recall_score, f1_score,
    roc_auc_score, roc_curve, confusion_matrix, classification_report
)

# 预设样式
sns.set_style("whitegrid") 
#启用LaTeX渲染(如果系统安装了LaTeX)
plt.rcParams['text.usetex'] = False
# 设置中文显示
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['mathtext.fontset'] = 'dejavusans'  # 或 'stix'

5.2. 生成金融数据集

def generate_financial_data(ts_code):
    """生成金融数据"""
    
    data_path = Path(r"E:\AppData\quant_trade\klines\kline2014-2024")
    kline_file = data_path / f"{ts_code}.csv"
    
    df = pd.read_csv(kline_file, usecols=["trade_date", "close", "vol"],
                     parse_dates=["trade_date"])\
            .rename(columns={"vol": "volume"})\
            .sort_values(by=["trade_date"])\
            .reset_index(drop=True)
    
    df['return'] = df['close'].pct_change()
    
    # 技术指标
    # RSI
    delta = df['return'].fillna(0)
    gain = delta.where(delta > 0, 0).rolling(14).mean()
    loss = -delta.where(delta < 0, 0).rolling(14).mean()
    rs = gain / (loss + 1e-10)
    df['rsi'] = 100 - (100 / (1 + rs))
    
    # MACD
    ema12 = df['close'].ewm(span=12, adjust=False).mean()
    ema26 = df['close'].ewm(span=26, adjust=False).mean()
    df['macd'] = ema12 - ema26
    df['macd_signal'] = df['macd'].ewm(span=9, adjust=False).mean()
    
    # 均线比率
    df['ma5'] = df['close'].rolling(5).mean()
    df['ma20'] = df['close'].rolling(20).mean()
    df['ma_ratio'] = df['ma5'] / df['ma20'] - 1
    
    # 波动率
    df['volatility'] = df['return'].rolling(20).std()
    
    # 成交量比率
    df['volume_ratio'] = df['volume'] / df['volume'].rolling(10).mean()
    
    # 动量指标
    for lag in [1, 2, 3, 5, 10]:
        df[f'momentum_{lag}'] = df['return'].shift(lag).fillna(0)
    
    # 目标变量:3日是否上涨
    df['target'] = (df['close'].shift(-3) > df['close']).astype(int)
    
    # 删除缺失值
    df = df.dropna()
    
    return df

# 生成数据
print("生成金融数据...")
ts_code = "300033.SZ"
df = generate_financial_data(ts_code)
print(f"数据形状: {df.shape}")

# 特征选择
feature_cols = ['rsi', 'macd', 'macd_signal', 'ma_ratio', 'volatility', 
                'volume_ratio', 'momentum_1', 'momentum_2', 'momentum_3', 
                'momentum_5', 'momentum_10']
X = df[feature_cols].values
y = df['target'].values

print(f"特征数量: {len(feature_cols)}")
print(f"样本数量: {len(X)}")
print(f"目标分布: \n{pd.Series(y).value_counts(normalize=True)}")

# 按时间划分(70%训练,30%测试)
split_idx = int(len(X) * 0.7)
X_train_raw = X[:split_idx]
X_test_raw = X[split_idx:]
y_train = y[:split_idx]
y_test = y[split_idx:]

print(f"\n训练集: {len(X_train_raw)} 样本")
print(f"测试集: {len(X_test_raw)} 样本")

# 标准化(SVM需要,其他模型可选但统一处理)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train_raw)
X_test = scaler.transform(X_test_raw)
生成金融数据...
数据形状: (2451, 18)
特征数量: 11
样本数量: 2451
目标分布: 
0    0.510812
1    0.489188
Name: proportion, dtype: float64

训练集: 1715 样本
测试集: 736 样本

5.3. 定义统一评估函数

def comprehensive_evaluation(model, X_train, y_train, X_test, y_test, model_name):
    """全面评估模型性能"""
    
    # 训练时间
    start = time.time()
    model.fit(X_train, y_train)
    train_time = time.time() - start
    
    # 预测时间
    start = time.time()
    y_pred = model.predict(X_test)
    predict_time = time.time() - start
    
    # 概率预测(如果支持)
    if hasattr(model, 'predict_proba'):
        y_proba = model.predict_proba(X_test)[:, 1]
        auc = roc_auc_score(y_test, y_proba)
    else:
        y_proba = None
        auc = None
    
    # 基础指标
    accuracy = accuracy_score(y_test, y_pred)
    precision = precision_score(y_test, y_pred)
    recall = recall_score(y_test, y_pred)
    f1 = f1_score(y_test, y_pred)
    
    # 时间序列交叉验证
    tscv = TimeSeriesSplit(n_splits=3)
    try:
        cv_scores = cross_val_score(model, X_train, y_train, cv=tscv, 
                                    scoring='roc_auc', n_jobs=-1)
        cv_mean = cv_scores.mean()
        cv_std = cv_scores.std()
    except:
        cv_mean, cv_std = None, None
    
    return {
        'model': model_name,
        'accuracy': accuracy,
        'precision': precision,
        'recall': recall,
        'f1': f1,
        'auc': auc,
        'train_time': train_time,
        'predict_time': predict_time,
        'cv_auc_mean': cv_mean,
        'cv_auc_std': cv_std,
        'y_pred': y_pred,
        'y_proba': y_proba
    }

5.4. 训练4个核心模型

5.4.1 随机森林
print("="*60)
print("1. 训练随机森林模型")
print("="*60)

rf_model = RandomForestClassifier(
    n_estimators=200,
    max_depth=15,
    min_samples_split=5,
    min_samples_leaf=2,
    random_state=42,
    n_jobs=-1
)

rf_results = comprehensive_evaluation(
    rf_model, X_train, y_train, X_test, y_test, "随机森林"
)

print(f"准确率: {rf_results['accuracy']:.4f}")
print(f"AUC: {rf_results['auc']:.4f}")
print(f"训练时间: {rf_results['train_time']:.2f}秒")
============================================================
1. 训练随机森林模型
============================================================
准确率: 0.5326
AUC: 0.5417
训练时间: 0.62秒
5.4.2 XGBoost
print("="*60)
print("2. 训练XGBoost模型")
print("="*60)

xgb_model = xgb.XGBClassifier(
    n_estimators=200,
    learning_rate=0.05,
    max_depth=6,
    min_child_weight=3,
    subsample=0.8,
    colsample_bytree=0.8,
    random_state=42,
    n_jobs=-1,
    eval_metric='logloss'
)

xgb_results = comprehensive_evaluation(
    xgb_model, X_train, y_train, X_test, y_test, "XGBoost"
)

print(f"准确率: {xgb_results['accuracy']:.4f}")
print(f"AUC: {xgb_results['auc']:.4f}")
print(f"训练时间: {xgb_results['train_time']:.2f}秒")
============================================================
2. 训练XGBoost模型
============================================================
准确率: 0.5326
AUC: 0.5404
训练时间: 0.36秒
5.4.3 SVM(RBF核)
print("="*60)
print("3. 训练SVM模型")
print("="*60)

svm_model = SVC(
    kernel='rbf',
    C=1.0,
    gamma='scale',
    probability=True,
    random_state=42
)

svm_results = comprehensive_evaluation(
    svm_model, X_train, y_train, X_test, y_test, "SVM"
)

print(f"准确率: {svm_results['accuracy']:.4f}")
print(f"AUC: {svm_results['auc']:.4f}")
print(f"训练时间: {svm_results['train_time']:.2f}秒")

============================================================
3. 训练SVM模型
============================================================
准确率: 0.5149
AUC: 0.5144
训练时间: 1.22秒
5.4.4 朴素贝叶斯
print("="*60)
print("4. 训练朴素贝叶斯模型")
print("="*60)

nb_model = GaussianNB()

nb_results = comprehensive_evaluation(
    nb_model, X_train, y_train, X_test, y_test, "朴素贝叶斯"
)

print(f"准确率: {nb_results['accuracy']:.4f}")
print(f"AUC: {nb_results['auc']:.4f}")
print(f"训练时间: {nb_results['train_time']:.2f}秒")
============================================================
4. 训练朴素贝叶斯模型
============================================================
准确率: 0.5231
AUC: 0.5170
训练时间: 0.00秒

5.5. 综合性能对比

5.5.1 性能汇总表
# 收集所有结果
all_results = [rf_results, xgb_results, svm_results, nb_results]

results_df = pd.DataFrame([{
    '模型': r['model'],
    '准确率': r['accuracy'],
    '精确率': r['precision'],
    '召回率': r['recall'],
    'F1分数': r['f1'],
    'AUC': r['auc'],
    '训练时间(s)': r['train_time'],
    '预测时间(s)': r['predict_time']
} for r in all_results])

print("="*80)
print("4大模型性能对比汇总")
print("="*80)
print(results_df.to_string(index=False))

# 标注最佳
print("\n" + "="*80)
print("各指标最佳模型")
print("="*80)

metrics = ['准确率', 'AUC', 'F1分数', '训练时间(s)', '预测时间(s)']
for metric in metrics:
    if metric in ['训练时间(s)', '预测时间(s)']:
        best_idx = results_df[metric].idxmin()
    else:
        best_idx = results_df[metric].idxmax()
    print(f"{metric:12s}: {results_df.loc[best_idx, '模型']:10s} ({results_df.loc[best_idx, metric]:.4f})")

================================================================================
4大模型性能对比汇总
================================================================================
     模型      准确率      精确率      召回率     F1分数      AUC  训练时间(s)  预测时间(s)
   随机森林 0.532609 0.490358 0.528190 0.508571 0.541651 0.621225 0.046460
XGBoost 0.532609 0.490358 0.528190 0.508571 0.540416 0.364628 0.002168
    SVM 0.514946 0.467105 0.421365 0.443058 0.514409 1.217710 0.142187
  朴素贝叶斯 0.523098 0.451389 0.192878 0.270270 0.517034 0.001850 0.000471

================================================================================
各指标最佳模型
================================================================================
准确率         : 随机森林       (0.5326)
AUC           : 随机森林       (0.5417)
F1分数         : 随机森林       (0.5086)
训练时间(s)     : 朴素贝叶斯      (0.0018)
预测时间(s)     : 朴素贝叶斯      (0.0005)
5.5.2 可视化对比
fig, axes = plt.subplots(2, 2, figsize=(14, 10))

# 1. 性能指标条形图
metrics_plot = ['准确率', '精确率', '召回率', 'F1分数', 'AUC']
x = np.arange(len(results_df['模型']))
width = 0.15
for i, metric in enumerate(metrics_plot):
    axes[0, 0].bar(x + i*width, results_df[metric], width, label=metric)
axes[0, 0].set_xticks(x + width*2)
axes[0, 0].set_xticklabels(results_df['模型'])
axes[0, 0].set_ylabel('分数')
axes[0, 0].set_title('模型性能指标对比')
axes[0, 0].legend()
axes[0, 0].grid(True, alpha=0.3)

# 2. 时间对比
axes[0, 1].bar(x - width/2, results_df['训练时间(s)'], width, label='训练时间', color='blue')
axes[0, 1].bar(x + width/2, results_df['预测时间(s)'], width, label='预测时间', color='red')
axes[0, 1].set_xticks(x)
axes[0, 1].set_xticklabels(results_df['模型'])
axes[0, 1].set_ylabel('时间 (秒)')
axes[0, 1].set_title('训练与预测时间对比')
axes[0, 1].legend()
axes[0, 1].set_yscale('log')
axes[0, 1].grid(True, alpha=0.3)

# 3. ROC曲线对比
for r in all_results:
    if r['y_proba'] is not None:
        fpr, tpr, _ = roc_curve(y_test, r['y_proba'])
        axes[1, 0].plot(fpr, tpr, linewidth=2, label=f"{r['model']} (AUC={r['auc']:.4f})")
axes[1, 0].plot([0, 1], [0, 1], 'k--', linewidth=1, label='随机分类器')
axes[1, 0].set_xlabel('假阳性率 (FPR)')
axes[1, 0].set_ylabel('真阳性率 (TPR)')
axes[1, 0].set_title('ROC曲线对比')
axes[1, 0].legend(loc='lower right')
axes[1, 0].grid(True, alpha=0.3)

# 4. 雷达图
from math import pi
# ['准确率', '精确率', '召回率', 'F1分数', 'AUC']
metrics_radar = ['accuracy', 'precision', 'recall', 'f1', 'auc']
angles = [n / len(metrics_radar) * 2 * pi for n in range(len(metrics_radar))]
angles += angles[:1]

for r in all_results:
    values = [r[m] for m in metrics_radar]
    values += values[:1]
    axes[1, 1].plot(angles, values, 'o-', linewidth=2, label=r['model'])
axes[1, 1].set_xticks(angles[:-1])
axes[1, 1].set_xticklabels(metrics_radar)
axes[1, 1].set_ylim(0, 1)
axes[1, 1].set_title('模型性能雷达图')
axes[1, 1].legend(loc='upper right')

plt.suptitle('4大模型综合性能对比', fontsize=14)
plt.tight_layout()
plt.show()

在这里插入图片描述

5.5.3 混淆矩阵对比
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
axes = axes.ravel()

models_plot = [(rf_results, '随机森林'), (xgb_results, 'XGBoost'), 
               (svm_results, 'SVM'), (nb_results, '朴素贝叶斯')]

for idx, (r, name) in enumerate(models_plot):
    cm = confusion_matrix(y_test, r['y_pred'])
    sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', ax=axes[idx],
                xticklabels=['下跌', '上涨'], yticklabels=['下跌', '上涨'])
    axes[idx].set_title(f'{name}\n准确率: {r["accuracy"]:.4f}')
    axes[idx].set_xlabel('预测')
    axes[idx].set_ylabel('真实')

plt.suptitle('混淆矩阵对比', fontsize=14)
plt.tight_layout()
plt.show()

在这里插入图片描述

5.6. 交叉验证稳定性分析

print("="*60)
print("时间序列交叉验证稳定性分析")
print("="*60)

cv_df = pd.DataFrame([{
    '模型': r['model'],
    'CV AUC 均值': r['cv_auc_mean'],
    'CV AUC 标准差': r['cv_auc_std']
} for r in all_results if r['cv_auc_mean'] is not None])

print(cv_df.to_string(index=False))

# 可视化
plt.figure(figsize=(10, 6))
for r in all_results:
    if r['cv_auc_mean'] is not None:
        plt.bar(r['model'], r['cv_auc_mean'], yerr=r['cv_auc_std'], 
                capsize=5, color=['blue', 'red', 'green', 'orange'][all_results.index(r)])
plt.xlabel('模型')
plt.ylabel('CV AUC')
plt.title('时间序列交叉验证结果(误差线表示标准差)')
plt.ylim(0.4, 0.7)
plt.grid(True, alpha=0.3)
plt.show()

# 稳定性排序
stability_sorted = cv_df.sort_values('CV AUC 标准差')
print("\n模型稳定性排序(标准差越小越稳定):")
for _, row in stability_sorted.iterrows():
    print(f"  {row['模型']}: 标准差={row['CV AUC 标准差']:.4f}")

============================================================
时间序列交叉验证稳定性分析
============================================================
     模型  CV AUC 均值  CV AUC 标准差
   随机森林   0.519411    0.030001
XGBoost   0.484726    0.035542
    SVM   0.526231    0.028161
  朴素贝叶斯   0.522043    0.070046

在这里插入图片描述

模型稳定性排序(标准差越小越稳定):
  SVM: 标准差=0.0282
  随机森林: 标准差=0.0300
  XGBoost: 标准差=0.0355
  朴素贝叶斯: 标准差=0.0700

5.7. 多模型融合策略

5.7.1 投票融合
def voting_ensemble(predictions_list, weights=None):
    """加权投票融合"""
    predictions = np.array(predictions_list)
    if weights is None:
        weights = np.ones(len(predictions_list))
    weights = np.array(weights).reshape(-1, 1)
    weighted_sum = np.sum(predictions * weights, axis=0)
    return (weighted_sum > np.sum(weights) / 2).astype(int)

# 收集预测结果
predictions_list = [r['y_pred'] for r in all_results]

# 等权投票
ensemble_equal = voting_ensemble(predictions_list)
acc_equal = accuracy_score(y_test, ensemble_equal)

# 加权投票(按AUC加权)
auc_weights = [r['auc'] for r in all_results if r['auc'] is not None]
ensemble_weighted = voting_ensemble(predictions_list, auc_weights)
acc_weighted = accuracy_score(y_test, ensemble_weighted)

print("="*60)
print("投票融合结果")
print("="*60)
print(f"等权投票准确率: {acc_equal:.4f}")
print(f"加权投票准确率: {acc_weighted:.4f}")
print(f"最佳单一模型准确率: {max([r['accuracy'] for r in all_results]):.4f}")
============================================================
投票融合结果
============================================================
等权投票准确率: 0.5231
加权投票准确率: 0.5367
最佳单一模型准确率: 0.5326
5.7.2 Stacking融合
print("="*60)
print("Stacking融合训练")
print("="*60)

# 定义基学习器
base_learners = [
    ('rf', RandomForestClassifier(n_estimators=200, max_depth=15, random_state=42)),
    ('xgb', xgb.XGBClassifier(n_estimators=200, learning_rate=0.05, max_depth=6, 
                               random_state=42, eval_metric='logloss')),
    ('svm', SVC(kernel='rbf', C=1.0, gamma='scale', probability=True, random_state=42))
]

# Stacking分类器
stacking = StackingClassifier(
    estimators=base_learners,
    final_estimator=LogisticRegression(),
    cv=3,
    stack_method='predict_proba'
)

start_time = time.time()
stacking.fit(X_train, y_train)
stacking_time = time.time() - start_time

y_pred_stacking = stacking.predict(X_test)
if hasattr(stacking, 'predict_proba'):
    y_proba_stacking = stacking.predict_proba(X_test)[:, 1]
    stacking_auc = roc_auc_score(y_test, y_proba_stacking)
else:
    stacking_auc = None

stacking_acc = accuracy_score(y_test, y_pred_stacking)

print(f"Stacking准确率: {stacking_acc:.4f}")
print(f"Stacking AUC: {stacking_auc:.4f}")
print(f"Stacking训练时间: {stacking_time:.2f}秒")

============================================================
Stacking融合训练
============================================================
Stacking准确率: 0.5340
Stacking AUC: 0.5310
Stacking训练时间: 7.64秒
5.7.3 融合效果对比
fusion_results = {
    '随机森林': rf_results['accuracy'],
    'XGBoost': xgb_results['accuracy'],
    'SVM': svm_results['accuracy'],
    '朴素贝叶斯': nb_results['accuracy'],
    '等权投票': acc_equal,
    '加权投票': acc_weighted,
    'Stacking': stacking_acc
}

plt.figure(figsize=(12, 6))
models_fusion = list(fusion_results.keys())
scores_fusion = list(fusion_results.values())

colors = ['blue', 'red', 'green', 'orange', 'purple', 'brown', 'pink']
bars = plt.bar(models_fusion, scores_fusion, color=colors)
plt.xlabel('模型')
plt.ylabel('准确率')
plt.title('单一模型 vs 融合模型性能对比')
plt.xticks(rotation=45, ha='right')
plt.ylim(0.5, 0.65)

# 标注数值
for bar, score in zip(bars, scores_fusion):
    plt.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.003,
             f'{score:.4f}', ha='center', va='bottom')

plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()

print(f"融合模型相比最佳单一模型的提升: {(stacking_acc - max([r['accuracy'] for r in all_results]))*100:.2f}%")

在这里插入图片描述

融合模型相比最佳单一模型的提升: 0.14%

5.8. 各模型优劣深度分析

5.8.1 错误分析
def error_analysis_comparison(all_results, y_test):
    """对比各模型的错误预测模式"""
    
    print("="*70)
    print("各模型错误预测模式分析")
    print("="*70)
    
    error_analysis = []
    
    for r in all_results:
        y_pred = r['y_pred']
        errors = (y_test != y_pred)
        
        # 错误类型
        false_positives = np.sum((y_test == 0) & (y_pred == 1))
        false_negatives = np.sum((y_test == 1) & (y_pred == 0))
        
        error_analysis.append({
            '模型': r['model'],
            '总错误数': np.sum(errors),
            '错误率': np.mean(errors),
            '误报(FP)': false_positives,
            '漏报(FN)': false_negatives,
            'FP/FN比': false_positives / (false_negatives + 1e-10)
        })
    
    error_df = pd.DataFrame(error_analysis)
    print(error_df.to_string(index=False))
    
    # 可视化
    fig, axes = plt.subplots(1, 2, figsize=(14, 5))
    
    # 错误率对比
    axes[0].bar(error_df['模型'], error_df['错误率'], color=['blue', 'red', 'green', 'orange'])
    axes[0].set_ylabel('错误率')
    axes[0].set_title('各模型错误率对比')
    axes[0].grid(True, alpha=0.3)
    
    # FP/FN对比
    x = np.arange(len(error_df))
    width = 0.35
    axes[1].bar(x - width/2, error_df['误报(FP)'], width, label='误报 (FP)', color='red')
    axes[1].bar(x + width/2, error_df['漏报(FN)'], width, label='漏报 (FN)', color='blue')
    axes[1].set_xticks(x)
    axes[1].set_xticklabels(error_df['模型'])
    axes[1].set_ylabel('数量')
    axes[1].set_title('误报与漏报对比')
    axes[1].legend()
    axes[1].grid(True, alpha=0.3)
    
    plt.tight_layout()
    plt.show()
    
    return error_df

error_df = error_analysis_comparison(all_results, y_test)
======================================================================
各模型错误预测模式分析
======================================================================
     模型  总错误数      错误率  误报(FP)  漏报(FN)   FP/FN比
   随机森林   344 0.467391     185     159 1.163522
XGBoost   344 0.467391     185     159 1.163522
    SVM   357 0.485054     162     195 0.830769
  朴素贝叶斯   351 0.476902      79     272 0.290441

在这里插入图片描述

5.8.2 预测置信度分析
def confidence_analysis(results_list, y_test):
    """分析各模型的预测置信度"""
    
    plt.figure(figsize=(12, 6))
    
    for r in results_list:
        if r['y_proba'] is not None:
            # 正确预测的置信度
            correct_conf = r['y_proba'][y_test == r['y_pred']]
            # 错误预测的置信度
            wrong_conf = r['y_proba'][y_test != r['y_pred']]
            
            plt.hist(correct_conf, bins=30, alpha=0.5, label=f"{r['model']} - 正确", density=True)
            plt.hist(wrong_conf, bins=30, alpha=0.5, label=f"{r['model']} - 错误", density=True, linestyle='--')
    
    plt.xlabel('预测置信度')
    plt.ylabel('密度')
    plt.title('各模型预测置信度分布(正确 vs 错误)')
    plt.legend()
    plt.grid(True, alpha=0.3)
    plt.show()
    
    # 打印平均置信度
    print("\n平均预测置信度:")
    for r in results_list:
        if r['y_proba'] is not None:
            correct_conf = r['y_proba'][y_test == r['y_pred']].mean()
            wrong_conf = r['y_proba'][y_test != r['y_pred']].mean()
            print(f"  {r['model']}: 正确={correct_conf:.3f}, 错误={wrong_conf:.3f}, 差距={correct_conf-wrong_conf:.3f}")

confidence_analysis(all_results, y_test)

在这里插入图片描述

平均预测置信度:
  随机森林: 正确=0.496, 错误=0.508, 差距=-0.012
  XGBoost: 正确=0.496, 错误=0.515, 差距=-0.019
  SVM: 正确=0.499, 错误=0.505, 差距=-0.007
  朴素贝叶斯: 正确=0.436, 错误=0.449, 差距=-0.014

5.9. 模型优劣总结

5.9.1 各算法在量化预测中的优劣总结
  1. 随机森林 (Random Forest)

    • 优点:
      • 抗过拟合能力强(Bagging + 特征随机)
      • 提供特征重要性,可解释性好
      • 对异常值不敏感
      • 训练速度快于XGBoost
    • 缺点:
      • 预测速度较慢(需要遍历所有树)
      • 内存占用大
      • 高维稀疏数据表现一般
    • 适用场景: 中等规模数据、需要可解释性、特征工程完善
  2. XGBoost

    • 优点:
      • 精度通常最高
      • 内置正则化(gamma, lambda, alpha)
      • 自动处理缺失值
      • 二阶优化,收敛快
    • 缺点:
      • 训练时间较长
      • 参数较多,调参复杂
      • 对异常值敏感
    • 适用场景: 追求最高精度、中等以上数据量、有时间进行调参
  3. SVM (RBF核)

    • 优点:
      • 高维数据表现优秀
      • 核技巧处理非线性关系
      • 内存高效(只使用支持向量)
      • 理论基础扎实
    • 缺点:
      • 训练时间慢(O(n²) ~ O(n³))
      • 对特征缩放极度敏感(必须标准化)
      • 参数(C, gamma)需要仔细调参
      • 概率输出质量差
    • 适用场景: 中小规模数据、高维特征、不要求概率输出
  4. 朴素贝叶斯

    • 优点:
      • 训练极快(只计算统计量)
      • 预测极快(查表+乘法)
      • 小数据表现优秀
      • 天然支持多分类
      • 对无关特征鲁棒
    • 缺点:
      • 特征独立假设在金融数据中通常不成立
      • 概率估计可能不准确
      • 不能学习特征间的交互作用
    • 适用场景: 快速基线模型、实时预警系统、特征相对独立
5.9.2 量化交易模型选择建议(根据本次测试结果(同一数据集)):
  • 性能排名(AUC):

    1. 随机森林
    2. XGBoost
    3. 朴素贝叶斯
    4. SVM
  • 速度排名(预测时间):

    1. 朴素贝叶斯 (最快)
    2. 随机森林
    3. XGBoost
    4. SVM (最慢)
  • 稳定性排名(CV标准差):

    1. SVM
    2. 随机森林
    3. XGBoost
    4. 朴素贝叶斯
  • 融合策略效果:

    • 投票融合: 0.5231
    • Stacking: 0.5340
    • 最佳单一模型: 0.5326
  • 实战建议:

    1. 基线模型: 朴素贝叶斯(快速验证)
    2. 追求精度: XGBoost(需要调参)
    3. 平衡方案: 随机森林(易用+可解释)
    4. 终极方案: Stacking融合多模型
    5. 实时交易: 朴素贝叶斯 或 轻量级随机森林
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐