【问题标题】:Strange Results with Numeric Predictor in Naive Bayes in RR中朴素贝叶斯中数值预测器的奇怪结果
【发布时间】:2014-11-11 21:29:58
【问题描述】:

更新:

以下代码应该是可重现的

someFrameA = data.frame(label="A", amount=rnorm(10000, 100, 20))
someFrameB = data.frame(label="B", amount=rnorm(1000, 50000, 20))
wholeFrame = rbind(someFrameA, someFrameB)
fit <- e1071::naiveBayes(label ~ amount, wholeFrame)
wholeFrame$predicted = predict(fit, wholeFrame)
nrow(subset(wholeFrame, predicted != label))

在我的例子中,这给出了 243 个错误分类。

注意这两行: (行数、标签、数量、预测)

10252     B 50024.81895         A
2955      A   100.55977         A
10678     B 50010.26213         B

虽然输入仅与 12.6 不同,但分类发生了变化。奇怪的是,像这样的行的后验概率如此接近:

> predict(fit, wholeFrame[10683, ], type="raw")
             A         B
[1,] 0.5332296 0.4667704

原问题:

我正在尝试使用交易金额对一些银行交易进行分类。我的原始模型中有许多其他基于文本的特征,但在仅使用数字模型时发现了一些可疑之处。

> head(trainingSet)
                 category amount
1                   check 688.00
2 non-businesstransaction   2.50
3 non-businesstransaction  36.00
4 non-businesstransaction 243.22
5                 payroll 302.22
6 non-businesstransaction  16.18

fit <- e1071::naiveBayes(category ~ amount, data=trainingSet)
fit

离散预测变量的朴素贝叶斯分类器

调用: naiveBayes.default(x = X, y = Y, laplace = laplace)

A-priori probabilities:
Y
                bankfee                   check       creditcardpayment       e-commercedeposit               insurance 
            0.029798103             0.189613233             0.054001459             0.018973486             0.008270494 
      intrabanktransfer             loanpayment              mcapayment non-businesstransaction                     nsf 
            0.045001216             0.015689613             0.011432741             0.563853077             0.023351982 
                  other                 payroll              taxpayment          utilitypayment 
            0.003405497             0.014838239             0.005716371             0.016054488 

Conditional probabilities:
                         amount
Y                               [,1]        [,2]
  bankfee                  103.58490   533.67098
  check                    803.44668  2172.12515
  creditcardpayment        819.27502  2683.43571
  e-commercedeposit         42.15026    59.24806
  insurance                302.16500   727.52321
  intrabanktransfer       1795.54065 11080.73658
  loanpayment              308.43233   387.71165
  mcapayment               356.62755   508.02412
  non-businesstransaction  162.41626   951.65934
  nsf                       44.92198    78.70680
  other                   9374.81071 18074.36629
  payroll                 1192.79639  2155.32633
  taxpayment              1170.74340  1164.08019
  utilitypayment           362.13409  1064.16875

根据 e1071 文档,“条件概率”的第一列是数值变量的平均值,另一列是标准差。这些均值和标准差是正确的,先验概率也是正确的。

所以,这行令人不安:

> thatRow
   category   amount
40    other 11268.53

收到这些后验:

> predict(fit, newdata=thatRow, type="raw")
          bankfee       check creditcardpayment e-commercedeposit    insurance intrabanktransfer   loanpayment    mcapayment
[1,] 4.634535e-96 7.28883e-06      9.401975e-05         0.4358822 4.778703e-51        0.02582751 1.103762e-174 1.358662e-101
     non-businesstransaction       nsf       other      payroll   taxpayment utilitypayment
[1,]            1.446923e-29 0.5364704 0.001717378 1.133719e-06 2.059156e-18   2.149142e-24

请注意,“nsf”的得分大约是“other”的 300 倍。由于这笔交易的金额为 11200 美元,如果按照“nsf”分布,它将与平均值相差 100 多个标准差。同时,由于“其他”交易的样本均值约为 9k 美元,标准差较大,我认为该交易更可能是“其他”交易。虽然“nsf”更可能是先验概率,但它们的差异并没有超过尾部观察,并且除了“其他”之外还有很多其他可行的候选者。

我假设这个包只是查看了 normal(mew=samplemean, stdev=samplestdev) pdf 并使用该值进行乘法,但事实并非如此吗?我不太清楚如何查看源代码。

数据类型似乎也不错:

> class(trainingSet$amount)
[1] "numeric"
> class(trainingSet$category)
[1] "factor"

打印输出中的“离散预测变量的朴素贝叶斯分类器”可能很奇怪,因为这是一个连续预测变量,但我认为这个包可以处理连续预测变量。

我使用 klaR 包得到了类似的结果。也许我需要为此设置内核选项?

【问题讨论】:

  • 如果您只是不知道如何查看 R 函数的源代码,this question 应该会有所帮助。否则,您发布的信息不足以充当reproducible example。包含足够的信息(数据),以便我们可以产生与您相同的结果(这并不意味着我们需要整个数据集,只需要一个子集,以便我们可以处理与您相同的数据以获得相同的错误)。

标签: r machine-learning classification


【解决方案1】:

阈值参数是其中很大一部分。包里的代码有点像这样:

 L <- sapply(1:nrow(newdata), function(i) {
        ndata <- newdata[i, ]
        L <- log(object$apriori) + apply(log(sapply(seq_along(attribs),
            function(v) {
                nd <- ndata[attribs[v]]
                if (is.na(nd)) rep(1, length(object$apriori)) else {
                  prob <- if (isnumeric[attribs[v]]) {
                    msd <- object$tables[[v]]
                    msd[, 2][msd[, 2] <= eps] <- threshold
                    dnorm(nd, msd[, 1], msd[, 2])
                  } else object$tables[[v]][, nd]
                  prob[prob <= eps] <- threshold
                  prob
                }

阈值(并且此已记录)将替换任何小于 eps 的概率。因此,如果连续变量的正常 pdf 为 0.000000000,则默认为 0.001。

> wholeFrame$predicted = predict(fit, wholeFrame, threshold=0.001)
> nrow(subset(wholeFrame, predicted != label))
[1] 249
> wholeFrame$predicted = predict(fit, wholeFrame, threshold=0.0001)
> nrow(subset(wholeFrame, predicted != label))
[1] 17
> wholeFrame$predicted = predict(fit, wholeFrame, threshold=0.00001)
> nrow(subset(wholeFrame, predicted != label))
[1] 3

现在,我相信 sapply 返回的数量是不正确的,因为当“调试”它时,我得到了 .012 之类的东西,应该是 dnorm (49990, 100, 20),我认为有些东西会被遗漏/与均值和标准差矩阵混淆,但无论如何,设置阈值将对此有所帮助。

.001*(10/11) > pdfB*(1/11) 或由于这种情况导致 A 的后验高于 B 意味着 pdfB 必须偶然小于 0.01。

> dnorm(49977, 50000, 20)
[1] 0.01029681
> 2*pnorm(49977, 50000, 20)
[1] 0.2501439

由于 B 类有 1000 个观测值,我们应该预计会有大约 250 个错误分类,这与最初的 243 个非常接近。

【讨论】:

    猜你喜欢
    • 2012-03-24
    • 2018-02-12
    • 2012-11-22
    • 1970-01-01
    • 2016-07-29
    • 2015-05-22
    • 1970-01-01
    • 2011-04-08
    • 2015-11-19
    相关资源
    最近更新 更多