基于Python的财务风险预警系统构建:从数据到模型的完整实践 📅 发布时间:2026/9/1 3:59:22 👁 浏览次数: 在实际的数据科学与人工智能课程中期末实践报告往往是学生将理论知识转化为具体项目能力的第一次系统性尝试。对于会计、金融等非纯技术背景的班级而言这份报告的核心挑战在于如何将数据科学Data Science与人工智能Artificial Intelligence的方法论与一个具体的、可理解的业务领域如会计、财务分析相结合而不是仅仅停留在算法调用的表面。一个成功的实践报告应该清晰地展示从问题定义、数据获取与处理、模型选择与训练到结果分析与业务解读的完整闭环并体现出对技术原理的初步理解和工程化落地的思考。本文将以“会计数据分析”为背景构建一个完整的期末实践项目框架。我们将围绕“企业财务风险预警”这一经典场景使用Python生态中的常见工具库完成一个从数据到模型再到可视化报告的最小可行项目。通过这个项目你将掌握如何搭建一个标准的数据科学工作流理解机器学习模型在财务领域的应用逻辑并学会撰写一份结构清晰、内容扎实的技术实践报告。无论你是会计专业的学生初次接触编程还是已有一定基础希望深化理解本文提供的步骤、代码和思路都将为你提供一个可直接复现的蓝本。1. 理解项目目标构建一个财务风险预警分析系统在开始写代码之前必须明确我们究竟要解决什么问题以及如何用数据科学的方法来解决它。一个模糊的目标会导致后续所有步骤的混乱。1.1 业务问题定义从会计视角看风险预警对于会计或财务分析而言风险预警的核心是提前识别出可能陷入财务困境如破产、债务违约、持续亏损的企业。传统的财务分析依赖于财务比率如流动比率、资产负债率和专家经验判断。数据科学的方法则试图从历史数据中自动学习出这些风险模式。我们的项目目标可以定义为利用上市公司公开的财务数据构建一个分类模型能够根据企业过去一年的关键财务指标预测其下一年是否会被标记为“ST”特别处理通常意味着财务异常。ST状态在中国A股市场是一个明确的财务风险信号数据相对容易获取且标签清晰非常适合作为学习项目。1.2 技术路径设计标准CRISP-DM工作流为了实现上述目标我们将遵循跨行业数据挖掘标准流程CRISP-DM这是数据科学项目最常用的方法论框架。我们的技术路径将分为六个阶段业务理解明确预测目标ST状态和可用数据财务指标。数据理解获取数据探索数据的基本情况、分布和缺失值。数据准备清洗数据、处理缺失值、特征工程、划分训练集和测试集。建模选择并训练一个或多个机器学习模型。评估使用测试集评估模型性能选择最佳模型。部署在项目中体现为生成分析报告和可视化结果。这个流程确保了项目的系统性和可重复性。1.3 环境与工具准备搭建Python数据科学工作台工欲善其事必先利其器。一个稳定、统一的环境是项目成功的基础。我们将使用Python作为主要编程语言并依赖以下几个核心库数据处理pandas,numpy数据可视化matplotlib,seaborn机器学习scikit-learn统计分析scipy(可选)开发环境推荐使用Jupyter Notebook或VS Code便于交互和展示。首先我们通过命令行创建并配置项目环境。如果你使用conda可以按以下步骤操作# 1. 创建一个新的conda环境指定Python版本 conda create -n finance_risk_py39 python3.9 # 2. 激活环境 conda activate finance_risk_py39 # 3. 安装核心依赖库 pip install pandas numpy matplotlib seaborn scikit-learn jupyter如果你使用纯pip和venv# 1. 创建项目文件夹并进入 mkdir finance_risk_project cd finance_risk_project # 2. 创建虚拟环境 python -m venv venv # 3. 激活虚拟环境 # 在Windows上: venv\Scripts\activate # 在Mac/Linux上: source venv/bin/activate # 4. 安装核心依赖库 pip install pandas numpy matplotlib seaborn scikit-learn jupyter环境配置完成后可以在项目根目录下启动Jupyter Notebook并创建一个新的Notebook文件例如financial_risk_analysis.ipynb。后续的代码都将在这个Notebook中分步骤执行和讲解。2. 数据获取、理解与准备数据是模型的燃料其质量直接决定模型性能的上限。这一阶段耗时最长也最容易出错。2.1 数据来源与获取对于上市公司财务数据有多个开源或付费的数据库。为了学习目的我们可以使用akshare这个免费的金融数据接口库或者使用预设的示例数据集。这里为了流程的稳定性和可复现性我们使用scikit-learn内置的一个模拟分类数据集作为演示并模拟财务数据的特征命名。在实际报告中你应该尽可能使用真实数据如从CSMAR、Wind或akshare获取。首先我们加载必要的库并创建一个模拟的财务数据集。# 导入必要的库 import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns from sklearn.datasets import make_classification from sklearn.model_selection import train_test_split # 设置中文显示和图形样式可选 plt.rcParams[font.sans-serif] [SimHei] # 用来正常显示中文标签 plt.rcParams[axes.unicode_minus] False # 用来正常显示负号 sns.set_style(whitegrid) # 生成模拟财务数据 # n_samples: 样本数公司数 # n_features: 特征数财务指标数这里设为10个关键指标 # n_informative: 实际对分类有用的特征数 # n_redundant: 冗余特征由信息特征线性组合而成 # n_clusters_per_class: 每个类别有几个簇 # random_state: 随机种子确保结果可复现 X, y make_classification(n_samples1000, n_features10, n_informative6, n_redundant2, n_clusters_per_class1, random_state42) # 将数据转换为DataFrame便于理解和操作 # 为特征命名模拟常见的财务指标 feature_names [ 流动比率, 速动比率, 资产负债率, 总资产周转率, 应收账款周转率, 存货周转率, 营业收入增长率, 净利润增长率, 净资产收益率, 每股收益 ] df pd.DataFrame(X, columnsfeature_names) # 添加目标列是否ST (1表示ST0表示非ST) df[is_ST] y # 查看数据前5行和基本信息 print(数据形状样本数 特征数目标:, df.shape) print(\n数据前5行) print(df.head()) print(\n数据基本信息) print(df.info()) print(\n目标变量分布) print(df[is_ST].value_counts()) print(ST比例, df[is_ST].mean())2.2 数据探索与可视化在建模前我们必须了解数据的“长相”。这包括检查缺失值、异常值、特征分布以及特征与目标的关系。# 1. 检查缺失值 print(缺失值统计) print(df.isnull().sum()) # 2. 查看基本统计描述 print(\n数值特征描述性统计) print(df.describe()) # 3. 目标变量分布可视化 plt.figure(figsize(6, 4)) sns.countplot(xis_ST, datadf) plt.title(ST与非ST公司数量分布) plt.xlabel(是否ST (0:否 1:是)) plt.ylabel(公司数量) plt.show() # 4. 特征分布直方图以两个特征为例 fig, axes plt.subplots(2, 3, figsize(15, 8)) axes axes.ravel() # 将二维坐标轴数组展平 for idx, col in enumerate(feature_names[:6]): # 只看前6个特征 axes[idx].hist(df[col], bins30, edgecolorblack, alpha0.7) axes[idx].set_title(f{col}分布) axes[idx].set_xlabel(col) axes[idx].set_ylabel(频数) plt.tight_layout() plt.show() # 5. 特征与目标的关系箱线图 plt.figure(figsize(10, 6)) # 选取‘资产负债率’和‘净资产收益率’两个关键指标进行对比 df_melt pd.melt(df, id_vars[is_ST], value_vars[资产负债率, 净资产收益率], var_name财务指标, value_name值) sns.boxplot(x财务指标, y值, hueis_ST, datadf_melt) plt.title(ST与非ST公司在关键财务指标上的差异) plt.show() # 6. 特征间相关性热力图 plt.figure(figsize(10, 8)) correlation_matrix df[feature_names].corr() sns.heatmap(correlation_matrix, annotTrue, fmt.2f, cmapcoolwarm, squareTrue, cbar_kws{shrink: .8}) plt.title(财务指标相关性热力图) plt.show()通过以上可视化我们可以初步判断数据是否平衡ST公司通常远少于非ST公司即样本不均衡哪些特征分布有异常特征之间是否存在高度相关性如流动比率和速动比率可能相关以及哪些特征在ST和非ST组间表现出明显差异。2.3 数据预处理与特征工程原始数据很少能直接用于建模。我们需要进行一系列清洗和转换。from sklearn.preprocessing import StandardScaler from sklearn.feature_selection import SelectKBest, f_classif # 1. 处理缺失值本例模拟数据无缺失此处展示通用方法 # 对于数值特征常用均值、中位数或众数填充 # df.fillna(df.mean(), inplaceTrue) # 2. 处理异常值可选根据业务逻辑 # 例如对于‘资产负债率’理论上应在0-1之间但可能有极端值 # 可以使用分位数进行截断 # for col in [资产负债率]: # lower df[col].quantile(0.01) # upper df[col].quantile(0.99) # df[col] df[col].clip(lower, upper) # 3. 特征缩放 # 很多模型如SVM、KNN、神经网络对特征尺度敏感需要进行标准化 scaler StandardScaler() X_scaled scaler.fit_transform(df[feature_names]) # 将缩放后的数据存回DataFrame方便查看 df_scaled pd.DataFrame(X_scaled, columns[f{col}_scaled for col in feature_names]) df pd.concat([df, df_scaled], axis1) # 4. 特征选择 # 使用方差分析ANOVA选择与目标最相关的k个特征 selector SelectKBest(score_funcf_classif, k6) # 选择6个最佳特征 X_selected selector.fit_transform(df[[f{col}_scaled for col in feature_names]], df[is_ST]) # 获取被选中的特征名 selected_mask selector.get_support() selected_features [feature_names[i] for i in range(len(feature_names)) if selected_mask[i]] print(f选择出的{len(selected_features)}个重要特征{selected_features}) # 5. 划分训练集和测试集 # 这是关键一步确保模型评估的公正性。stratify参数保证训练集和测试集中ST比例一致。 X_train, X_test, y_train, y_test train_test_split( X_selected, df[is_ST], test_size0.2, random_state42, stratifydf[is_ST] ) print(f训练集大小{X_train.shape} 测试集大小{X_test.shape}) print(f训练集ST比例{y_train.mean():.3f} 测试集ST比例{y_test.mean():.3f})3. 模型选择、训练与评估有了干净的数据我们就可以开始尝试不同的机器学习模型并科学地评估它们的性能。3.1 模型选择与训练我们尝试三种经典且解释性不同的分类模型逻辑回归基础、随机森林集成树模型、支持向量机SVM。通过对比理解不同模型的特性。from sklearn.linear_model import LogisticRegression from sklearn.ensemble import RandomForestClassifier from sklearn.svm import SVC from sklearn.metrics import classification_report, confusion_matrix, accuracy_score, roc_auc_score, roc_curve # 初始化模型 models { 逻辑回归: LogisticRegression(random_state42, max_iter1000), 随机森林: RandomForestClassifier(n_estimators100, random_state42), 支持向量机: SVC(probabilityTrue, random_state42) # 启用概率估计方便计算AUC } # 用于存储每个模型在测试集上的预测结果和性能 results {} for name, model in models.items(): print(f\n 训练 {name} ) # 训练模型 model.fit(X_train, y_train) # 在测试集上预测 y_pred model.predict(X_test) y_pred_proba model.predict_proba(X_test)[:, 1] if hasattr(model, predict_proba) else None # 计算评估指标 accuracy accuracy_score(y_test, y_pred) report classification_report(y_test, y_pred, output_dictTrue) cm confusion_matrix(y_test, y_pred) # 存储结果 results[name] { model: model, y_pred: y_pred, y_pred_proba: y_pred_proba, accuracy: accuracy, classification_report: report, confusion_matrix: cm } # 打印关键指标 print(f准确率 (Accuracy): {accuracy:.4f}) print(f精确率 (Precision - ST类): {report[1][precision]:.4f}) print(f召回率 (Recall - ST类): {report[1][recall]:.4f}) print(fF1分数 (F1-Score - ST类): {report[1][f1-score]:.4f}) print(混淆矩阵) print(cm)3.2 模型性能评估与可视化对于分类问题尤其是样本不均衡的风险预警问题不能只看准确率。我们需要综合多个指标并借助可视化工具。# 1. 绘制ROC曲线比较模型 plt.figure(figsize(8, 6)) for name, res in results.items(): if res[y_pred_proba] is not None: fpr, tpr, _ roc_curve(y_test, res[y_pred_proba]) auc roc_auc_score(y_test, res[y_pred_proba]) plt.plot(fpr, tpr, labelf{name} (AUC {auc:.3f})) plt.plot([0, 1], [0, 1], k--, label随机猜测 (AUC 0.5)) plt.xlim([0.0, 1.0]) plt.ylim([0.0, 1.05]) plt.xlabel(假正率 (False Positive Rate)) plt.ylabel(真正率 (True Positive Rate)) plt.title(不同模型的ROC曲线对比) plt.legend(loclower right) plt.grid(True) plt.show() # 2. 绘制性能指标对比柱状图 metrics_df pd.DataFrame({ 模型: list(results.keys()), 准确率: [res[accuracy] for res in results.values()], ST类精确率: [res[classification_report][1][precision] for res in results.values()], ST类召回率: [res[classification_report][1][recall] for res in results.values()], ST类F1: [res[classification_report][1][f1-score] for res in results.values()], }) fig, axes plt.subplots(2, 2, figsize(12, 8)) axes axes.ravel() metric_cols [准确率, ST类精确率, ST类召回率, ST类F1] for idx, col in enumerate(metric_cols): axes[idx].bar(metrics_df[模型], metrics_df[col]) axes[idx].set_title(col) axes[idx].set_ylabel(分数) # 在柱子上方显示数值 for i, v in enumerate(metrics_df[col]): axes[idx].text(i, v 0.01, f{v:.3f}, hacenter) plt.tight_layout() plt.show() # 3. 分析最佳模型的特征重要性以随机森林为例 if 随机森林 in results: best_model results[随机森林][model] importances best_model.feature_importances_ indices np.argsort(importances)[::-1] # 按重要性降序排列 plt.figure(figsize(10, 6)) plt.title(随机森林模型 - 特征重要性) plt.bar(range(len(selected_features)), importances[indices], aligncenter) plt.xticks(range(len(selected_features)), [selected_features[i] for i in indices], rotation45) plt.xlabel(特征) plt.ylabel(重要性得分) plt.tight_layout() plt.show() # 打印重要性排序 print(特征重要性排序) for i in indices: print(f {selected_features[i]}: {importances[i]:.4f})3.3 模型选择与解释根据以上评估我们可以得出一些结论准确率可能很高但因为ST公司样本少模型如果全部预测为“非ST”也能获得高准确率因此这个指标参考价值有限。精确率预测为ST的公司中真正是ST的比例。高精确率意味着预警信号的可信度高可以减少误报。召回率真正的ST公司中被模型成功预测出来的比例。高召回率意味着漏报少。F1分数精确率和召回率的调和平均数是衡量模型对少数类ST识别能力的综合指标。AUCROC曲线下的面积衡量模型整体排序能力越接近1越好对样本不均衡不敏感。通常在财务风险预警中我们更关心召回率尽量不漏掉风险公司和精确率预警信号要靠谱需要在两者之间根据业务成本进行权衡。从特征重要性图中我们可以解读出哪些财务指标对预测ST状态贡献最大这本身就是一份有价值的分析结论。4. 项目总结、报告撰写与进阶思考完成模型构建与评估后需要将整个工作整理成一份结构化的实践报告并思考项目的局限性与改进方向。4.1 实践报告的核心结构一份合格的数据科学与人工智能实践报告应包含以下部分你可以将前面步骤的代码、输出和图表整合进去摘要用200-300字概括项目目标、方法、主要发现和结论。引言/背景阐述财务风险预警的意义以及数据科学方法在该领域的应用价值。问题定义与数据明确预测目标二分类ST/非ST说明数据来源、字段含义、样本规模及基本统计特征。方法论数据预处理流程缺失值、异常值、标准化。特征工程方法特征选择、构造。使用的模型及其原理简介逻辑回归、随机森林、SVM。模型评估指标准确率、精确率、召回率、F1、AUC、混淆矩阵。实验过程与结果展示数据探索的可视化结果分布、相关性、类别差异。呈现模型训练后的性能对比表格和图表如ROC曲线、指标柱状图。展示最佳模型的特征重要性分析。讨论与分析对比不同模型的优劣解释为什么某个模型在本任务上表现更好。结合特征重要性讨论哪些财务指标对风险预警最关键这与传统财务分析理论是否一致分析模型的误报将健康公司判为ST和漏报将ST公司判为健康案例讨论其业务影响。结论与展望总结项目是否达到预期目标。指出本项目的局限性如数据量小、特征有限、未考虑时序性等。提出未来改进方向如引入更多非财务数据、使用深度学习模型、考虑动态预测等。参考文献列出引用的数据来源、算法库和关键理论文献。附录可以包含核心代码片段或完整代码的GitHub仓库链接。4.2 项目常见问题与排查在完成项目的过程中你可能会遇到以下典型问题问题现象可能原因检查与解决思路模型准确率很高95%但召回率极低接近0样本严重不均衡。模型倾向于预测多数类。1. 检查目标变量分布 (df[‘is_ST’].value_counts())。2. 使用过采样如SMOTE、欠采样或调整类别权重如class_weight‘balanced’。3. 改用AUC、F1等对不均衡更鲁棒的指标评估。所有模型性能都很差AUC接近0.5特征与目标无关或数据噪声太大。模型无法学习到有效模式。1. 重新进行数据探索可视化特征与目标的关系检查是否真的存在区分度。2. 检查数据预处理是否正确例如标准化是否误操作。3. 尝试更复杂的特征工程或检查数据来源和质量。训练集表现很好测试集表现很差过拟合。模型过度记忆了训练集的噪声。1. 增加训练数据量。2. 简化模型复杂度如减少树深度、增加正则化参数。3. 使用交叉验证选择超参数而不是在训练集上优化。ValueError: Unknown label type: ‘continuous’目标变量y是浮点数但分类模型期望整数标签。使用y y.astype(int)将目标变量转换为整型。运行akshare等库获取数据时报网络错误或接口变更网络问题或第三方库API更新。1. 检查网络连接。2. 查看库的官方文档或GitHub Issues确认接口用法是否已更新。3. 作为备选使用本地缓存的CSV文件或模拟数据确保项目主体可进行。4.3 从课程实践到生产环境的思考课程项目与真实生产系统之间存在巨大鸿沟。完成基础实践后可以从以下角度进行扩展思考这能让你的报告更具深度数据层面实时性财务报告是季报/年报如何构建更及时的预警指标如结合股价、新闻舆情等另类数据。时序性本项目使用了截面数据。真实风险是演化的如何利用多年财务数据构建时序模型如LSTM数据质量真实财务数据存在缺失、错误、操纵财务造假问题如何清洗和验证模型层面可解释性在金融风控领域模型的可解释性至关重要。如何用SHAP、LIME等工具解释单个预测模型稳定性模型性能是否会随时间推移而衰减如何设计模型监控和定期重训练机制集成与优化是否可以用模型融合Stacking提升性能如何系统地进行超参数调优系统层面工程化如何将Jupyter Notebook中的分析代码重构为模块化、可配置、可调度的生产代码Python脚本API服务如何将训练好的模型封装成RESTful API供其他系统调用自动化报告如何利用Python如Jinja2WeasyPrint或BI工具如Tableau, Superset自动生成可视化分析报告这份期末实践报告的核心价值不仅在于你跑通了一个机器学习流程更在于你通过这个过程理解了数据科学项目从业务问题出发经过数据、模型、评估最终回归业务决策的完整逻辑。尝试用你的代码和文字将这个故事清晰地讲述出来。