質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.78%

正解率が極端に低い原因がわかりません。

解決済

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 1,377

hiko1129

score 79

前提・実現したいこと

R 3.3.2
naiveBayes

正解率を上げたいと考えています。
ksvmを利用した場合に比べて極端に低い正解率が表示されるので、どこか根本的に間違っている部分があると思われるのですがわかりませんでした。その部分を改善してまともな正解率を算出するものにしたいと考えております。
よろしくお願いいたします。

発生している問題・エラーメッセージ

エラーが出ているわけではないのですが、正解率が極端に低いためどこかで根本的な間違いを犯しているようです。
ksvmを利用した場合は90%近くでるのですが、naiveBayesを利用した場合は10%程で、データ数を増やすと更に下がります。
1を-1と判断することが多いです。

試したこと

docMatrixDFのweightの変更
naiveBayesのclass.weightsの削除等

特に改善しませんでした。

コード

library(XML)
library(RCurl)
library(tm)
library(RSQLite)
library(RMeCab)
library(Nippon)
library(e1071)


url = 'http://svn.sourceforge.jp/svnroot/slothlib/CSharp/Version1/SlothLib/NLP/Filter/StopWord/word/Japanese.txt'
# 日本語のストップワードリストのURLです。

html_file = getURL(url)
# htmlファイルの取得
doc = htmlParse(html_file, encoding="UTF-8")
# 解析

target_xpath = '/html/body/p'
p = xpathSApply(doc, target_xpath, xmlValue)
# ストップワードの取り出し

stopwords = unlist(strsplit(p, '(\r\n){1,}'))
# 改行を削除することで単語ごとに格納

con = dbConnect(SQLite(), "reviews.db", synchronous="off")
# レビューが保存されているデータベースに接続

r1 = dbGetQuery(con, "select * from unique_reviews limit 200")
# データベースから値を取得
# テーブルはidとreviewとrateを持っています

r1 = r1[r1$rate!=3,]
# 評価値が3のものを取り除く

for(i in length(r1$review)) {
  r1$review[i] = zen2han(r1$review[i])
}
# 英数字の全角を半角にすることで英数字を半角に揃える。

dtm = docMatrixDF(r1$review, weight='tf3', minFreq=2)
# 文書単語行列に変換
# /usr/local/etc/mecabrcにてdicdir=/usr/local/lib/mecab/dic/mecab-ipadic-neologdに変えました。

dtm = dtm[rowSums(dtm) > 5, ]

row_names1 = row.names(dtm)
row_names2 = removeNumbers((row.names(dtm)))
for(i in 1:length(row_names1)) {
  if(row_names1[i] != row_names2[i]) {
    dtm[i,] = NA
    # 数字を含んでいる単語を削除する。
    # 削除する行にNAをセット
    # ここで毎回削除すると行にずれが生じるのでここではNAのセットに留める
  }
}
dtm = na.omit(dtm)
# NAがセットされた行をすべて削除

punct = c('!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/', '・', '「', '」', '、', '。')
stopwords = c(stopwords, punct)
for(stopword in stopwords) {
  dtm <- dtm[row.names(dtm) != stopword,]
}
# 不要な単語をある程度削除

dtm = as.data.frame(dtm)
# データフレームに変換

for(i in 1:(dim(dtm)[1])) {
  frequency = 0
  for(j in 1:(dim(dtm)[2])) {
    if(dtm[[j]][[i]] > 0) {
      frequency = frequency + 1
    }
  }
  if(frequency < 5) {
    dtm[i,] = NA
  }
}
dtm = na.omit(dtm)
# ある単語がどれだけの文書に出現しているかを計算

dtm = as.data.frame(t(dtm))
# 転置

rate = c()
for(i in r1$rate) {
  if(i > 3) {
    rate = c(rate, 1)
    } else {
    rate = c(rate, -1)
  }
}
# ポジティブ、ネガティブで分類するために4,5の評価を1に、1,2の評価を-1にしました

dtm = cbind(dtm, Class=as.ordered(rate))
# 評価値(クラス)を追加

train_index = 1:(dim(dtm)[1] * 0.8)
# 分割用のインデックスを作成
# 学習用を8割、テスト用を2割
dtm.train = dtm[train_index,]
# 学習用データ
dtm.test = dtm[-train_index,]
# テストデータ

set.seed(50)
# 乱数固定

weights = 100/table(rate)
# 重みの計算
doc.bayes = naiveBayes(Class~., data=dtm.train, cross=15, class.weights=c('-1'=weights[[1]], '1'=weights[[2]]))
# 重み調整により不均衡データへ対応しています。

prediction <- predict(doc.bayes, dtm.test[, -ncol(dtm.test)] )
# 答えの列を削除して予測

precision <- table(dtm.test[, ncol(dtm.test)], prediction)
# 混同行列に合計がつかないものを作成。

confusion_matrix = addmargins(precision)
# 混同行列の作成
print(confusion_matrix)
# 混同行列の表示

accuracy = (confusion_matrix[1,1] + confusion_matrix[2,2]) / confusion_matrix[3, 3]
# 正解率の計算
print(accuracy)
# 正解率の表示

以下のような結果になります。

print(confusion_matrix)
     prediction
      -1  1 Sum
  -1   4  0   4
  1   31  0  31
  Sum 35  0  35

print(accuracy)
[1] 0.1142857
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

ストップワードの元になるデータはプレインテキストなので、HTMLとみなしてXPathで内容を取り出そうとしてもなにも取れないように思います。結果として、ノイズが多くなっている可能性はあります。

まずは、文書単語行列の内容をprint文かなにかで出力するようにして、思い通りのものが取得できているか (不要なものを取り除けているか) を確認してみてはどうでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.78%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る