尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

机器学习预测股票涨跌:代码每次结果不同的原因与避坑指南

发布时间:2026/9/25 7:01:04

资讯中心
01
ARTICLE

机器学习预测股票涨跌:代码每次结果不同的原因与避坑指南

机器学习预测股票涨跌:代码每次结果不同的原因与避坑指南
简介2024年课程设计用机器学习股票预测算法源码项目面向金融数据分析、人工智能、通信工程、自动化等相关专业的高校学生、教师和科研工作者可作毕业设计、课程设计或项目初期演示的完整参考。压缩包共26个文件整体仅2.57MB主要包含6个Jupyter Notebook分析脚本、5个Python数据处理与预测脚本、3个CSV行情样本数据、Markdown与Txt说明文档以及Word版课设报告目录层次清晰。内容实战性较强完整覆盖数据获取、特征工程、FFT滤波、LSTM单票预测、sklearn机器学习单票回测等关键流程演示了从行情数据到模型评估的完整链路并包含可复现训练和预测的股票历史样本数据报告中对策略思路与结果亦作了总结便于在此基础上修改扩展。已有53人学习下载适合作为股票预测实战入门或课设毕设的借鉴模板。1. 机器学习预测股票涨跌:为什么同样的代码每次跑结果都不一样解压课设 zip 的那一刻,你可能已经踩进一个看不见的坑:按 README 跑完 train.py,第一次测试集 AUC 是 0.68,再跑一次变成 0.73,第三次又回到 0.71。这不是代码抄错了,而是机器学习股票预测项目最常见的不稳定来源——随机种子、数据划分顺序、模型初始化参数都在起作用。下面把这套「机器学习股票预测算法源码项目说明报告」类课程设计的落地流程拆开讲,从标签构造、数据划分到回测评估,把最容易让机器学习入门读者翻车的几个环节逐个说透。读完你至少能回答三个问题:预测目标怎么定、随机种子怎么固定、回测结果为什么不能全信。2. 选型:预测股票该用哪个模型,课设里为什么常见随机森林和 LSTM2.1 先想清楚预测目标:涨跌分类、价格回归还是选股排序动手写代码之前,第一件事不是选模型,而是定预测目标。同一个算法,预测「明天涨还是跌」和预测「明天收盘价是多少」,在损失函数、评估指标和代码难度上是两码事。目标没定清楚,后面所有选型理由都站不住。课设里最常见的是二分类,也就是预测 t1 日相对 t 日收盘价是涨还是跌。原因很实际:分类任务的评估好解释,准确率、F1、AUC 都能直接写进报告,答辩时也容易讲清楚。其次是回归,直接预测未来 N 日价格或收益率,但回归在股票数据上很容易被极端值带偏,而且评估时「误差小」并不能直接换算成「能赚钱」。第三种是排序,多只股票按上涨概率打分选 Top-K,这种更接近真实选股,但课设里数据量和逻辑复杂度都偏高,初学者容易把自己绕进去。我一般建议课设优先做二分类。二分类的标签构造只有一行判断:明天收盘价是否高于今天。后续的特征工程、模型评估、回测都能围绕这一个标签展开,报告主线也不会散。等二分类跑通、整套管线稳定了,再考虑把标签改成未来 5 日收益做回归对比,这才是比较稳妥的进阶路径。2.2 传统机器学习与深度学习模型的边界:样本量决定你该选哪一边选型问题上,课设圈子里两个主流方向是随机森林和 LSTM,对应传统机器学习模型与深度学习模型两条路线。两条路线的适用边界,一句话概括:样本量在几千条以内,树模型是首选;有几万条数据且明确要建模时间依赖,再考虑循环网络。随机森林在中小样本上的优势非常明显。股票日线数据通常只有几千条样本,随机森林在这种量级下很难过拟合,而且对特征尺度不敏感,不归一化也能跑出不错的效果。周志华《机器学习》里讲到的偏差-方差分解,恰好可以解释随机森林为什么稳定:Bagging 通过多棵树投票把方差压下来,单棵树再乱,集合的预测也相对平稳。对机器学习入门读者来说,随机森林的调参空间小、可解释性强,是课设兜底的最优选择。LSTM 则适合你明确要建模「序列依赖」的场景。股价数据在时间维度上确实存在相关结构,连续几天的走势会互相影响,LSTM 的循环结构天然吃这种输入。但它的代价也很直接:需要更大的数据量、更仔细的归一化、更小心的训练策略,否则训练过程极不稳定。「模型预测股票涨跌 每次结果不一样」这句话,在 LSTM 上出现的概率远高于随机森林,因为深度模型初始化、梯度下降顺序、甚至 GPU 的并行计算都会引入随机性。课设如果要用 LSTM,务必做好第 4 章的种子固定工作,否则答辩时你根本没法解释为什么两次运行报告数字不同。还有一个方向需要泼冷水:强化学习算法。课设里经常有人想用强化学习做自动交易,但强化学习需要环境建模、奖励设计、稳定训练策略三件事同时到位,对本科生课设来说工程量太大,而且训练结果随机性比监督学习更高。除非题目明确要求,否则不建议在课设里碰它。选型结论可以这样定:样本量在几千条以内,先跑随机森林,它能给你一个可靠的下界;如果数据量有几万条日线、或者你确实想展示深度学习的建模能力,再上 LSTM,但必须配套完整的随机种子方案。常见的错误是直接拿 LSTM 硬跑小样本,训练集损失降不下去,还反过来怀疑数据有问题。2.3 特征构造:从 K 线数据到模型输入的一步模型吃的是特征,不是原始股价。直接丢给模型「开盘价、收盘价、最高价、最低价、成交量」五列,模型也能学,但学不到趋势、动量、波动这些交易里真正有意义的结构。特征构造是整条管线里最值得花时间的一步,也是报告里最容易被答辩老师追问的部分。常见做法是先复现技术指标,再用指标做特征。均线、RSI、MACD 是三个基础方向:均线反映趋势,RSI 反映超买超卖,波动率反映风险。下面这段代码演示了从日线数据构造特征和标签的完整流程,也是这类课设源码项目里最核心的预处理段落:import pandas as pd import numpy as np def build_features(df: pd.DataFrame) - pd.DataFrame: 输入 df 包含 date, open, high, low, close, volume 六列 data df.sort_values(date).copy() # 涨跌幅:模型对价格的绝对数值不敏感,对变化率更敏感 data[return_1] data[close].pct_change(1) # 5 日均线与 10 日均线,以及它们的偏离度 data[ma5] data[close].rolling(5).mean() data[ma10] data[close].rolling(10).mean() data[ma_ratio] data[ma5] / data[ma10] - 1.0 # RSI(14):相对强弱指标,衡量近期上涨和下跌的力量对比 delta data[close].diff() gain delta.clip(lower0).rolling(14).mean() loss (-delta.clip(upper0)).rolling(14).mean() rs gain / (loss 1e-9) data[rsi14] 100 - 100 / (1 rs) # 波动率:过去 20 日收益率的标准差 data[volatility] data[return_1].rolling(20).std() # 标签:次日收盘价是否高于当日,1 表示上涨 data[label] (data[close].shift(-1) data[close]).astype(int) # 去掉因滚动窗口产生的 NaN 行 data data.replace([np.inf, -np.inf], np.nan).dropna() return data.reset_index(dropTrue)这段代码有三点值得说明。第一,所有特征都只用了当日及之前的数据,rolling 窗口不会向前看,这是避免特征泄露的基础。第二,label 用 shift(-1) 构造,意思是「明天收盘相对于今天收盘是否上涨」,这个 shift 的方向一旦写反,整个模型学的就是未来数据,测试集指标会虚高到失真。第三,RSI 分母加了一个 1e-9 的平滑项,防止连续下跌导致 loss 为 0 时出现除零错误。特征不是越多越好,课设里 10 个以内的特征足够讲清楚逻辑,堆到几十个特征反而会让报告难以解释每个特征的含义。特征数量控制住之后,还有一个容易忽略的点:不同股票的股价区间差异极大,贵州茅台和几块钱的股票,收盘价量纲完全不同。如果你把原始价格喂给线性模型或者 LSTM,大价差股票会主导损失函数。第 3 章会讲归一化,这一步先把原始价格都转成涨跌幅和技术指标,本质上也是在消除量纲影响。提示:特征构造完成后,务必打印 data.head() 和 data.isna().sum() 检查行列对齐。常见的翻车点是 shift 之后标签错位,训练时没有报错,但评估结果完全不可信。3. 搭建训练管线:数据集划分、滚动窗口与标签构造3.1 标签构造的两条铁律:对齐和前瞻标签是监督学习的「标准答案」,股票预测里标准答案稍微偏移一天,结论就完全失真,所以标签构造要单独当成一个步骤对待,而不是顺手在特征函数里写一行。第一条铁律是标签必须与被预测时刻对齐。预测 t1 日的涨跌,标签就要用 t1 日的数据生成,而特征只能用 t 日及之前的数据。上一章代码里用 shift(-1) 把「明天的收盘价」搬到今天这行,正是为了对齐。第二条铁律是时间序列的标签不能跨样本混用。同一个交易日的涨跌只应该出现在一条训练样本里,如果特征窗口重叠,比如 5 日均线在相邻两行都包含同一天的收盘价,严格来说样本之间存在依赖,但课设里这种依赖通常被忽略,需要在报告里说明。另一个常见问题是「预测今天」和「预测明天」的混淆。很多入门者会在收盘后用当天数据预测当天涨跌,这等于拿收盘价预测收盘价,准确率虚高。课设里的正解是:数据用 t 日收盘后的信息,预测 t1 日的涨跌。听起来只差一天,报告里的数字能差 5 个百分点以上。还需要处理两类特殊交易日:停牌日和涨跌停日。停牌当天的行情数据为缺失或 0,直接保留会让模型学到「价格为 0」这种无意义模式,常见做法是直接删除停牌行。涨跌停日更隐蔽:如果当天涨停,次日大概率高开或惯性冲高,标签会系统性偏向某个方向,但这种规律转瞬即逝,模型很难真正学到。课设里不必处理得过于复杂,但要在报告的局限说明里写一句,答辩老师会认为你想到了这一层。3.2 时间序列划分:为什么不能直接调用 train_test_split数据划分是股票预测课设里最容易被一眼看穿的问题。如果直接调用 train_test_split(random_state42),它会随机打散样本,把 2022 年 1 月和 2023 年 5 月的数据混在同一个训练集里。这在其他机器学习任务里没问题,在时间序列上就是作弊:模型见过未来,测试集指标自然会虚高。标准做法是按时间顺序切分,训练集用前面的 70%,验证集用接下来的 15%,测试集用最后的 15%。更贴近真实交易的是滚动窗口:每训练一段时间,就往前推进一个步长重新训练,模拟「每天收盘后更新模型」的部署节奏。下面这段代码给出一个可复用的时间序列划分函数:def temporal_split(df: pd.DataFrame, train_ratio: float 0.7, val_ratio: float 0.15): 按时间顺序切分数据集,不打乱样本顺序 n len(df) train_end int(n * train_ratio) val_end int(n * (train_ratio val_ratio)) train df.iloc[:train_end].copy() val df.iloc[train_end:val_end].copy() test df.iloc[val_end:].copy() # 打印切分后的日期区间,防止数据顺序没按日期排好 print(train:, train[date].iloc[0], -, train[date].iloc[-1]) print(val:, val[date].iloc[0], -, val[date].iloc[-1]) print(test:, test[date].iloc[0], -, test[date].iloc[-1]) return train, val, test注意:切分前先确认 df 已经按日期升序排序。真实行情数据经常出现停牌、复牌,如果不做排序,iloc 切出来的区间日期是错乱的,训练集里可能混着未来的数据。参数说明:train_ratio 和 val_ratio 分别控制训练集和验证集占比,这是时间序列切分的两个核心参数。课设数据量在 2000 到 5000 条时,70/15/15 是稳妥比例;数据量超过一万条时,可以调整到 80/10/10,因为更长的训练序列对时间序列模型收益更明显。滚动窗口的做法则是在这个基础上,每训练一个窗口后丢弃最早的数据段,再纳入最新数据段。实现上就是一个 for 循环滑动 iloc 的起点和终点,比如窗口长度 1200、步长 200,测试区间的每个子段都用它之前的数据训练。这种切分方式更接近量化交易里的 walk-forward 检验,如果课设报告里能写出滚动窗口与固定切分两种方式的结果对比,答辩含金量会明显提升。3.3 归一化:训练集 fit,验证集和测试集只能 transform归一化是深度学习模型的必需品。传统树模型对尺度不敏感,但金融数据里不同股票的股价区间差异极大,原始价格直接喂给神经网络,损失函数会被高价股主导。常见做法是 StandardScaler,把均值归到 0、标准差归到 1。这里有一个很容易踩的细节:scaler 必须在训练集上 fit,验证集和测试集只调用 transform。原因很简单,如果让测试集的统计量参与了均值和标准差的估计,测试集信息就泄露进了预处理,评估结果不再干净。下面这段代码演示标准的三集合处理流程:from sklearn.preprocessing import StandardScaler feature_cols [return_1, ma_ratio, rsi14, volatility] label_col label scaler StandardScaler() train_x scaler.fit_transform(train[feature_cols]) # 只在训练集上 fit val_x scaler.transform(val[feature_cols]) # 验证集只 transform test_x scaler.transform(test[feature_cols]) # 测试集只 transform train_y train[label_col].values val_y val[label_col].values test_y test[label_col].values这段代码的逻辑是:特征列和标签列先分开,特征进入 scaler 处理,标签保持原始 0/1 值不动。fit_transform 在训练集上计算均值标准差并完成转换,val 和 test 的 transform 复用同一组统计量,保证三个集合的数据处于同一尺度。最后两行把标签转成 numpy 数组,方便后续喂给 sklearn 或 PyTorch。参数说明:feature_cols 里选的是第 2 章构造的特征。如果你自己加了成交量、市盈率等特征,记得加进这个列表。标签不用归一化,尤其是二分类任务,标签是 0/1 整数,归一化反而会让损失函数失去概率含义。如果做回归预测价格,才需要对标签做归一化,并在评估前反归一化,这个细节会在第 4 章展开。这段流程也是机器学习应用流程里最容易出事的环节:先切分再归一化,还是先归一化再切分,顺序错了结果完全不一样。规矩只有一条——任何用到全局统计量的操作,都必须先切分、再 fit 训练集,最后 transform 另外两个集合。把这句话写进报告的预处理说明里,能挡住一半以上的追问。4. 核心代码与参数:让模型稳定复现的三个关键设置4.1 随机种子:每次结果不一样的根源「模型预测股票涨跌 每次结果不一样」是股票预测课设被问得最多的问题,根源几乎都是随机种子没有固定完整。Python 生态里至少存在四个独立的随机源:numpy 的随机数、Python 内置 random 模块、sklearn 的模型随机性、PyTorch 的初始化与数据加载。只固定其中一个,其他三个仍然在乱跳。下面这段代码是课设里建议直接复制的种子固定函数,覆盖了 sklearn 模型训练和 PyTorch 训练两条路线。sklearn 和 torch 是这次要用到的两个 python 机器学习常用包,它们的随机性管理机制完全不同,所以必须分开处理:import os import random import numpy as np import torch def seed_everything(seed: int 42): 统一固定 numpy / random / torch 的随机种子 random.seed(seed) # Python 内置随机 np.random.seed(seed) # numpy 随机 os.environ[PYTHONHASHSEED] str(seed) # 哈希种子,影响集合遍历顺序 torch.manual_seed(seed) # PyTorch CPU torch.cuda.manual_seed_all(seed) # PyTorch GPU # 关闭 cuDNN 的自动调优,保证卷积/循环网络前向结果确定 torch.backends.cudnn.deterministic True torch.backends.cudnn.benchmark False调用方式很简单,在导入所有库之后、读取数据之前执行 seed_everything(42)。参数 seed 是主种子,课设里换成任何固定整数都行。需要说明的是,cudnn.deterministic 会牺牲少量训练速度换取完全可复现,对日线级别的数据集来说,速度损失完全可以忽略。如果你用了 PyTorch 的 DataLoader,还要传入generatortorch.Generator().manual_seed(seed),否则多线程数据加载顺序仍然会引入随机性。固定种子这件事,逻辑上是在固定两样东西:样本顺序和参数初始状态。样本顺序影响梯度下降的轨迹,参数初始状态影响模型收敛到哪个局部最优。这两个因素在股票这种高噪声数据上,对最终指标的影响可能超过模型结构本身。所以种子函数不是可选项,而是整条训练管线稳定性的地基。提示:固定种子之后,第一次和第二次运行的数字可能仍然有微小差异,这来自操作系统浮点运算的非确定性,差异一般在小数点后三位以外,不影响报告结论。如果差异在第二位小数就跳变,说明种子没有真正固定住。4.2 模型参数:随机森林和 LSTM 的课设默认值种子固定之后,参数选择决定模型上限。随机森林和 LSTM 的调参逻辑完全不同,下面这张表给出两组课设里验证过比较稳的基准参数:模型参数课设基准值调参方向RandomForestn_estimators500过大收益递减,过小方差高RandomForestmax_depth6-8限制深度防过拟合,股票特征少不需要太深RandomForestmin_samples_leaf20控制叶节点最小样本数,平滑预测LSTMhidden_size64隐层维度,数据量小不宜超过 128LSTMnum_layers2超过 2 层在千级样本上易过拟合LSTMdropout0.3抑制过拟合,课设常见 0.2-0.5LSTMlearning_rate0.001太大训练发散,太小收敛过慢LSTMbatch_size32日线数据建议 16-64随机森林的四个参数里,max_depth 和 min_samples_leaf 是最值得调的。股票特征是典型的高噪声低信噪比,把树压浅一点、叶节点要求多一点,能显著减少对个别异常 K 线的过拟合。n_estimators 从 100 涨到 500 方差下降明显,再往上基本是浪费算力。LSTM 的参数要记住一个原则:小样本配小网络。hidden_size 超过 128、num_layers 超过 2,百万级参数在几千条日线上几乎必然过拟合,训练集损失漂亮,测试集直接崩。learning_rate 保持 0.001 的 Adam 默认值,如果训练损失震荡不收敛,优先把 batch_size 调小,而不是把学习率降到千分位以下。调参顺序也有讲究。我一般先固定种子,用随机森林跑一组 baseline,把整套特征工程和评估脚本调通,然后再换 LSTM。LSTM 只在随机森林结果的基础上尝试提升,而不是开头就冲深度学习。这样哪怕 LSTM 最终没跑赢,报告里也有一组可信的对照数据。4.3 评估指标:准确率不够用,F1 与回测收益怎么算股票涨跌数据的标签分布天然不平衡,牛市里上涨样本可能占 60% 以上。准确率在这种分布下没有意义——就算模型永远预测「涨」,也能拿到 60% 的准确率。课设报告里至少应该同时报告准确率、F1 和 AUC 三个指标,F1 对少数类敏感,AUC 反映排序能力,两者比单一准确率诚实得多。回测是另一个维度:模型预测涨跌后,按信号模拟持仓,计算累计收益和最大回撤。下面给出一个最简单的回测函数,适合课设演示,但不适合直接当实盘结论:def backtest(df: pd.DataFrame, pred: np.ndarray, fee: float 0.001): 按预测信号每天全仓买入/卖出,计算累计净值与最大回撤 df 需包含 close 列,pred 为 0/1 预测数组,长度与 df 对齐 df df.copy() df[signal] pred # 1 表示次日持有多头,0 表示空仓 df[ret] df[close].pct_change().fillna(0) df[strategy_ret] df[signal].shift(1) * df[ret] - fee df[equity] (1 df[strategy_ret]).cumprod() total_return df[equity].iloc[-1] - 1 max_drawdown (df[equity] / df[equity].cummax() - 1).min() return df, total_return, max_drawdown这段代码的思路是:信号在第 t 日产生,实际持仓从 t1 日开始,所以 strategy_ret 用 signal.shift(1) 做一天延迟,模拟真实交易中不可能当天收盘价买卖的问题。fee 参数是单边手续费加滑点,0.001 表示万十,这个值已经比较乐观,真实佣金加滑点通常不低于 0.002。参数说明:signal 是 0/1 信号,0 表示空仓,1 表示持有。这个策略不涉及做空,是最基础的「只做多」演示。max_drawdown 用净值除以历史峰值再减一计算,是回撤幅度,负值越大说明风险越高。课设报告里应该同时给出 total_return 和 max_drawdown,只报收益不报回撤,答辩时容易被追问风险控制。还有一个常见困惑:AUC 很高但回测收益一般,或者反过来。这不是 bug,AUC 衡量的是排序质量,回测衡量的是策略收益,两者中间隔着信号阈值、仓位管理和交易成本。课设里遇到这种情况,优先看 AUC 的计算方向是否正确——用 predict_proba 的正类概率计算,而不是用 predict 的硬标签,否则 AUC 会被人为压低。5. 避坑:课设里最容易翻车的 5 个问题和排查顺序5.1 现象:训练集 99%,测试集 52%这是最常见的翻车现场,训练集指标漂亮得惊人,测试集立刻现原形。原因几乎都是特征泄露,具体有两种。第一种是标签构造时 shift 方向写反,导致训练样本里包含了当天的未来价格。第二种是特征里用了未来信息,比如用全量数据的均值做了归一化,或者用 rolling 窗口时没有注意窗口向右看。解决方法是回到第 2 章的特征函数,逐行检查滚动窗口的参数:rolling(5) 用的是当前行及之前 4 行,属于合法;如果用 shift(-1) 把未来数据搬进特征,那必须删掉。用 matplotlib 画出特征曲线和价格曲线,目测特征是否出现「提前于价格变动」的形状,是发现泄露最快的方式。5.2 现象:LSTM 预测结果是一条直线预测结果画出来是一条水平直线,这在课设答疑里出现频率极高。直接原因是把预测任务理解成了回归:用 LSTM 拟合下一日收盘价,而收盘价序列高度平滑,模型发现输出历史均值能拿到最小 MSE,于是学成了一个常数。解决方法是把目标从价格回归改成涨跌分类,分类的交叉熵损失不会把模型推向均值。如果确实要做回归,必须对标签做差分处理,预测「明日涨跌幅」而不是「明日价格」,同时把归一化的范围压到零均值附近。还有一个次要原因是学习率过大导致梯度爆炸,表现为训练损失在初期就跳到 NaN,这时候把 learning_rate 从 0.001 降到 0.0001,并且检查数据里有没有极端的异常价格。5.3 现象:同样的代码每次结果都不一样代码没改,连续跑三次,指标每次差 1-2 个百分点,这是随机种子只固定了一半。最常见的遗漏是只设置了 np.random.seed 和 torch.manual_seed,但 DataLoader 的数据打乱顺序仍然随机;或者固定了训练种子,却在评估时没有固定模型预测阶段的种子,导致 dropout 在推理时仍在生效。解决方法是完整执行第 4 章的 seed_everything,并且在模型预测前调用 model.eval() 关掉 dropout 和 batch_norm 的训练行为。如果做到这些之后两次结果仍然在第二位小数跳动,通常是 GPU 浮点非确定性,可以接受,但报告里要注明「在 CPU 环境下可完全复现」。5.4 现象:回测收益很高,实盘一买就亏回测曲线漂亮得像印钞机,实盘直接打脸。这不是模型忽然失效,而是回测里埋伏了未来函数或交易成本漏洞。最常见的未来函数是信号当天收盘价成交:真实交易中,收盘价确定的那一刻已经无法用收盘价成交,必须用次日开盘价,代码里就要让持仓从 t1 开始,也就是第 4 章回测函数里 shift(1) 的作用。手续费和滑点只给一个 0.001 的乐观费率,也会让策略在回测里被严重高估。解决方法是把 fee 调到 0.002-0.003,用次日开盘价代替当日收盘价再跑一遍,收益大概率大幅缩水,这才是模型真实水平的近似值。回测收益缩水不一定是坏事,它帮你提前挤掉了水分。5.5 现象:报告参数和 zip 源码对不上答辩老师翻源码,发现报告里写 n_estimators300,源码里却是 100。这不是诚信问题,是版本管理缺失。课设项目通常会在调试中反复改参数,最后交的 zip 往往是最后一次运行的结果,但报告却引用了几天前的数字。解决方法是跑最终版之前,在脚本开头打印关键参数到命令行,跑完直接把输出截图放进报告;zip 打包前用相同种子和参数重新跑一遍验证,确认报告数字能够复现。这是兜底手段,也是所有避坑条目里唯一一个纯粹靠流程就能解决的问题,养成这个习惯能省掉答辩时最尴尬的追问。6. 让课设报告经得起追问:滚动回测与参数稳健性检查前面五章解决的是「跑起来」,最后这一步解决的是「答辩时站得住」。老师问得最多的一个问题就是:你的参数在别的股票、别的时段上也稳定吗?要回答这个问题,靠的是滚动回测和参数稳健性检查。滚动回测的常见做法是把测试区间拆成多个子区间,逐段用历史数据训练、更新预测,模拟真实部署的节奏。参数稳健性检查更简单:固定所有超参数,只更换测试区间,记录每个区间的 F1 和 AUC。如果某段大盘震荡期指标显著下滑,说明模型对市场状态敏感,报告里要如实写明这个边界。results [] for start in range(0, 800, 200): window df.iloc[start:start 1200] train, val, test temporal_split(window) # 上一章的切分函数 model RandomForestClassifier(n_estimators500, max_depth6, random_state1) model.fit(train[feature_cols], train[label_col]) auc roc_auc_score(test[label_col], model.predict_proba(test[feature_cols])[:, 1]) results.append((str(test[date].iloc[0]), str(test[date].iloc[-1]), round(auc, 4)))这段代码展示了一个最小实现:步长 200、窗口 1200,依次滚动训练随机森林,并计算每个窗口的 AUC。range 的三个数值分别代表起始位置、步长和总样本数,数据量不同就把这三个值按比例放缩。把 results 打印出来形成一张小表放进报告,比任何文字说明都有说服力。我自己做这类课设时,最后一步永远是同一件事:把随机种子从 42 换到 2024,重跑一遍,看核心指标的变化幅度。如果 AUC 波动超过 0.03,我就知道前面几章里还有没发现的泄露或参数敏感点。这个习惯帮我抓出过好几次标签移位错误,也让我在答辩时对每一个数字都心里有底。希望这个检查办法也能帮到你,愿你的报告里每一个数字都能经得起第二次运行的考验。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。