当前位置:首页>python>企业会不会“爆雷”?用 Python 提前识别财务危机风险

企业会不会“爆雷”?用 Python 提前识别财务危机风险

  • 2026-09-10 20:45:37
企业会不会“爆雷”?用 Python 提前识别财务危机风险

一、案例简介

企业财务风险分析,最麻烦的地方往往不是看懂某一个指标,而是同时处理几十个指标。资产负债率偏高可能意味着偿债压力,但如果企业现金流充足,也未必会陷入危机;利润下降可能只是短期波动,也可能是经营恶化的信号。

单独依靠某一项财务指标,很难准确判断企业是否存在风险。因此,这套案例把企业风险预警转化为一个机器学习分类问题:

企业财务数据    ↓数据清洗与变量构造    ↓划分训练集和测试集    ↓逻辑回归、随机森林、XGBoost    ↓计算财务危机概率    ↓生成企业风险预警名单

1. 研究问题

案例主要回答三个问题:

  1. 1. 哪些企业更可能出现财务危机?
  2. 2. 哪些财务指标对风险预警最重要?
  3. 3. 不同机器学习模型的预测能力有何差异?

2. 风险定义

将企业是否发生财务危机设置为二分类变量:

取值
含义
0
企业经营状况正常
1
企业出现亏损、违约或持续经营风险

模型最终输出的不是简单的“正常”或“危机”,而是每家企业发生财务危机的预测概率。

3. 数据结构

案例数据包含3,200条企业观测,财务危机企业占比约20%。主要变量如下:

变量
含义
风险方向
debt_ratio
资产负债率
越高风险越大
current_ratio
流动比率
越低风险越大
cashflow_ratio
经营现金流比率
越低风险越大
roa
总资产收益率
越低风险越大
revenue_growth
营业收入增长率
越低风险越大
receivable_turnover
应收账款周转率
越低风险越大
firm_size
企业规模
不确定
firm_age
企业年龄
不确定
ownership_concentration
股权集中度
不确定
financial_distress
是否发生财务危机
被解释变量

二、代码思路

1. 数据预处理

首先处理缺失值和异常值,再将样本按照80%和20%的比例划分为训练集与测试集。

由于正常企业数量通常远多于危机企业,划分时需要使用分层抽样,保证两个数据集中危机企业的占比基本一致。

2. 建立三个模型

案例同时训练三种模型:

  • • 逻辑回归:结构清晰,适合作为基准模型;
  • • 随机森林:能够识别非线性关系和变量交互;
  • • XGBoost:通过逐步修正预测误差,提高风险识别能力。

3. 评价模型效果

企业财务风险预警不能只看准确率。假设100家企业中只有10家出现危机,即使模型将全部企业预测为正常,准确率也能达到90%,但这个模型没有识别出任何真正的风险企业。

因此,案例重点使用以下指标:

指标
含义
Accuracy
全部企业中预测正确的比例
Precision
被预警企业中真正发生危机的比例
Recall
实际危机企业中被成功识别的比例
F1-score
Precision与Recall的综合表现
AUC
模型区分正常企业与危机企业的能力

对于风险预警任务,Recall和AUC通常比单纯的准确率更加重要。

4. 输出风险名单

模型训练完成后,为每家企业计算财务危机概率,并划分风险等级:

预测概率
风险等级
0.00~0.30
低风险
0.30~0.60
中风险
0.60~1.00
高风险

三、核心代码

1. 读取企业数据

import pandas as pddata = pd.read_csv(    "data/enterprise_financial_data.csv",    encoding="utf-8-sig")feature_columns = [    "debt_ratio",    "current_ratio",    "cashflow_ratio",    "roa",    "revenue_growth",    "receivable_turnover",    "firm_size",    "firm_age",    "ownership_concentration"]X = data[feature_columns]y = data["financial_distress"]

代码从CSV文件读取企业财务指标,并将financial_distress设置为预测目标。

2. 处理缺失值

from sklearn.impute import SimpleImputerimputer = SimpleImputer(strategy="median")X_imputed = pd.DataFrame(    imputer.fit_transform(X),    columns=feature_columns)

这里使用中位数填补缺失值。相比均值,中位数对极端财务数据更加稳健。

3. 划分训练集与测试集

from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(    X_imputed,    y,    test_size=0.2,    random_state=42,    stratify=y)

stratify=y表示分层抽样,避免训练集和测试集中的危机企业比例相差过大。

4. 训练逻辑回归

from sklearn.pipeline import Pipelinefrom sklearn.preprocessing import StandardScalerfrom sklearn.linear_model import LogisticRegressionlogistic_model = Pipeline([    ("scaler", StandardScaler()),    ("model", LogisticRegression(        class_weight="balanced",        max_iter=1000,        random_state=42    ))])logistic_model.fit(X_train, y_train)

