R中朴素贝叶斯数值预测因子的奇怪结果

时间:2014-09-17 18:07:27

标签: r machine-learning classification

更新

以下代码应该是可重现的

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文档,&#34;条件概率的第一列&#34;是数字变量的平均值,另一个是标准偏差。这些手段和标准是正确的,先验概率也是如此。

所以,这一行令人不安:

> 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

请注意&#34; nsf&#34;得分约为其他&#34;其他&#34;确实。由于这笔交易的金额为11.2万美元,如果要遵循这个&#34; nsf&#34;分布,它将与平均值相差超过100个标准偏差。同时,因为&#34;其他&#34;交易的样本均值约为9k美元,且标准偏差很大,我认为此交易更可能是一个&#34;其他&#34;。虽然&#34; nsf&#34;它更可能与之前的概率相比,它们不会超过尾部观察,并且还有很多其他可行的候选者除了&#34;其他&#34;同样。

我假设这个软件包只是查看了正常的(mew = samplemean,stdev = samplestdev)pdf并使用该值进行乘法,但情况并非如此?我无法弄清楚如何查看来源。

数据类型似乎也很好:

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

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

我的klaR包有类似的结果。也许我需要在那上面设置内核选项?

1 个答案:

答案 0 :(得分: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,则默认为.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)&gt; pdfB *(1/11)或由于这种情况而具有高于B的后者的A意味着pdfB必须小于.01。

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

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