SVM 等离散分类器的 ROC 曲线:为什么我们仍然称其为“曲线”?,不只是一个“点”吗?

机器算法验证 交叉验证 奥克
2022-01-18 05:45:16

在讨论中:how to generate a roc curve for binary classification,我认为混淆是“二元分类器”(即任何分离 2 个类的分类器)对于 Yang 来说是所谓的“离散分类器”(产生离散输出 0/1,如 SVM)而不是连续输出,如 ANN 或贝叶斯分类器......等等。所以,讨论是关于如何为“二元连续分类器”绘制 ROC,答案是输出是排序的由于输出是连续的,因此通过它们的分数,并且使用阈值来产生 ROC 曲线上的每个点。

我的问题是“二进制离散分类器”,例如 SVM,输出值为 0 或 1。所以 ROC 只产生一个点而不是曲线。我很困惑为什么我们仍然称它为曲线?!我们还能谈论门槛吗?特别是如何在 SVM 中使用阈值?如何计算 AUC?,交叉验证在这里有什么作用吗?

3个回答
  • 是的,有些情况下无法获得通常的接受者操作曲线,并且只存在一个点。

  • 可以设置 SVM,以便它们输出类成员概率。这些将是通常的值,阈值将被改变以产生接收器操作曲线
    那是你要找的吗?

  • ROC 中的步骤通常发生在少量测试用例上,而不是与协变量的离散变化有关(特别是,如果您选择离散阈值,那么您最终会得到相同的点,以便对于每个新点只有一个样本发生变化它的任务)。

  • 不断改变模型的其他(超)参数当然会产生一组特异性/敏感性对,从而在 FPR;TPR 坐标系中给出其他曲线。
    曲线的解释当然取决于产生曲线的变化。

这是 iris 数据集的“versicolor”类的常用 ROC(即请求概率作为输出):

  • FPR;TPR(γ = 1,C = 1,可变概率阈值):
    鹏

相同类型的坐标系,但 TPR 和 FPR 作为调谐参数 γ 和 C 的函数:

  • FPR;TPR(变化 γ,C = 1,概率阈值 = 0.5):
    伽玛

  • FPR;TPR(γ = 1,变化的 C,概率阈值 = 0.5):
    成本

这些情节确实是有意义的,但意义与通常的中华民国截然不同!

这是我使用的 R 代码:

svmperf <- function (cost = 1, gamma = 1) {
    model <- svm (Species ~ ., data = iris, probability=TRUE, 
                  cost = cost, gamma = gamma)
    pred <- predict (model, iris, probability=TRUE, decision.values=TRUE)
    prob.versicolor <- attr (pred, "probabilities")[, "versicolor"]

    roc.pred <- prediction (prob.versicolor, iris$Species == "versicolor")
    perf <- performance (roc.pred, "tpr", "fpr")

    data.frame (fpr = perf@x.values [[1]], tpr = perf@y.values [[1]], 
                threshold = perf@alpha.values [[1]], 
                cost = cost, gamma = gamma)
}

df <- data.frame ()
for (cost in -10:10)
  df <- rbind (df, svmperf (cost = 2^cost))
head (df)
plot (df$fpr, df$tpr)

cost.df <- split (df, df$cost)

cost.df <- sapply (cost.df, function (x) {
    i <- approx (x$threshold, seq (nrow (x)), 0.5, method="constant")$y 
    x [i,]
})

cost.df <- as.data.frame (t (cost.df))
plot (cost.df$fpr, cost.df$tpr, type = "l", xlim = 0:1, ylim = 0:1)
points (cost.df$fpr, cost.df$tpr, pch = 20, 
        col = rev(rainbow(nrow (cost.df),start=0, end=4/6)))

df <- data.frame ()
for (gamma in -10:10)
  df <- rbind (df, svmperf (gamma = 2^gamma))
head (df)
plot (df$fpr, df$tpr)

gamma.df <- split (df, df$gamma)

gamma.df <- sapply (gamma.df, function (x) {
     i <- approx (x$threshold, seq (nrow (x)), 0.5, method="constant")$y
     x [i,]
})

gamma.df <- as.data.frame (t (gamma.df))
plot (gamma.df$fpr, gamma.df$tpr, type = "l", xlim = 0:1, ylim = 0:1, lty = 2)
points (gamma.df$fpr, gamma.df$tpr, pch = 20, 
        col = rev(rainbow(nrow (gamma.df),start=0, end=4/6)))

roc.df <- subset (df, cost == 1 & gamma == 1)
plot (roc.df$fpr, roc.df$tpr, type = "l", xlim = 0:1, ylim = 0:1)
points (roc.df$fpr, roc.df$tpr, pch = 20, 
        col = rev(rainbow(nrow (roc.df),start=0, end=4/6)))

通常,来自 SVM 的预测标签给出,其中是 SVM 优化的超平面的权重,是 SVM 优化的截距。这也可以重写如下: y^y^=sign(wTx+b)wb

y^={0if  wTx+b<01otherwise

但是,如果我们引入一个阈值来控制阳性检测率,即 ηη

y^={0if  wTx+b<η1otherwise

通过改变,我们可以使用 SVM 生成 ROC,从而调整灵敏度和特异性率。η

例如,如果我们想在 python 中进行,我们可以使用阈值,如下所示。wbη

>>> from sklearn.svm import SVC
>>> model = SVC(kernel='linear', C=0.001, probability=False, class_weight='balanced')
>>> model.fit(X, y)
>>> # The coefficients w are given by
>>> w = list(model.coef_)
>>> # The intercept b is given by
>>> b = model.intercept_[0]
>>> y_hat = X.apply(lambda s: np.sum(np.array(s)*np.array(w))+b, axis=1)
>>> y_hat = (y_hat > eta).astype(float)

ROC 曲线绘制随协变量阈值(可能是连续的或离散的)而变化的特异性与敏感性。我认为您将协变量与响应混淆了,并且可能不完全理解 ROC 曲线是什么。如果协变量是连续的并且我们查看协变量连续变化的阈值,那么它肯定是一条曲线。如果协变量是离散的,您仍然可以将其绘制为连续阈值的函数。然后曲线将是平坦的,在与协变量的离散值相对应的阈值处上升(或下降)。所以这将适用于 SVM 和任何其他离散分类器。

关于 AUC,因为我们仍然有一个 ROC(估计的),我们仍然可以计算它下面的面积。我不确定你对交叉验证的问题有什么想法。在分类问题的上下文中,交叉验证用于获得分类器错误率的无偏或几乎无偏估计。所以它可以进入我们如何估计ROC上的点。