2014-01-16 11 views
6

Naive Bayes Classifierをドキュメント用語行列と連携させるのは非常に厄介な問題です。私は非常に単純な間違いをしていると確信していますが、それが何であるか把握することはできません。私のデータはアカウントスプレッドシートからのものです。私はどのカテゴリ(テキスト形式:主に部門名や予算名)が慈善団体に費やす可能性が高く、民間企業に費やすのはどれだけ(または唯一の)ものなのかを尋ねられました。彼らはNaive Bayes分類器を使ってこれを行うことを提案しました。私はモデルを訓練するために何千ものデータ行とモデルをテストするために数十万行を持っています。私は文字列を準備し、スペースをアンダースコアとands/&の+に置き換えて、それぞれのカテゴリを1つの用語として扱いました。したがって、 'アルコールと薬物中毒'は、アルコール+薬物_addictionになります。Naive Bayesのドキュメント用語行列classfier:予期せぬ結果R

いくつかの例行:

"environment+housing strategy+commissioning third_party_payments supporting_ppl_block_gross_chargeable" -> This row went to a charity 
"west_north_west customer+tenancy premises h.r.a._special_maintenance" -> This row went to a private company. 

テンプレートとしてthis exampleを使用して、私は、両方のトレーニングとテストデータのために(TMを使用して)私の文書の用語行列を思い付くするには、次の関数を書きました。

library(tm) 
library(e1071) 

getMatrix <- function(chrVect){ 
    testsource <- VectorSource(chrVect) 
    testcorpus <- Corpus(testsource) 
    testcorpus <- tm_map(testcorpus,stripWhitespace) 
    testcorpus <- tm_map(testcorpus, removeWords,stopwords("english")) 
    testmatrix <- t(TermDocumentMatrix(testcorpus)) 
} 

trainmatrix <- getMatrix(traindata$cats) 
testmatrix <- getMatrix(testdata$cats) 

これまでのところ、とても良いです。問題は、a)Naive Bayesモデルを適用し、b)そのモデルから予測しようとするときです。 klarパッケージを使用する - 多くの用語には1つのカテゴリのインスタンスがゼロであり、laplace用語での再生はこれを修正していないようだから、確率エラーはゼロになります。一つ一つのアイテムが、彼らはほぼ同じであるべきにもかかわらず、同じカテゴリを予測...

model <- naiveBayes(as.matrix(trainmatrix),as.factor(traindata$Code)) 
rs<- predict(model, as.matrix(testdata$cats)) 

e1071中を使用して、モデルが働いていたが、その後、私は使用してモデルをテストしたとき。モデル内の何かが明らかに機能していません。モデル$表の用語のいくつかを見ると、多くの人がプライベートの価値が高く、慈善団体の価値が高いことが分かります。コードとしてas.factorを使用しました。

output: 
rs 1 2 
    1 0 0 
    2 19 17 

何が問題になるのでしょうか? dtmの行列はnaivebayesとうまく連動しませんか?私はデータを準備する際に一歩踏み出したことはありませんか?私は完全にアイデアがありません。これがすべて晴れたことを願っています。そうでない場合は明確にしてください。どんな提案も大歓迎です。

+0

