You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python绘制自定义阈值范围的MLP音频分类ROC曲线

自定义阈值范围绘制ROC曲线的实现方案

问题背景

我正在使用MLP进行音频分类,现有代码可正常绘制ROC曲线并获取各类别最优阈值,但无法针对用户自定义的阈值范围绘制ROC曲线,求实现方法。

原运行正常的代码如下:

# Compute ROC curve and ROC area for each class
fpr = dict()
tpr = dict()
roc_auc = dict()
optimal_idx = dict()
optimal_threshold = dict()
for i in range(num_labels):
        fpr[i], tpr[i], thres = roc_curve(Y_test[:, i], Y_pred[:, i])
        roc_auc[i] = auc(fpr[i], tpr[i])
        # print(thres)
        optimal_idx[i] = np.argmax(tpr[i] - fpr[i])
        optimal_threshold[i] = thres[optimal_idx[i]]
        print(f'Threshold value for class{i}:', optimal_threshold[i])
      
        # Compute micro-average ROC curve and ROC area
fpr["micro"], tpr["micro"], thres = roc_curve(Y_test.ravel(), Y_pred.ravel())
roc_auc["micro"] = auc(fpr["micro"], tpr["micro"])
  
    # Compute macro-average ROC curve and ROC area
    # First aggregate all false positive rates
all_fpr = np.unique(np.concatenate([fpr[i] for i in range(num_labels)]))

      # Then interpolate all ROC curves at this points
mean_tpr = np.zeros_like(all_fpr)
  
for i in range(num_labels):
      mean_tpr += np.interp(all_fpr, fpr[i], tpr[i])
    
    # Finally average it and compute AUC
mean_tpr /= num_labels

fpr["macro"] = all_fpr
tpr["macro"] = mean_tpr
roc_auc["macro"] = auc(fpr["macro"], tpr["macro"])
      # Plot all ROC curves
lw=2
plt.figure()
plt.plot(
      fpr["micro"],
      tpr["micro"],
      label="micro-average ROC curve (area = {0:0.2f})".format(roc_auc["micro"]),
      color="deeppink",
      linestyle=":",
      linewidth=4,)

plt.plot(
      fpr["macro"],
      tpr["macro"],
      label="macro-average ROC curve (area = {0:0.2f})".format(roc_auc["macro"]),
      color="navy",
      linestyle=":",
      linewidth=4,)
# from itertools import cycle
colors = cycle(["aqua", "darkorange", "cornflowerblue"])
for i, color in zip(range(num_labels), colors):
      plt.plot(
          fpr[i],
          tpr[i],
          color=color,
          lw=lw,
          label="ROC curve of class {0} (area = {1:0.2f})".format(i, roc_auc[i]),
      )

plt.plot([0, 1], [0, 1], "k--", lw=lw)
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 for MLP")
plt.legend(loc="lower right")
plt.show()

实现方法

核心逻辑是手动遍历自定义阈值,逐个计算对应的FPR和TPR,再用这些结果绘制ROC曲线,具体步骤如下:

1. 定义自定义阈值范围

可以用numpy生成指定区间的阈值数组,或者直接传入自定义的阈值列表:

import numpy as np

# 示例1:生成0.1到0.9,步长0.1的阈值
custom_thresholds = np.linspace(0.1, 0.9, 9)
# 示例2:直接传入自定义阈值列表
# custom_thresholds = [0.2, 0.4, 0.5, 0.7, 0.8]

2. 计算自定义阈值对应的FPR和TPR

遍历每个类别,针对自定义阈值逐一计算混淆矩阵,推导FPR和TPR:

from sklearn.metrics import confusion_matrix

fpr_custom = dict()
tpr_custom = dict()

for i in range(num_labels):
    y_true = Y_test[:, i]  # 当前类别的真实标签
    y_score = Y_pred[:, i]  # 当前类别的预测得分
    
    fpr_list = []
    tpr_list = []
    
    for thresh in custom_thresholds:
        # 根据阈值生成二分类预测标签
        y_pred = (y_score >= thresh).astype(int)
        # 计算混淆矩阵(TN, FP, FN, TP)
        tn, fp, fn, tp = confusion_matrix(y_true, y_pred).ravel()
        # 计算FPR和TPR(避免分母为0的情况)
        fpr = fp / (fp + tn) if (fp + tn) != 0 else 0.0
        tpr = tp / (tp + fn) if (tp + fn) != 0 else 0.0
        
        fpr_list.append(fpr)
        tpr_list.append(tpr)
    
    # 转换为numpy数组便于后续绘图和计算
    fpr_custom[i] = np.array(fpr_list)
    tpr_custom[i] = np.array(tpr_list)

3. 计算自定义阈值曲线的AUC(可选)

如果需要评估自定义阈值曲线的AUC,直接使用auc函数:

from sklearn.metrics import auc

roc_auc_custom = dict()
for i in range(num_labels):
    roc_auc_custom[i] = auc(fpr_custom[i], tpr_custom[i])

4. 绘制自定义阈值的ROC曲线

替换原绘图逻辑中的fpr和tpr为自定义计算的结果,还可以添加标记点突出阈值位置:

import matplotlib.pyplot as plt
from itertools import cycle

lw = 2
plt.figure(figsize=(8, 6))

colors = cycle(["aqua", "darkorange", "cornflowerblue"])
for i, color in zip(range(num_labels), colors):
    plt.plot(
        fpr_custom[i],
        tpr_custom[i],
        color=color,
        lw=lw,
        marker='o',  # 用圆点标记每个自定义阈值对应的点
        label=f"Custom ROC of class {i} (AUC = {roc_auc_custom[i]:0.2f})",
    )

# 绘制随机猜测的基准线
plt.plot([0, 1], [0, 1], "k--", lw=lw)
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 for MLP (Custom Thresholds)")
plt.legend(loc="lower right")
plt.show()

5. 微平均/宏平均的自定义阈值ROC(可选)

如果需要全局的微平均或宏平均曲线,逻辑如下:

  • 微平均:将所有样本的真实标签和预测得分拉平,再遍历自定义阈值计算全局FPR和TPR
  • 宏平均:对每个类别的自定义FPR和TPR取算术平均

示例微平均实现:

# 微平均自定义阈值ROC
y_true_flat = Y_test.ravel()
y_score_flat = Y_pred.ravel()

fpr_micro_custom = []
tpr_micro_custom = []

for thresh in custom_thresholds:
    y_pred_flat = (y_score_flat >= thresh).astype(int)
    tn, fp, fn, tp = confusion_matrix(y_true_flat, y_pred_flat).ravel()
    fpr = fp / (fp + tn) if (fp + tn) != 0 else 0.0
    tpr = tp / (tp + fn) if (tp + fn) != 0 else 0.0
    fpr_micro_custom.append(fpr)
    tpr_micro_custom.append(tpr)

fpr_micro_custom = np.array(fpr_micro_custom)
tpr_micro_custom = np.array(tpr_micro_custom)
roc_auc_micro_custom = auc(fpr_micro_custom, tpr_micro_custom)

# 绘制微平均曲线
plt.plot(
    fpr_micro_custom,
    tpr_micro_custom,
    color="deeppink",
    linestyle=":",
    linewidth=4,
    marker='s',
    label=f"Micro-average Custom ROC (AUC = {roc_auc_micro_custom:0.2f})"
)

内容的提问来源于stack exchange,提问作者A. Gehani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 08:10:35