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

时间:2015-11-02 16:30:19

标签: python machine-learning roc naivebayes

我是机器学习的新手,我目前正在尝试在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曲线。也许是因为我对分类器的一些基本概念的误解,实际上我完全失望了。 使用我的分类器,我可以预测' class'对于给定的名称,作为值的argmin(-log((C | O)),因为它在上面的代码中编写,所以函数classify在被调用时搜索该类的值对于与给定名称相关的所有特征,对数将是最小的 - 这是在Naive Bayes分类器的定义中准确指定的。

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

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

1 个答案:

答案 0 :(得分:0)

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

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

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

对于每个t,你可以计算

  • 真正的正率:实际在C1类中的行的分数,并且因为prob(C1 | O)> = t
  • 将被归类为属于C1的行
  • 假阳性率:不属于C1类但由于概率(C1 | O)> = t
  • 而被归类为属于C1的行的分数

在实践中,你只需要测试数据样本中你得到的值prob(C1 | O)为t(在你的例子中,我希望得到类似于2 **(特征数)的东西)值)。