☰
Python股票波动分类实战:决策树、朴素贝叶斯与神经网络代码对比
2026/10/26 8:23:44 网站建设 项目流程

简介:这份资源面向希望系统掌握经典分类算法并动手实践的Python学习者,围绕决策树、朴素贝叶斯与人工神经网络三条主线,提供可直接运行的代码与配套数据,帮助读者从原理理解过渡到真实场景建模。压缩包共3个文件,包含1个ipynb交互式笔记本、1个py脚本和1个csv数据集,整体约119KB,其中笔记本适合在Jupyter Notebook中逐步调试与观察输出,脚本便于快速复用,csv则承载股票价格波动分析的案例数据。资源以股票价格波动为实战场景,串联起决策树、贝叶斯与神经网络三种算法的建模流程,读者可借此对比不同分类思路在金融数据上的表现,理解特征处理、模型训练与结果评估的完整链路。目前已有5904人学习下载,适合具备Python基础、希望用一份轻量资料打通多种分类算法实操的读者参考。

1. 从一份股票数据到三种分类器:这套 Python 代码包能跑出什么

手里有一份a601318.csv,字段是股票价格波动相关的数据,目标是把「涨/跌/震荡」这类离散标签分出来。很多人第一反应是直接上深度学习,但真到落地阶段,决策树、朴素贝叶斯、人工神经网络这三种经典分类器反而是最稳的起点——它们分别代表了规则切分、概率推断和权重拟合三条完全不同的建模思路。这套资源把三种算法的.ipynb和.py实现连同案例数据打包在一起,配合jupyter notebook打开就能逐格跑通。适合谁?刚接触python分类算法、想拿一份能直接复现的代码对照原理的从业者,以及需要快速验证股票价格波动分析思路的人。它不解决调参玄学,但能让你把三种算法的输入输出、评估口径和踩坑点一次性摸清楚。

2. 决策树分类算法:从基尼指数到股票波动标签的完整落地

2.1 决策树为什么适合先跑股票波动数据

决策树的核心是在每个节点上选一个特征做切分,让子节点的不纯度下降最快。分类任务里常用的不纯度指标是基尼指数和信息熵,前者计算量小、对连续特征分箱友好,后者对类别不平衡更敏感。股票价格波动数据往往混着涨跌幅、成交量、换手率这类连续量,决策树不需要做归一化,直接按阈值切分就能跑,这是它比神经网络省事的地方。

选它的理由很直接:可解释性强。你能把树画出来,看到「换手率 > 3.2% 且 振幅 > 5%」这样的规则路径,这对股票场景下的归因特别有用。代价是单棵树容易过拟合,所以实战里一般会限制max_depth、min_samples_leaf,或者直接换成随机森林。这套资源里的决策树实现是单棵树的版本,适合先把原理跑通。

2.2 用 sklearn 跑通决策树分类的代码骨架

资源里的分类算法.py和.ipynb都包含决策树部分,核心逻辑是读a601318.csv、构造特征列和标签列、切分训练测试集、训练DecisionTreeClassifier、输出准确率和混淆矩阵。下面是我按资源结构整理的可复现代码,字段名按实际 CSV 调整:

import pandas as pd from sklearn.model_selection import train_test_split from sklearn.tree import DecisionTreeClassifier from sklearn.metrics import accuracy_score, confusion_matrix # 读取股票价格波动数据 df = pd.read_csv('a601318.csv') # 特征列:涨跌幅、成交量、换手率等;标签列:波动方向 feature_cols = ['pct_chg', 'volume', 'turnover_rate', 'amplitude'] X = df[feature_cols] y = df['label'] # 假设 label 为 0/1/2 三分类 # 按 7:3 切分,random_state 固定保证可复现 X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.3, random_state=42, stratify=y ) # 限制树深,防止单棵树把训练集背下来 clf = DecisionTreeClassifier( criterion='gini', # 基尼指数,也可换 'entropy' max_depth=5, # 树太深必过拟合 min_samples_leaf=10, # 叶子最少样本数 random_state=42 ) clf.fit(X_train, y_train) y_pred = clf.predict(X_test) print('准确率:', accuracy_score(y_test, y_pred)) print('混淆矩阵:\n', confusion_matrix(y_test, y_pred))

逻辑说明:train_test_split里的stratify=y保证训练测试集类别比例一致,股票标签如果分布不均,不加这个参数准确率会虚高。max_depth=5和min_samples_leaf=10是两个最有效的防过拟合旋钮,前者控制树的复杂度,后者控制叶子节点的统计稳定性。参数怎么改?如果混淆矩阵显示某一类几乎全错,先把max_depth加到 8 看训练集准确率是否飙升,若飙升就是过拟合,回头加min_samples_leaf或换entropy。

2.3 决策树在股票数据上的两个边界

第一个边界是连续特征的分箱。股票数据里像成交量这种量纲极大的列,决策树虽然不要求归一化,但切分点会偏向取值多的特征,导致信息增益被高基数特征主导。常见做法是对成交量做对数变换或分位数分箱,再喂给模型。

