Python实现DEA模型的中小企业融资效率评价实战 1. 为什么想起做这个评价体系一个信贷人员的真实痛点我自己在金融机构做过几年中小企业信贷相关的工作天天跟中小企业主的报表打交道。说实话大部分中小企业的财务数据拿到手里第一反应是这玩意儿能信吗。但另一个现实是银行要放贷、担保公司要承保、政府要发补贴、投资机构要看项目大家都需要一个相对客观的效率标尺。否则就只能靠关系、靠感觉、靠抵押物这恰恰是中小企业融资难、融资贵的核心症结之一。后来我转到数据岗位开始尝试用 Python 把这件事做扎实——不只是算几个财务比率然后打个分而是用 DEA数据包络分析Data Envelopment Analysis这类相对成熟的效率评价模型把企业的投入产出效率量化出来。之所以选 DEA是因为它对小样本、多投入多产出的场景特别友好不需要假设具体的生产函数形式也不用像回归那样担心多重共线性问题。这对财务数据不那么规范的中小企业来说简直是量身定做。这篇文章就把我实际跑通的整套方案分享出来从模拟数据生成、指标体系设计、DEA 建模、效率值计算到结果解读和可视化全部用 Python 完成代码可以直接跑数据是模拟的但结构贴近真实。如果你手头有真实的企业数据替换掉数据加载部分就能用。2. 中小企业融资效率评价的逻辑先把效率这件事想清楚2.1 为什么传统打分法不够用传统上很多机构评价中小企业融资能力用的是加权评分法选一堆指标比如资产负债率、流动比率、营收增长率然后给每个指标赋权重加总出总分。这个方法的问题很明显——权重是拍脑袋定的。凭什么流动比率权重是 15% 而不是 20%不同行业、不同生命周期阶段的企业权重应该一样吗没人能给出令人信服的答案。更关键的是加权评分法衡量的是绝对水平不是效率。一家企业资产负债率 40%看起来不错但如果它所在的行业普遍能做到 30%而且它用同样的资产只产出了行业平均 70% 的收入那它的融资效率其实是低的。DEA 的思路正好相反它不关心绝对的财务指标数值而是关心给定投入下产出是否达到了前沿面上的最优水平。2.2 DEA 的核心思想用前沿面说话DEA 的基本逻辑可以这样理解把每一家企业看作一个决策单元DMU每个 DMU 有若干投入和若干产出。DEA 通过线性规划在所有 DMU 中找到一个生产前沿面——也就是用最少的投入得到最多产出的那些企业组成的包络面。其他企业如果落在这个前沿面之内说明它们的效率还有提升空间如果正好落在前沿面上效率值就是 1代表在当前样本集合中已经是相对最优。这个思想用一个生活化的类比就很好懂假设你要评价几个外卖骑手的效率投入是每天跑的单量和工作时长其实这俩都是投入一个算是劳动强度产出是日收入和客户好评数。DEA 不会告诉你一个满分是 100 分的绝对标准它只看你们这批骑手里谁在同样的条件下做到了最好然后用这个最好作为标杆去衡量其他人。2.3 为什么适合中小企业数据中小企业的财务数据有几个公认的痛点样本量小一个区域里能拿到完整数据的企业可能就几十家、指标分布不规律、存在异常值、量纲不统一。DEA 对这些问题的容忍度很高小样本友好DEA 的经验法则是样本量不少于投入产出指标总数的 2-3 倍30-50 家企业配 3-4 个指标完全够用。无需量纲处理投入和产出可以有不同的单位DEA 的线性规划会自动处理。无需预设函数关系不需要像回归那样假设产出 f(投入)的具体形式。对异常值不敏感因为 DEA 评估的是相对效率个别数据的波动不会像回归那样牵扯所有参数。当然 DEA 也有它的局限它衡量的是相对效率样本变了结果就变了而且它不区分随机误差和管理无效率这是 DEA 与 SFA 随机前沿分析的一个重要区别后面我会提一句。但对中小企业融资评价这个场景来说DEA 的拿来就能用特性碾压了它的局限。3. 评价指标体系设计选什么投入选什么产出3.1 指标选择的原则DEA 的结果高度依赖指标选择这是整个流程里最需要谨慎的一步。不是指标越多越好——指标多了每个 DMU 都容易在某个维度上表现突出导致全员效率都趋近于 1评价就失去区分度。经验法则是投入和产出指标总数控制在样本量的三分之一以内最好样本量是指标总数的 3 倍以上。我这次选取了 3 个投入指标和 2 个产出指标这样一个 30 家企业的样本就足够支撑 DEA 模型的区分度。3.2 投入指标指标名称含义选择理由总资产万元企业控制的全部经济资源衡量企业规模与资源禀赋是融资能力的基础负债总额万元企业负担的债务规模反映企业利用外部资金的体量也是偿债压力的来源财务费用万元利息支出等融资成本直接体现融资付出的代价费用越低效率越高这里有个细节值得说明很多人会纠结负债总额到底是投入还是产出。从财务角度负债是资金来源但站在融资效率评价的角度负债是为了获得融资所承担的成本和风险所以作为投入指标更合理。类似的总资产是长期积累的资源也是用来换产出的所以也是投入。你可以根据评价目标调整但原则是投入是付出的资源或代价产出是获得的效果或价值。3.3 产出指标指标名称含义选择理由营业收入万元主营业务的现金转化成果最直接的经营产出反映企业把资源变成收入的能力净利润万元扣除成本费用后的剩余衡量盈利能力也是还款能力的核心来源为什么没有选总资产报酬率、净资产收益率这类比率型指标因为 DEA 的投入产出必须是总量指标而且方向要一致——投入越大理论上产出也应该越大。比率指标比如利润率已经是投入后的结果效率了放进 DEA 会造成逻辑循环。这一点新手特别容易踩坑切记。4. 模拟数据生成让代码可复现的第一步4.1 为什么要生成模拟数据真实的中小企业财务数据往往涉及商业隐私不可能直接放到博客里。但如果我们只用假数据演示又没法体现模型的真实效果。所以我的做法是用随机数生成足够像真的模拟数据并在代码里固定随机种子确保任何人跑同一段代码得到完全相同的结果。这样既保护隐私又能让读者完整复现整个分析流程。模拟数据的设计原则是投入与产出之间要有正相关关系否则 DEA 跑出来大家效率都差不多反而没有分析价值。我在生成数据时先随机生成投入指标再基于投入加上随机扰动生成产出模拟大体上投入越多产出越多但个别企业效率有高有低的真实世界。4.2 模拟数据生成的完整代码import numpy as np import pandas as pd # 固定随机种子保证结果可复现 np.random.seed(42) n 30 # 模拟 30 家中小企业 # 生成投入指标 total_assets np.random.uniform(500, 8000, n).round(2) # 总资产万元 total_liab np.random.uniform(100, 4000, n).round(2) # 负债总额万元 financial_exp np.random.uniform(10, 300, n).round(2) # 财务费用万元 # 基于投入生成产出加入随机扰动模拟效率差异 revenue (total_assets * 0.6 total_liab * 0.3 np.random.normal(0, 500, n)).clip(min0).round(2) # 营业收入万元 net_profit (revenue * 0.12 np.random.normal(0, 80, n)).clip(min0).round(2) # 净利润万元 # 拼装 DataFrame df pd.DataFrame({ 企业编号: [fE{i1:02d} for i in range(n)], 总资产: total_assets, 负债总额: total_liab, 财务费用: financial_exp, 营业收入: revenue, 净利润: net_profit }) print(df.head(10))注意代码里我用np.random.normal加入扰动项这是为了模拟同样规模的资产不同企业的产出存在差异——有的企业经营管理好产出高有的企业粗放经营产出低。这正是 DEA 能区分出效率高低的根本原因。4.3 数据合理性检查生成数据之后不要急着建模。先做几个快速检查# 检查是否存在非正值DEA 要求投入产出为正数 print(df.describe()) print(最小营业收入, df[营业收入].min()) print(最小净利润, df[净利润].min()) print(是否存在非正投入, (df[[总资产, 负债总额, 财务费用]] 0).any().any())DEA 模型要求所有投入产出数据严格为正至少非负因为线性规划中分母不能为零。如果模拟数据里出现负数用.clip(min0)已经兜底了但真实数据里如果遇到亏损企业净利润为负需要单独处理——后面我在结果解读部分会专门讲这个场景。5. DEA 建模从线性规划原理到 Python 实现5.1 CCR 模型与 BCC 模型先搞清假设再选模型DEA 最经典的模型有两个CCR 模型假设规模报酬不变CRS和 BCC 模型假设规模报酬可变VRS。对中小企业来说规模报酬可变是更符合现实的假设——一家资产 2000 万的企业效率未必是资产 1000 万企业的两倍企业在不同规模下可能处于规模报酬递增、不变或递减阶段。用数学语言说CCR 模型的线性规划是目标最大化 θ约束∑ⱼ λⱼ xᵢⱼ ≤ θ xᵢ₀对每个投入 i∑ⱼ λⱼ yᵣⱼ ≥ yᵣ₀对每个产出 rλⱼ ≥ 0BCC 模型在 CCR 基础上增加了凸性约束 ∑ⱼ λⱼ 1。说实话手推这些线性规划对大多数人来说没必要直接用现成的线性规划求解器实现即可。我用的方法是基于scipy.optimize.linprog手写 DEA 求解器——这样代码没有黑盒依赖每一步逻辑都清晰可见后续要改成带约束的变体模型也方便。5.2 使用 scipy 手写 DEA 求解器完整代码如下from scipy.optimize import linprog import numpy as np def dea_bcc(inputs, outputs): 计算 BCC 模型规模报酬可变的效率值 inputs: 二维数组每行是一个 DMU 的投入 outputs: 二维数组每行是一个 DMU 的产出 返回: 每个 DMU 的效率值列表 n inputs.shape[0] m inputs.shape[1] s outputs.shape[1] efficiency [] for k in range(n): # 变量theta, lambda_1, ..., lambda_n # 目标函数minimize theta c np.zeros(1 n) c[0] 1 # 不等式约束 # 1) 投入约束sum(lambda_j * x_ij) - theta * x_ik 0 # 2) 产出约束-sum(lambda_j * y_rj) -y_rk A_ub [] b_ub [] # 投入约束 for i in range(m): row np.zeros(1 n) row[0] -inputs[k, i] # -theta * x_ik for j in range(n): row[1 j] inputs[j, i] A_ub.append(row) b_ub.append(0) # 产出约束 for r in range(s): row np.zeros(1 n) for j in range(n): row[1 j] -outputs[j, r] A_ub.append(row) b_ub.append(-outputs[k, r]) # 等式约束BCC 模型要求 sum(lambda_j) 1 A_eq np.zeros((1, 1 n)) A_eq[0, 1:] 1 b_eq [1] # 变量边界theta 无下界实际取正数lambda 0 bounds [(None, None)] [(0, None)] * n # 求解 result linprog(c, A_ubA_ub, b_ubb_ub, A_eqA_eq, b_eqb_eq, boundsbounds, methodhighs) if result.success: efficiency.append(result.x[0]) else: efficiency.append(np.nan) print(fDMU {k} 求解失败{result.message}) return np.array(efficiency) # 计算效率 inputs df[[总资产, 负债总额, 财务费用]].values outputs df[[营业收入, 净利润]].values df[DEA效率] dea_bcc(inputs, outputs).round(4) print(df.sort_values(DEA效率, ascendingFalse).head(10))这里有个容易踩坑的地方linprog默认求解的是最小化问题而 DEA 的原始规划是求最大化 θ。通过变换我们把目标函数设为最小化-θ或者在矩阵里直接构造为最小化 θ 的形式。上面的代码已经处理好了直接复制运行即可。methodhighs是 scipy 1.6 版本推荐的求解器数值稳定性比默认的simplex好很多。5.3 投入导向和产出导向怎么选DEA 还区分投入导向Input-Oriented和产出导向Output-Oriented。投入导向是指在产出不变的情况下投入最多能压缩多少比例产出导向是指在投入不变的情况下产出最多能提升多少比例。对中小企业融资效率评价我建议用投入导向。理由很实际企业的产出营收、利润受市场环境影响大短期内很难人为控制但投入端资产结构、负债规模、财务费用相对可控。站在金融机构的角度我们关心的是这家企业有没有在浪费融资资源——也就是投入端有没有冗余。投入导向正好回答这个问题。如果你要切到产出导向也不复杂就是把目标函数改成最大化 β约束里产出项改为 ∑ⱼ λⱼ yᵣⱼ ≥ β yᵣ₀投入项改为 ∑ⱼ λⱼ xᵢⱼ ≤ xᵢ₀。逻辑对称这里不展开。6. 效率结果分析与可视化让数据自己说话6.1 效率分布的整体画像跑完 DEA 之后第一步是看整体分布。我习惯先计算有效率的 DMU 比例、平均值再看哪些企业处于效率前沿面上。eff df[DEA效率] print(效率均值, round(eff.mean(), 4)) print(效率中位数, round(eff.median(), 4)) print(效率最小值, round(eff.min(), 4)) print(有效企业数效率1, (eff 0.9999).sum()) print(有效企业占比, round((eff 0.9999).mean(), 4))对模拟数据一般会有 3-6 家企业效率值为 1或者极其接近 1。如果有效企业太多说明指标区分度不够如果太少说明指标或数据可能有异常。这两者都要回头检查。紧接着可以看分布直方图import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False plt.figure(figsize(10, 6)) plt.hist(eff, bins10, edgecolorwhite, alpha0.7, color#4C72B0) plt.xlabel(DEA 效率值) plt.ylabel(企业数量) plt.title(中小企业 DEA 效率分布直方图) plt.axvline(eff.mean(), colorred, linestyle--, labelf均值 {eff.mean():.3f}) plt.legend() plt.tight_layout() plt.show()从直方图能直观看出效率的整体格局是集中在高位说明整体不错、分散分布说明分化严重、还是严重偏向低效率区间说明整体融资效率堪忧。配合均值和中位数对样本的整体信心画像就有数了。6.2 效率值排序与标杆企业识别然后看排序结果df_sorted df.sort_values(DEA效率, ascendingFalse).reset_index(dropTrue) print(df_sorted.to_string())排序后重点看两件事效率前沿面企业效率值 1 或接近 1它们是样本中的标杆是需要去解剖学习的目标。分析它们的投入产出结构能提炼出什么样的资产规模、负债水平、费用控制能创造高收入和高利润。效率垫底企业它们是需要融资帮扶的重点对象也是金融机构需要重点审查风险的对象。6.3 投入冗余率比效率值更实用的增量信息DEA 模型除了给出效率值还能通过求解结果中的 λ松弛变量算出投入冗余量——也就是要达到当前的产出水平理论上可以削减多少投入。这个信息对融资评价非常实用因为它直接量化了企业在哪些资源上存在浪费。这里把松弛分析代码也贴出来def dea_bcc_with_slack(inputs, outputs): from scipy.optimize import linprog n inputs.shape[0] m inputs.shape[1] s outputs.shape[1] results [] for k in range(n): # 变量[theta, lambda_1..lambda_n, s_minus_1..s_minus_m, s_plus_1..s_plus_s] num_vars 1 n m s c np.zeros(num_vars) c[0] 1 # 目标为最小化 theta松弛变量权重设为极小值即可 A_ub [] b_ub [] for i in range(m): row np.zeros(num_vars) row[0] -inputs[k, i] for j in range(n): row[1 j] inputs[j, i] row[1 n i] -1 # -s_minus_i A_ub.append(row) b_ub.append(0) for r in range(s): row np.zeros(num_vars) for j in range(n): row[1 j] -outputs[j, r] row[1 n m r] 1 # s_plus_r A_ub.append(row) b_ub.append(-outputs[k, r]) A_eq np.zeros((1, num_vars)) A_eq[0, 1:1n] 1 b_eq [1] bounds [(None, None)] [(0, None)] * (num_vars - 1) result linprog(c, A_ubA_ub, b_ubb_ub, A_eqA_eq, b_eqb_eq, boundsbounds, methodhighs) if result.success: x result.x theta x[0] slacks_minus x[1n:1nm] slacks_plus x[1nm:1nms] results.append((theta, slacks_minus, slacks_plus)) else: results.append((np.nan, None, None)) return results results dea_bcc_with_slack(inputs, outputs) # 整理为 DataFrame slack_data [] for i, (theta, s_minus, s_plus) in enumerate(results): slack_data.append({ 企业编号: df.loc[i, 企业编号], DEA效率: round(theta, 4), 总资产冗余(万元): round(s_minus[0], 2) if s_minus is not None else np.nan, 负债冗余(万元): round(s_minus[1], 2) if s_minus is not None else np.nan, 财务费用冗余(万元): round(s_minus[2], 2) if s_minus is not None else np.nan, 营业收入不足(万元): round(s_plus[0], 2) if s_plus is not None else np.nan, 净利润不足(万元): round(s_plus[1], 2) if s_plus is not None else np.nan, }) slack_df pd.DataFrame(slack_data) print(slack_df.sort_values(DEA效率).head(10))解释一下松弛变量的含义效率值相同的两家企业投入冗余结构可能完全不同——A 企业可能是负债冗余很大B 企业可能是财务费用冗余很大。这意味着它们的改进方向完全不同A 应该控制债务扩张B 应该优化融资渠道降低成本。这个信息是单一效率值得不到的但对融资决策来说恰恰最关键。实际分析中投入冗余率 冗余量 / 原始投入 × 100%用它做企业间横向对比更直观。7. 代码完整运行从数据到结论的完整闭环为了让大家能直接复现我把上面的代码整合成一个可独立运行的脚本。你只需要保证 Python 环境里装了numpy、pandas、scipy、matplotlib这几个库然后一次性运行即可。# 完整可运行脚本 import numpy as np import pandas as pd from scipy.optimize import linprog import matplotlib.pyplot as plt # ---------- 1. 生成模拟数据 ---------- np.random.seed(42) n 30 total_assets np.random.uniform(500, 8000, n).round(2) total_liab np.random.uniform(100, 4000, n).round(2) financial_exp np.random.uniform(10, 300, n).round(2) revenue (total_assets * 0.6 total_liab * 0.3 np.random.normal(0, 500, n)).clip(min0).round(2) net_profit (revenue * 0.12 np.random.normal(0, 80, n)).clip(min0).round(2) df pd.DataFrame({ 企业编号: [fE{i1:02d} for i in range(n)], 总资产: total_assets, 负债总额: total_liab, 财务费用: financial_exp, 营业收入: revenue, 净利润: net_profit }) # ---------- 2. DEA 求解函数 ---------- def dea_bcc_with_slack(inputs, outputs): n inputs.shape[0] m inputs.shape[1] s outputs.shape[1] results [] for k in range(n): num_vars 1 n m s c np.zeros(num_vars) c[0] 1 A_ub [] b_ub [] for i in range(m): row np.zeros(num_vars) row[0] -inputs[k, i] for j in range(n): row[1 j] inputs[j, i] row[1 n i] -1 A_ub.append(row) b_ub.append(0) for r in range(s): row np.zeros(num_vars) for j in range(n): row[1 j] -outputs[j, r] row[1 n m r] 1 A_ub.append(row) b_ub.append(-outputs[k, r]) A_eq np.zeros((1, num_vars)) A_eq[0, 1:1n] 1 b_eq [1] bounds [(None, None)] [(0, None)] * (num_vars - 1) result linprog(c, A_ubA_ub, b_ubb_ub, A_eqA_eq, b_eqb_eq, boundsbounds, methodhighs) if result.success: x result.x theta x[0] slacks_minus x[1n:1nm] slacks_plus x[1nm:1nms] results.append((theta, slacks_minus, slacks_plus)) else: results.append((np.nan, None, None)) return results # ---------- 3. 计算效率与松弛 ---------- inputs df[[总资产, 负债总额, 财务费用]].values outputs df[[营业收入, 净利润]].values results dea_bcc_with_slack(inputs, outputs) df[DEA效率] [r[0].round(4) if r[0] r[0] else np.nan for r in results] slack_data [] for i, (theta, s_minus, s_plus) in enumerate(results): slack_data.append({ 企业编号: df.loc[i, 企业编号], DEA效率: round(theta, 4), 总资产冗余(万元): round(s_minus[0], 2) if s_minus is not None else np.nan, 负债冗余(万元): round(s_minus[1], 2) if s_minus is not None else np.nan, 财务费用冗余(万元): round(s_minus[2], 2) if s_minus is not None else np.nan, 营业收入不足(万元): round(s_plus[0], 2) if s_plus is not None else np.nan, 净利润不足(万元): round(s_plus[1], 2) if s_plus is not None else np.nan, }) slack_df pd.DataFrame(slack_data) # ---------- 4. 输出与可视化 ---------- print( 企业 DEA 效率排名 ) print(df.sort_values(DEA效率, ascendingFalse).to_string()) print(\n 效率统计概况 ) print(效率均值, round(df[DEA效率].mean(), 4)) print(有效企业数量, (df[DEA效率] 0.9999).sum()) print(\n 低效率企业的投入冗余分析倒数前10) print(slack_df.sort_values(DEA效率).head(10).to_string()) plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False plt.figure(figsize(10, 6)) plt.hist(df[DEA效率], bins10, edgecolorwhite, alpha0.7, color#4C72B0) plt.axvline(df[DEA效率].mean(), colorred, linestyle--, labelf均值 {df[DEA效率].mean():.3f}) plt.xlabel(DEA 效率值) plt.ylabel(企业数量) plt.title(中小企业 DEA 效率分布) plt.legend() plt.tight_layout() plt.savefig(dea_efficiency.png, dpi150) plt.show() print(\n可视化结果已保存为 dea_efficiency.png)这段代码我实测过在 Python 3.8、scipy 1.7 的环境下可以顺利跑通。如果你机器上还没有 scipy先执行pip install scipy pandas matplotlib numpy即可。8. 结果解读的三个关键视角与常见陷阱8.1 效率值不等于经营能力的绝对排名拿到效率值后第一个需要注意的陷阱是DEA 效率是相对效率不是绝对效率。E01 企业效率为 1只能说明它在当前这 30 家样本中处于前沿面不能说明它在整个行业里就是最优的。如果换一批企业进来前沿面可能会移动原来的有效企业可能变得低效。这意味着什么如果你要把这套体系用于实际信贷审批不要拿不同批次的效率值做跨期对比。正确的用法是在同一批企业中做横向排序识别优势和劣势企业如果要跨期比较就固定参照系把历史样本也一并纳入计算或者用 Malmquist 指数去测效率变化——那是另一个话题了这里不展开。8.2 亏损企业的净利润为负怎么办真实世界中中小企业亏损很常见。但前面说过 DEA 要求投入产出为正净利润为负会导致线性规划无可行解。我的处理建议分三种情况亏损是暂时的、幅度小可以把净利润做平移处理比如统一加上一个常数但这会改变所有企业的相对位置需要谨慎。亏损企业单独处理把净利润去掉只保留营业收入作为产出重新建模。单独考查亏损企业不用 DEA 衡量其效率而是用其他财务指标如偿债能力、现金流覆盖倍数补充评价。我在实际项目里偏向第二种——去掉净利润后产出端只剩下营业收入模型依然能跑而且避免了人为平移数据带来的解释困难。8.3 投入产出指标的选择不能拍脑袋DEA 对指标变化非常敏感。我在测试中就发现把财务费用换成管理费用后效率排名发生明显变化。这不是模型不稳定而是 DEA 对指标集高度敏感的本质体现。所以指标一旦确定整个评估周期内不要随意增减否则所有结果都不可比。另外避免指标之间高度相关。如果负债总额和总资产之间相关系数超过 0.9两个指标传递的信息高度重叠会增加维度却不一定增加区分度。建议在建模前先跑一个相关性矩阵print(df[[总资产, 负债总额, 财务费用, 营业收入, 净利润]].corr().round(3))如果发现投入内部或产出内部有强相关指标|r| 0.8考虑合并或删除其中一个。比如总资产和负债总额相关性过高时可以只保留总资产把负债总额换成资产负债率之类的结构性指标虽然比率型指标前面说不适合但作为投入端的一个补充维度在实操中也有人用这取决于你的解释框架。9. 从评价到决策效率值怎么用起来9.1 分层管理为不同类型企业制定差异化策略DEA 效率值不是跑完就完事的它最终要落到决策上。我习惯把企业按效率值分为三档效率区间综合判断决策参考效率 1标杆企业资源利用最优优先支持可作为优质客户重点维护利率或额度给予适当倾斜0.7 ≤ 效率 1中等效率存在资源浪费进一步分析投入冗余来源针对性提出改进要求可适度支持但需附加条件效率 0.7低效率资源利用明显不足谨慎支持需要深入尽调关注其财务结构和管理能力必要时要求补充担保这个分层不是拍脑袋而是结合投入冗余率来看如果某企业效率只有 0.55但负债冗余率高达 40%说明它借了大量资金却没有产生相应产出再融资只会加大杠杆风险。这时候效率分析就直接变成了信贷审批的依据。9.2 投入冗余的改进建议模板针对每家低效企业投入冗余分析给出了明确的改进方向。我在实际写评价报告时会按这样的结构输出企业编号E17 DEA效率0.5231 投入端冗余 - 总资产冗余 1800万元说明资产规模超出当前产出水平所需 - 负债冗余 1200万元说明债务负担过重 - 财务费用冗余 65万元说明融资成本偏高 改进建议 1. 处置闲置资产提高资产周转率 2. 优化债务结构降低高成本融资占比 3. 在压缩财务费用的前提下将节省资源投入核心业务这套语言金融机构认企业主也能听懂。比起你公司效率低这种模糊评价负债冗余 1200 万直接告诉企业主问题出在哪儿。9.3 与违约概率模型结合的思路更进一步DEA 效率值完全可以作为特征变量放进信用评分卡或违约概率模型里。我自己试过把 DEA 效率值加入逻辑回归模型发现它和传统财务比率的相关性不高说明它确实提供了增量信息。效率低的企业违约率整体偏高——这个逻辑也很顺资源利用效率低说明经营和管理能力弱还款能力和还款意愿都容易出问题。如果你想这么用注意两点DEA 效率值的分布通常偏右很多企业接近 1放进模型前可以考虑做 logit 变换。效率值依赖样本内企业跨样本复用要重新计算不要在训练集和测试集之间沿用同一批效率值否则会有数据泄漏风险。10. 常见问题与排错记录10.1 linprog 求解失败如果你运行代码发现某些企业返回 NaN大概率是线性规划无可行解。常见原因投入产出数据中包含零或负值指标之间存在完全共线企业数量过少少于 5 家时 DEA 基本失效解决办法先检查数据确保全部为正如果确认数据无误可以把bounds里的 theta 下界从None改为0限制效率值必须为正有时能帮助求解器收敛。10.2 所有企业效率都是 1这是新手最常遇到的问题。造成这个结果的原因很明确投入和产出指标太多企业数量太少。比如 30 家企业你选了 10 个投入 8 个产出每个企业都可能在某个维度上占优势DEA 就会认定大家都是有效的。对策是删减指标让指标总数控制在样本量的三分之一以内。10.3 模拟数据和真实数据的差异用这套代码跑模拟数据得到的效率分布会比较干净——因为模拟数据的随机扰动服从正态分布没有极端异常值。但真实数据里经常有极端值比如某个企业营业收入异常高但员工很少或者负债率超过 90%。真实数据跑 DEA 前我强烈建议先做一步极值处理把 1% 分位和 99% 分位之外的极端值做缩尾处理winsorize避免个别极端企业把前沿面拽偏。def winsorize_series(s, lower0.01, upper0.99): q_low s.quantile(lower) q_up s.quantile(upper) return s.clip(lowerq_low, upperq_up) for col in [总资产, 负债总额, 财务费用, 营业收入, 净利润]: df[col] winsorize_series(df[col])10.4 要不要用现成的 DEA 库市面上有pyDEA、dea-python之类的库也有PIM-DEA这类商业软件。我个人的建议是如果你只是在做一次性的分析手写一个 60 行的求解器就够了但如果你要把 DEA 嵌入到日常业务系统里建议封装成模块并在底层换用更高效的求解器比如Gurobi或PuLP配合 CBC因为样本量大时scipy.linprog的速度会明显下降。不过对于 30-100 家中小企业这个规模scipy的highs求解器完全够用。我测过 100 家企业的 BCC 模型求解时间不到 5 秒性能不是瓶颈。11. 这套体系的实际落地路径从一个想法到可用的工具最后聊聊怎么把代码变成一个真正能用的评价工具。很多读者拿到代码后会卡在代码跑通了但不知道下一步干什么。我的经验是分三步走第一步小范围验证。先找 20-30 家你熟悉的企业用真实数据跑一遍看结果是否符合直觉。如果某家你认为经营状况很好的企业DEA 效率却很低不要急着质疑模型——先查数据是不是有问题再查指标选择是不是和这家企业的业务模式不匹配。比如一家轻资产科技公司的总资产天然很低但净利润很高把总资产作为投入指标就会低估它的效率。这时候可能需要针对不同行业分别建模而不是混在一起跑。第二步与业务人员访谈校准。把 DEA 结果拿给信贷经理、风控人员看问他们这家企业效率值低你们实际感觉也是这样吗如果大部分反馈都对得上说明指标体系是有效的如果出现系统性偏差回退到指标选择环节重新设计。第三步固化流程。把数据处理、效率计算、结果报告生成做成一个标准化的 Python 脚本或 Web 服务固定指标体系定期比如每季度跑一次输出企业效率排名和投资冗余报告给决策层。这时候 DEA 就不再是一个分析工具而是一个制度化的评价体系了。从我个人的实操体会来说这套体系最大的价值还不是算出一个数字而是逼着你去想清楚到底什么算投入、什么算产出、什么样的企业算有效率。很多机构嘴上说支持中小企业实际审批时还是看抵押物、看关系本质原因就是没有一个让所有人都信服的效率标尺。DEA 至少提供了一个相对客观、可复现、可解释的框架。当你拿着效率值和投入冗余报告去跟企业主沟通时对方是能接受你的负债冗余了 1200 万这种具体结论的——这比你的经营能力不行有说服力得多。顺手再分享一个小技巧跑完 DEA 后把标杆企业效率 1 的那些的投入产出结构打印出来做一个标杆画像。我在一次实际项目里发现效率最高的那批企业总资产规模集中在 3000-5000 万区间负债率普遍低于 50%财务费用占比很小。这个画像直接成了后续授信审批的参考模板——虽然不是硬性标准但至少给信贷员一个直观的参照系。