を私は多項単純ベイズ分類器と同じ問題を抱えています。一部のデータは正しく割り当てられますが、大部分は1つのクラスで終わります。間違って入力されたクラスは、入力データのサイズに応じて切り替わります。私も[この](http://stackoverflow.com/questions/17904190/why-does-naivebayes-return-all-nas-for-multiclass-classification-in-r)の問題を避けるためにデータを繰り返してみましたが、大部分はまだ1つのクラスで終わる – christopherlovell

答えて

2

私はすでに自分自身に問題がありました。あなたは(私が見ている限り)すべてのことを正しく行っています.e1071のNaive Bayes実装(とくにklar)はバグです。

しかし、e1071で実装されているNaive Bayesが再び機能するように、簡単で迅速な修正があります。テキストベクトルをカテゴリ変数、つまりas.factorに変更する必要があります。すでにターゲット変数traindata$Codeでこれを実行していますが、trainmatrixtestdataの場合は、これを行う必要があります。

L <- log(object$apriori) + apply(log(sapply(seq_along(attribs), 
      function(v) { 
       nd <- ndata[attribs[v]] 
       ## nd is now a cell, row i, column attribs[v] 
       if (is.na(nd) || nd == 0) { 
        rep(1, length(object$apriori)) 
       } else { 
        prob <- if (isnumeric[attribs[v]]) { 
         ## we select table for attribute 
         msd <- object$tables[[v]] 
         ## if stddev is eqlt eps, assign threshold 
         msd[, 2][msd[, 2] <= eps] <- threshold 
         dnorm(nd, msd[, 1], msd[, 2]) 
        } else { 
         object$tables[[v]][, nd] 
        } 
        prob[prob <= eps] <- threshold 
        prob 
       } 
      })), 1, sum) 

私がダウンして100%のパーセントにバグを追跡することができませんでしたが、それはe1071中からナイーブベイズの実装では、この部分にある(私は注意して、クラーはe1071中の周りだけのラッパーです) if-else-conditionがあることがわかります。数値がなければ、純粋なベイが使用されています。数値がある場合 - バグが来る - この素朴なベイは自動的に正規分布になります。あなたのテキストに0と1しかない場合、ドノームはかなりうんざりです。私はprobをdnormによって作成された非常に低い値のために仮定します。常にthresholdに置き換えられ、したがって、先験的要因が高い変数は常に「勝つ」でしょう。

しかし、あなたの問題が正しいと理解すれば、どの部門が誰にお金を与えるのかを特定するための先験的な要因ではなく、予測する必要はありません。そして、あなたのモデルを深く見ているだけです。あなたのモデルでは、すべての用語のために、私があなたが探していると仮定している先験的確率が現れます。

## i have changed the vectors slightly 
first <- "environment+housing strategy+commissioning third_party_payments supporting_ppl_block_gross_chargeable" 
second <- "west_north_west customer+tenancy premises h.r.a._special_maintenance" 

categories <- c("charity", "private") 

library(tm) 
library(e1071) 

getMatrix <- function(chrVect){ 
    testsource <- VectorSource(chrVect) 
    testcorpus <- Corpus(testsource) 
    testcorpus <- tm_map(testcorpus,stripWhitespace) 
    testcorpus <- tm_map(testcorpus, removeWords,stopwords("english")) 
    ## testmatrix <- t(TermDocumentMatrix(testcorpus)) 
    ## instead just use DocumentTermMatrix, the assignment is superflous 
    return(DocumentTermMatrix(testcorpus)) 
} 

## since you did not supply some more data, I cannot do anything about these lines 
## trainmatrix <- getMatrix(traindata$cats) 
## testmatrix <- getMatrix(testdata$cats) 
## instead only 
trainmatrix <- getMatrix(c(first, second)) 

## I prefer running this instead of as.matrix as i can add categories more easily 
traindf <- data.frame(categories, as.data.frame(inspect(trainmatrix))) 

## now transform everything to a character vector since factors produce an error 
for (cols in names(traindf[-1])) traindf[[cols]] <- factor(traindf[[cols]]) 
## traindf <- apply(traindf, 2, as.factor) did not result in factors 

## check if it's as we wished 
str(traindf) 

## it is 
## let's create a model (with formula syntax) 
model <- naiveBayes(categories~., data=traindf) 

## if you look at the output (doubled to see it more clearly) 
predict(model, newdata=rbind(traindf[-1], traindf[-1])) 

をしかし、私はすでに述べたように、あなたは予測する必要はありません。のは、あなたのサンプルを少し変更したバージョンでこれと前述しましょう。モデルを見ても大丈夫です。 model$tables$premisesは、あなたが民間企業にお金を与える施設の可能性を100%与えます。

非常に大きなデータセットを扱う場合は、モデルでthresholdとepsを指定する必要があります。 Epsは、しきい値を指定する必要がある場合に、その制限を定義します。例えば。 eps = 0およびthreshold = 0.000001を使用できます。

また、用語 - 頻度の重み付けを使用することに固執する必要があります。 tf * idv素朴な湾の沼のためにうまくいかない。

希望私はようやく私の50の評判を得ることができます:P