第二个边界是类别不平衡。股票波动标签如果「震荡」占 70%,决策树会倾向于全预测震荡。这时候要么用class_weight='balanced',要么在切分时做欠采样。资源里的代码没有默认处理这个,跑之前先value_counts()看一眼标签分布,别等混淆矩阵出来才发现问题。

3. 朴素贝叶斯分类算法:条件独立假设下的概率推断与代码实现

3.1 朴素贝叶斯凭什么在分类任务里还能打

朴素贝叶斯的核心是贝叶斯定理加一个「特征条件独立」的强假设。公式不复杂:给定特征,算每个类别的后验概率,取最大的那个。它的强项是小样本和高维稀疏数据,训练速度极快,不需要迭代优化。股票波动数据如果特征之间相关性不强,朴素贝叶斯能给出一个概率基线,而且它的输出是校准过的概率,不像决策树那样输出的是叶子节点频率。

选它的理由:作为基线模型,它几乎零调参,跑一次就知道数据本身有没有可分性。如果朴素贝叶斯都跑不出比随机猜更好的结果,说明特征工程有问题,换神经网络也白搭。资源里的朴素贝叶斯实现用的是GaussianNB,适合连续特征;如果特征做了分箱,可以换MultinomialNB或CategoricalNB。

3.2 高斯朴素贝叶斯的代码与参数含义

from sklearn.naive_bayes import GaussianNB from sklearn.preprocessing import StandardScaler from sklearn.pipeline import Pipeline from sklearn.metrics import classification_report # 朴素贝叶斯对特征尺度敏感度低于神经网络,但标准化后更稳 pipe = Pipeline([ ('scaler', StandardScaler()), ('nb', GaussianNB(var_smoothing=1e-9)) ]) pipe.fit(X_train, y_train) y_pred_nb = pipe.predict(X_test) print(classification_report(y_test, y_pred_nb, digits=4))

逻辑说明:GaussianNB假设每个特征在每个类别下服从正态分布,var_smoothing是方差平滑项,防止某个特征方差为零导致概率计算除零。默认值1e-9在股票数据上一般够用,如果特征量纲差异极大,先过StandardScaler再进模型。classification_report比单纯看准确率有用,重点看macro avg的f1-score,如果某一类recall极低,说明条件独立假设在这个特征集上被严重违反。

参数怎么改?var_smoothing调大可以缓解过拟合,但太大会让分布变得太平,区分度下降。我一般从1e-9开始,按 10 倍步进试到1e-6,看验证集f1是否稳定。如果特征里有大量零值,GaussianNB不合适,换CategoricalNB并先做分箱。

3.3 朴素贝叶斯在股票场景的适用边界

条件独立假设在股票数据上几乎不可能成立——涨跌幅和振幅天然相关,成交量和换手率也高度耦合。所以朴素贝叶斯的结果只能当基线,不能当最终模型。它的价值在于给你一个「不考虑特征交互时能到多少分」的参照线。如果决策树比它高出一大截,说明特征交互很重要;如果两者差不多,说明数据本身线性可分性弱,得回去查特征构造。

另一个坑是连续特征的正态假设。股票收益率有尖峰厚尾,直接喂GaussianNB会低估极端波动的概率。常见做法是对收益率做秩变换或分位数分箱,再换CategoricalNB。资源里的代码默认走高斯路径,跑之前先画一下特征直方图,别硬套。

4. 人工神经网络分类算法:股票价格波动分析中的 MLP 实战

4.1 为什么用 MLP 而不是直接上 LSTM

股票价格波动分析听起来像时间序列问题,但这份资源的目标是分类,不是预测具体价格。MLP(多层感知机)把每个样本的特征向量映射到类别概率,不建模时间依赖,适合已经构造好截面特征的场景。选 MLP 的理由:它能自动学习特征交互,弥补朴素贝叶斯的独立假设缺陷,同时比 LSTM 好调、好解释、训练快。资源里的神经网络实现就是基于sklearn的MLPClassifier,没有引入pytorch或tensorflow,降低了环境门槛。

4.2 MLPClassifier 的关键参数与训练代码

from sklearn.neural_network import MLPClassifier from sklearn.preprocessing import StandardScaler from sklearn.pipeline import Pipeline from sklearn.metrics import accuracy_score # 神经网络对尺度敏感,标准化必须做 pipe_mlp = Pipeline([ ('scaler', StandardScaler()), ('mlp', MLPClassifier( hidden_layer_sizes=(64, 32), # 两层隐藏层 activation='relu', # 股票数据用 relu 比 tanh 收敛快 solver='adam', # 自适应学习率,省去手调 alpha=1e-4, # L2 正则,防过拟合 max_iter=500, # 迭代上限,不够会警告 early_stopping=True, # 留验证集早停 random_state=42 )) ]) pipe_mlp.fit(X_train, y_train) y_pred_mlp = pipe_mlp.predict(X_test) print('MLP 准确率:', accuracy_score(y_test, y_pred_mlp))

