ROC曲线应用于朴素贝叶斯分类器python的理解

Posted

技术标签:

【中文标题】ROC曲线应用于朴素贝叶斯分类器python的理解【英文标题】:Understanding of ROC Curve applied to Naive Bayesian Classifier python 【发布时间】:2016-02-02 14:48:20 【问题描述】:

我是机器学习的新手,我目前正在尝试在 Python 3.4 中实现 ROC 曲线,该曲线应用于朴素贝叶斯分类器。分类器的实际代码在此处给出:

from __future__ import division
from collections import defaultdict
from math import log

def train(samples):
    classes, freq = defaultdict(lambda:0), defaultdict(lambda:0)
    for feats, label in samples:
        classes[label] += 1                 # count classes frequencies
        for feat in feats:
            freq[label, feat] += 1          # count features frequencies

    for label, feat in freq:                # normalize features frequencies
        freq[label, feat] /= classes[label]
    for c in classes:                       # normalize classes frequencies
        classes[c] /= len(samples)

    return classes, freq                    # return P(C) and P(O|C)

def classify(classifier, feats):
    classes, prob = classifier
    return min(classes.keys(),              # calculate argmin(-log(C|O))
        key = lambda cl: -log(classes[cl]) + \
            sum(-log(prob.get((cl,feat), 10**(-7))) for feat in feats))

例如,我有一些包含与性别相关的名称的数据,我想将我的分类器应用于此类数据以预测给定名称的性别。 这里还有一些代码:

def get_features(sample): return (sample[-1],) # get last letter

samples = (line.split() for line in open('names.txt'))
features = [(get_features(feat), label) for feat, label in samples]
classifier = train(features)

print 'gender: ', classify(classifier, get_features('Mary'))

好的,所以我坚持在那里构建 ROC 曲线。也许是因为我对分类器的一些基本概念有误解,其实我很失望。 使用我的分类器,我可以预测给定名称的“类”,作为值的 argmin (-log((C|O)),因为它是在上面的代码中编写的,所以函数 classify 在调用时会在类中搜索对于与给定名称相关的所有特征,对数的值将是最小值 - 这在朴素贝叶斯分类器的定义中完全指定。

接下来,我想为这个分类器构建 ROC 曲线,但问题是我的 classify 函数返回一个二进制值,它实际上通过计算 argmin 来显示给定人的预测性别,正如我之前所说的。 我需要一种threshold 值,它必须与classify 函数结果进行比较才能绘制ROC 曲线,可以更改+/- 以获得几个(TPR,FPR)点。

请帮我消除这种不幸的误解,以便我可以建立我的 ROC 曲线。

【问题讨论】:

【参考方案1】:

Receiver operating characteristic (ROC) 用于说明二元(两类)分类器的性能。因此,对于一条曲线,您必须将自己限制为两个类(X 与 Y 或 X 与非 X)(但您可以重复为其他成对的类生成曲线)。

您可以使用值 prob(C1|O) 而不是查找 -log prob(C|O) 最小的类 C(假设它们在数据样本的行之间以相同的方式标准化)。

然后,您可以扫描阈值 t,如果 prob(C1|O) >= t,则决定将一行归为 C1 类。

对于每个 t 你可以计算

真阳性率:实际属于 C1 类的行的分数,因为 prob(C1|O) >= t 会被归类为 C1 误报率:不属于 C1 类但由于 prob(C1|O) >= t 而被归类为 C1 的行的比例

在实践中,您只需要测试您在数据样本的行上获得的值 prob(C1|O) (在您的示例中,我希望得到类似 2**(特征数)的不同值)。

【讨论】:

以上是关于ROC曲线应用于朴素贝叶斯分类器python的理解的主要内容,如果未能解决你的问题,请参考以下文章

R语言应用实战系列-朴素贝叶斯算法以及ROC和PR曲线

朴素贝叶斯算法以及ROC和PR曲线

在单个 ROC 图上绘制线性判别分析、分类树和朴素贝叶斯曲线

python基于朴素贝叶斯模型的预测概率和标签信息可视化ROC曲线

Pyspark 中朴素贝叶斯分类器的阈值是啥?

label_binarize 不适合显示错误输入形状的 sklearn 朴素贝叶斯分类器