
用 Python 揭秘均值回归策略:你的收益从何而来?
2026年重磅升级已全面落地!欢迎加入专注财经数据与量化投研的【数据科学实战】知识星球!您将获取持续更新的《财经数据宝典》与《量化投研宝典》,双典协同提供系统化指引;星球内含 500 篇以上独有高质量文章,深度覆盖策略开发、因子分析、风险管理等核心领域,内容基本每日更新;同步推出的「量化因子专题教程」系列(含完整可运行代码与实战案例),系统详解因子构建、回测与优化全流程,并实现日更迭代。我们持续扩充独家内容资源,全方位赋能您的投研效率与专业成长。无论您是量化新手还是资深研究者,这里都是助您少走弯路、事半功倍的理想伙伴,携手共探数据驱动的投资未来!
在做机器学习项目时,很多 Python 初学者都会遇到同一个难题:面对一份数据集和几十个候选算法,到底该从哪个模型入手?是花好几个小时把每个模型都手动调一遍,还是先快速找一个靠谱的基线?
本文要介绍的 LazyPredict,就是专门解决这个「选择困难」的工具。它属于 AutoML(自动化机器学习)家族,最大的特点是:只需几行代码,就能一次性训练并对比几十个 scikit-learn 模型,帮你快速锁定值得深入优化的算法。
下面我们通过信用风险、欺诈检测、客户流失、股票预测等多个金融场景,带你完整体验 LazyPredict 的用法,并总结出一条比「选模型」更重要的经验。
LazyPredict 是一个轻量级的模型基准测试库,它的核心价值可以概括为几点:
安装非常简单:
pip install lazypredict需要提醒的是:LazyPredict 用的是模型的默认参数,它给出的是一个「快照式」的初步排名,而不是最终结论。真正的调优还要靠后续的特征工程、超参数搜索和交叉验证。
第一个例子使用德国信用数据集,目标是把贷款申请人分成「好」或「坏」两类信用风险。
核心步骤是:做一点特征工程 → 编码类别变量 → 划分训练/测试集 → 交给 LazyPredict 一键跑分。
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from lazypredict.Supervised import LazyClassifier
# 读取数据
df = pd.read_excel("german_credit_data.xlsx")
# 把目标变量映射为数字:good -> 1,bad -> 0
df["Risk"] = df["Risk"].replace({"good": 1, "bad": 0})
# 简单的特征工程
df["Credit_per_month"] = df["Credit amount"] / df["Duration"] # 每月信贷额
df["High_credit"] = (df["Credit amount"] > 5000).astype(int) # 高额信贷标记
# 填补缺失值
df["Saving accounts"] = df["Saving accounts"].fillna("unknown")
df["Checking account"] = df["Checking account"].fillna("unknown")
# 对类别特征做标签编码
X = df.drop("Risk", axis=1)
for col in X.select_dtypes(include="object").columns:
X[col] = LabelEncoder().fit_transform(X[col])
y = df["Risk"]
# 划分训练集与测试集
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.1, random_state=42, stratify=y
)
# 一键基准测试:verbose=0 静默,ignore_warnings 忽略告警
clf = LazyClassifier(verbose=0, ignore_warnings=True)
models, predictions = clf.fit(X_train, X_test, y_train, y_test)
# 打印所有模型的对比结果
print(models)跑完之后,models 会返回一张表格,包含每个模型的准确率(Accuracy)、平衡准确率(Balanced Accuracy)、ROC AUC、F1 分数、精确率、召回率以及耗时。在这个数据集上,多数模型的准确率集中在 0.73 到 0.77 之间,方便你一眼看出哪些算法更有潜力。
延伸提示:stratify=y 这个参数很重要,它能保证训练集和测试集中正负样本的比例一致,尤其在类别不均衡时能让评估更可靠。
第二个例子是判断一笔银行交易是否可疑,数据集有 3 万多条记录,目标列是isSuspicious。
这里有个常见的实用技巧:把日期拆解成年、月、日、星期等特征,往往能显著提升模型表现。
# 把日期转成 datetime 类型
df["date"] = pd.to_datetime(df["date"])
# 从日期中提取可用的时间特征
df["Year"] = df["date"].dt.year
df["Month"] = df["date"].dt.month
df["Day"] = df["date"].dt.day
df["Weekday"] = df["date"].dt.weekday
# 拆完后删掉原始日期列
df.drop("date", axis=1, inplace=True)
# 对交易描述做编码
df["description"] = LabelEncoder().fit_transform(df["description"])
# 特征与目标
X = df.drop("isSuspicious", axis=1)
y = df["isSuspicious"]
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
clf = LazyClassifier(verbose=0, ignore_warnings=True)
models, predictions = clf.fit(X_train, X_test, y_train, y_test)
print(models)在这个任务里效果非常亮眼:LGBMClassifier、XGBClassifier、CatBoostClassifier 等树模型的准确率都超过了 0.99。这说明对于结构化的表格数据,梯度提升类模型通常是强有力的选择。
第三个例子来自电信客户流失数据集,目标是预测客户会不会离网。数据里既有数值特征也有大量类别特征,需要先做统一处理。
# 删除无意义的 ID 列
df.drop("customerID", axis=1, inplace=True)
# TotalCharges 原本是字符串,转成数值,无法转换的置为 NaN
df["TotalCharges"] = pd.to_numeric(df["TotalCharges"], errors="coerce")
# 用中位数填补缺失值
df["TotalCharges"].fillna(df["TotalCharges"].median(), inplace=True)
# 编码目标变量
y = LabelEncoder().fit_transform(df["Churn"])
# 编码所有类别特征
X = df.drop("Churn", axis=1)
for col in X.select_dtypes(include="object").columns:
X[col] = LabelEncoder().fit_transform(X[col])
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
clf = LazyClassifier(verbose=0, ignore_warnings=True)
models, predictions = clf.fit(X_train, X_test, y_train, y_test)
print(models)易错点提醒:TotalCharges 这一列看起来是数字,但实际上是 object(字符串)类型,里面还夹杂着空格。这时用pd.to_numeric(..., errors="coerce") 强制转换、再填补缺失值,是非常经典的清洗套路。
第四个例子用苹果(AAPL)的历史行情,预测「下一天股价是否上涨」。这里的重点从「选模型」转向了「造特征」。
# 按日期排序
df["date"] = pd.to_datetime(df["date"])
df.sort_values("date", inplace=True)
# ---------- 特征工程 ----------
df["return"] = df["close"].pct_change() # 日收益率
df["log_return"] = np.log(df["close"] / df["close"].shift(1)) # 对数收益率
# 滞后特征:把过去几天的收益率作为特征
df["return_lag1"] = df["return"].shift(1)
df["return_lag2"] = df["return"].shift(2)
# 移动平均线
df["ma5"] = df["close"].rolling(5).mean()
df["ma10"] = df["close"].rolling(10).mean()
df["ma20"] = df["close"].rolling(20).mean()
df["ma_ratio"] = df["ma5"] / df["ma20"] # 均线比值
# 波动率(风险信号)
df["volatility_5"] = df["return"].rolling(5).std()
df["volatility_10"] = df["return"].rolling(10).std()
# 目标:下一天收盘价比今天高出 0.2% 以上则记为 1
df["target"] = (df["close"].shift(-1) > df["close"] * 1.002).astype(int)
df.dropna(inplace=True)在这个案例里,即便试遍所有模型,准确率也大多徘徊在 0.5 附近——这恰恰印证了那句金融机器学习的名言:特征工程对结果的影响,往往比选哪个算法更大。把原始的开高低收价格转化成收益率、波动率、滞后信号,才是提升预测力的关键。
最后一个案例更进一步:不只是预测涨跌,而是把预测转化为真实的买卖决策,看看能不能跑赢「买入持有」(Buy-and-Hold)。文中对比了三种方案。
场景一:基础特征 + 逻辑回归
from sklearn.linear_model import LogisticRegression
# 训练逻辑回归模型
model = LogisticRegression(random_state=42, max_iter=1000)
model.fit(X_train, y_train)
df_test = df.iloc[-len(X_test):].copy()
df_test["signal"] = model.predict(X_test)
# 把预测信号转成持仓方向:1 做多,0 做空(-1)
df_test["position"] = df_test["signal"].replace({1: 1, 0: -1})
# 计算策略收益:用「昨天的持仓」乘以「今天的收益率」
df_test["strategy_return"] = df_test["position"].shift(1) * df_test["return"]
# 累计权益曲线(1 元本金的增长情况)
df_test["equity_curve"] = (1 + df_test["strategy_return"]).cumprod()场景二:简单动量策略
# 用规则代替模型:短期均线在长期均线之上就做多
df_test["signal"] = (df_test["momentum"] > 1).astype(int)
df_test["position"] = df_test["signal"].replace(0, -1)
df_test["strategy_return"] = df_test["position"].shift(1) * df_test["return"]
df_test["equity_curve"] = (1 + df_test["strategy_return"]).cumprod()
# 计算夏普比率与最大回撤,衡量风险
sharpe = np.mean(df_test["strategy_return"]) / np.std(df_test["strategy_return"])
df_test["peak"] = df_test["equity_curve"].cummax()
df_test["drawdown"] = df_test["equity_curve"] / df_test["peak"] - 1
print("夏普比率:", sharpe)
print("最大回撤:", df_test["drawdown"].min())场景三:扩展特征 + SVC(支持向量机)
from sklearn.svm import SVC
# 在更丰富的特征集上训练 RBF 核的 SVM
model = SVC(random_state=42, kernel="rbf")
model.fit(X_train, y_train)
df_test = df.iloc[-len(X_test):].copy()
df_test["signal"] = model.predict(X_test)三种方案对比下来结论很清晰:
虽然 SVC 并没有把买入持有远远甩开,但它证明了一件事:只要肯在特征工程上多下功夫,再搭配合适的分类器,就能得到相当靠谱的交易信号。
LazyPredict 只是起点。一旦锁定了几个有潜力的模型,就可以用GridSearchCV 做超参数调优,再用 K 折交叉验证得到更稳健的评估:
from sklearn.model_selection import GridSearchCV, cross_val_score
from sklearn.ensemble import RandomForestClassifier
# 定义参数搜索空间
params = {
"n_estimators": [100, 300, 500, 700],
"max_depth": [5, 10, 15, 20, 25],
"min_samples_split": [2, 5, 10, 20, 40, 80],
}
grid = GridSearchCV(
RandomForestClassifier(random_state=42),
params, cv=5, scoring="accuracy"
)
grid.fit(X_train, y_train)
print("最优参数:", grid.best_params_)
print("最优交叉验证得分:", grid.best_score_)
# 用交叉验证评估最终模型,比单次划分更可靠
best_rf = grid.best_estimator_
scores = cross_val_score(best_rf, X, y, cv=5)
print("交叉验证平均分:", scores.mean())此外,处理类别不平衡(如 SMOTE 过采样)、用 StandardScaler 做标准化、尝试 XGBoost / LightGBM / CatBoost 等集成方法,都是在表格数据上进一步提升效果的常用手段。
本文用五个金融场景,完整演示了如何用 LazyPredict 快速给几十个机器学习模型「打分排名」。可以提炼出几个要点:
对于正在学习 Python 的你,LazyPredict 是一个非常适合上手的工具:它让你把精力从「反复调模型」转移到「打磨数据和特征」上——而这,恰恰是数据科学里更有价值的功夫。
2026年全面升级已落地!【数据科学实战】知识星球核心权益如下:
星球已沉淀丰富内容生态——涵盖量化文章专题教程库、因子日更系列、高频数据集、PyBroker实战课程、专家深度分享与实时答疑服务。无论您是初探量化的学习者,还是深耕领域的从业者,这里都是助您少走弯路、高效成长的理想平台。诚邀加入,共探数据驱动的投资未来!
好文推荐
1. 用 Python 打造股票预测系统:Transformer 模型教程(一)
2. 用 Python 打造股票预测系统:Transformer 模型教程(二)
3. 用 Python 打造股票预测系统:Transformer 模型教程(三)
4. 用 Python 打造股票预测系统:Transformer 模型教程(完结)
6. YOLO 也能预测股市涨跌?计算机视觉在股票市场预测中的应用