逻辑说明:hidden_layer_sizes=(64, 32)表示两层,第一层 64 个神经元,第二层 32 个。股票数据样本量通常不大,层数别超过 3,否则参数量爆炸。alpha=1e-4是 L2 惩罚系数,调大可以压过拟合,调小让模型更自由。early_stopping=True会从训练集里切 10% 做验证,连续若干轮验证分不升就停,这是防过拟合最省事的开关。

参数怎么改?如果训练集准确率远高于验证集,先加alpha到1e-3,再考虑减层。如果训练集本身就低,先把max_iter加到 1000,看是不是没收敛。solver='adam'对大多数场景够用,数据量特别小时可以换lbfgs,收敛更稳但每轮慢。

4.3 神经网络在股票波动分类里的三个实操坑

第一个坑是标准化。MLP 对特征尺度极度敏感,成交量如果是百万级、涨跌幅是小数级,不标准化直接跑,梯度会被大量纲特征主导,模型等于只学了成交量。资源里的.py如果没写StandardScaler,自己补上。

第二个坑是随机种子。MLPClassifier的权重初始化是随机的,不固定random_state每次跑出来的准确率能差 5 个点。做对比实验时固定种子,否则你分不清是模型改进了还是运气好。

第三个坑是早停的验证集切分。early_stopping=True默认从训练集里切 10%,如果训练集本身只有几百条,切完验证集太小,早停信号噪声大。这时候要么关掉早停手动定max_iter,要么用交叉验证选轮数。

5. 避坑与排查:三种分类器跑股票数据时的常见翻车记录

5.1 标签泄漏:用未来数据预测过去

现象:准确率异常高,超过 0.95,但实盘完全不能用。原因:特征列里混入了未来信息,比如用当日收盘价算的标签,又用当日收盘价当特征。解决:检查a601318.csv的字段,确保特征在时间上早于标签。如果是按时间切分,用TimeSeriesSplit而不是随机train_test_split。

5.2 混淆矩阵全预测同一类

现象:准确率看着还行,但混淆矩阵里某一类recall为 0。原因:类别不平衡,模型学会了偷懒。解决:先df['label'].value_counts()看分布,加class_weight='balanced',或者对多数类欠采样。决策树和 MLP 都支持class_weight,朴素贝叶斯不支持,得在数据层面处理。

5.3 神经网络不收敛,损失震荡

现象:max_iter跑满还在警告ConvergenceWarning,准确率在 0.5 附近晃。原因:学习率太大或特征没标准化。解决:先确认StandardScaler在 pipeline 里,再把alpha调大、learning_rate_init调小。如果还不行,换solver='lbfgs'试一轮。

5.4 决策树训练集准确率 1.0,测试集 0.6

现象:树深没限制,每个叶子只有一个样本。原因:max_depth默认None,树长到完全拟合。解决:设max_depth在 3 到 8 之间,加min_samples_leaf至少 5。用clf.get_depth()看实际树深,超过 10 基本就是过拟合。

5.5 CSV 读取时中文列名乱码

现象:pd.read_csv后列名变成\ufeffpct_chg或乱码。原因:文件带 BOM 头或编码不是 UTF-8。解决:pd.read_csv('a601318.csv', encoding='utf-8-sig'),或者先df.columns = df.columns.str.strip()去掉隐藏字符。

6. 把三种分类器串成一条对比流水线:验证方法与一个固定习惯

跑通单个模型只是第一步,真正有价值的是把三种分类器放在同一套切分和评估口径下对比。我一般会写一个统一的evaluate函数,接收模型、训练集、测试集,返回准确率和macro f1,然后循环跑决策树、朴素贝叶斯、MLP。这样能排除切分随机性带来的干扰。

from sklearn.metrics import f1_score def evaluate(name, model, X_tr, y_tr, X_te, y_te): model.fit(X_tr, y_tr) pred = model.predict(X_te) acc = accuracy_score(y_te, pred) f1 = f1_score(y_te, pred, average='macro') print(f'{name}: acc={acc:.4f}, macro_f1={f1:.4f}') return acc, f1 # 三种模型统一对比 evaluate('DecisionTree', clf, X_train, y_train, X_test, y_test) evaluate('GaussianNB', pipe, X_train, y_train, X_test, y_test) evaluate('MLP', pipe_mlp, X_train, y_train, X_test, y_test)

对比时重点看macro_f1而不是准确率,因为股票标签往往不平衡,准确率会被多数类带偏。如果决策树的macro_f1最高,说明规则切分有效;如果 MLP 明显领先,说明特征交互重要;如果三者差不多,回去查特征工程,大概率是特征本身没信息量。

验证方法上,单次train_test_split不够稳,样本量小于 5000 时建议用StratifiedKFold跑 5 折,取macro_f1的均值和标准差。标准差大于 0.05 说明模型对切分敏感,得固定更多随机种子或扩大数据。

最后一个固定习惯:每次跑完三种模型,我都会把classification_report的macro avg那行单独存到一个 CSV 里,列名是模型名、准确率、macro_f1、训练时间。跑过十几轮之后,这张表比任何单次结果都有说服力。血泪经验是,曾经因为没固定random_state,把 MLP 的随机波动当成调参收益,白折腾了一周。从那以后我每次对比实验都强制走一遍种子固定和交叉验证,再下结论。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询