class_weight="balanced"会提高少数类别的权重,使模型更加重视财务危机企业。

5. 训练随机森林

from sklearn.ensemble import RandomForestClassifierrf_model = RandomForestClassifier(    n_estimators=500,    max_depth=8,    min_samples_leaf=5,    class_weight="balanced",    random_state=42,    n_jobs=-1)rf_model.fit(X_train, y_train)

随机森林通过建立多棵决策树进行综合判断,可以识别资产负债率、盈利能力和现金流之间的复杂关系。

6. 训练XGBoost

from xgboost import XGBClassifiernegative_num = (y_train == 0).sum()positive_num = (y_train == 1).sum()xgb_model = XGBClassifier(    n_estimators=400,    max_depth=4,    learning_rate=0.05,    subsample=0.8,    colsample_bytree=0.8,    scale_pos_weight=negative_num / positive_num,    eval_metric="logloss",    random_state=42)xgb_model.fit(X_train, y_train)

scale_pos_weight用于处理类别不平衡,提高模型对危机企业的敏感度。

7. 比较模型表现

from sklearn.metrics import (    accuracy_score,    precision_score,    recall_score,    f1_score,    roc_auc_score)models = {    "逻辑回归": logistic_model,    "随机森林": rf_model,    "XGBoost": xgb_model}results = []for model_name, model in models.items():    prediction = model.predict(X_test)    probability = model.predict_proba(X_test)[:, 1]    results.append({        "模型": model_name,        "准确率": accuracy_score(y_test, prediction),        "精确率": precision_score(y_test, prediction),        "召回率": recall_score(y_test, prediction),        "F1值": f1_score(y_test, prediction),        "AUC": roc_auc_score(y_test, probability)    })result_table = pd.DataFrame(results)print(result_table)

8. 生成风险名单

data["distress_probability"] = xgb_model.predict_proba(    X_imputed)[:, 1]data["risk_level"] = pd.cut(    data["distress_probability"],    bins=[0, 0.3, 0.6, 1.0],    labels=["低风险", "中风险", "高风险"],    include_lowest=True)risk_list = data[    [        "firm_id",        "firm_name",        "distress_probability",        "risk_level"    ]].sort_values(    "distress_probability",    ascending=False)risk_list.to_csv(    "output/企业财务风险预警名单.csv",    index=False,    encoding="utf-8-sig")

四、结果展示

1. 模型效果对比

测试集包含640家企业,其中128家企业属于财务危机样本。三种模型的预测结果如下:

模型
准确率
精确率
召回率
F1值
AUC
逻辑回归
0.814
0.602
0.703
0.648
0.821
随机森林
0.869
0.690
0.766
0.726
0.891
XGBoost
0.9060.7430.8130.7760.921

结果表明,XGBoost的综合表现最好,AUC达到0.921,并成功识别出81.3%的财务危机企业。

2. XGBoost识别结果

实际情况
预测正常
预测危机
合计
正常企业
476
36
512
危机企业
24
104
128
合计
500
140
640

在128家实际发生财务危机的企业中,模型成功识别104家,遗漏24家。与此同时,有36家正常企业被提前列入风险名单。

对于财务预警场景,适当增加误报可以换取更高的危机企业识别率,为后续人工核查争取时间。

3. 重要风险指标

XGBoost给出的变量重要性如下:

排名
财务指标
重要性
1
资产负债率
0.214
2
经营现金流比率
0.183
3
总资产收益率
0.162
4
流动比率
0.124
5
营业收入增长率
0.103
6
应收账款周转率
0.076
7
股权集中度
0.052
8
企业规模
0.045
9
企业年龄
0.041

从结果来看,企业风险主要集中在三个方面:

  1. 1. 债务压力较高:资产负债率越高,财务风险越明显;
  2. 2. 现金流持续恶化:经营现金流不足时,企业可能难以维持日常经营;
  3. 3. 盈利能力下降:ROA和营业收入增长率降低,会明显提高危机概率。

4. 高风险企业名单

按照XGBoost输出的危机概率,风险最高的部分企业如下:

企业编号
企业名称
危机概率
风险等级
F0286
华*制造
0.947
高风险
F1732
中*设备
0.921
高风险
F0954
瑞*材料
0.896
高风险
F2417
恒*科技
0.873
高风险
F0641
新*机械
0.851
高风险

进一步查看这些企业的财务数据可以发现,它们普遍具有资产负债率偏高、现金流不足、盈利能力下降和收入负增长等特征。

通过这套流程,原本分散在财务报表中的指标被转换为直观的风险概率和预警等级。后续还可以继续加入行业特征、审计意见、股票交易数据和企业年报文本,构建更加完整的企业财务风险预警系统。

最新文章

随机文章