LoginSignup
24
23

More than 5 years have passed since last update.

Rで文書分類器。未来設定のラブライブ!百合小説を抽出する。

Last updated at Posted at 2014-04-26

概要

統計専用言語Rで文書分類器を作った。
任意のカテゴリに分類したサンプル文書群を渡した後に検証したい文書群を渡すと、
自動で分類してくれる。
形態素解析には「MeCab」を、処理ロジックには「ナイーブベイズ」を使っている。
今回は、ラブライブ!百合小説(ただし、にこまきに限る)の中から、
未来設定(二次創作設定の一つ。世界や登場人物の将来を描く)のものを抽出する。
ちなみに、全文書内で現実設定:未来設定の比率は11:4くらい。

精度

訓練データ(サンプル文書)の質と量による。
自分が実行した時はPixiv小説で「百合」とキーワード検索した結果、
BLでなく百合がヒットする確率と同じくらいだった。

手法

01. RMeCabパッケージをインストールする

-> RMeCab のインストールと R を用いたテキスト処理(形態素解析など)
 ※R言語とMeCabのインストール手順もこちらを参考にした。

02. e1071パッケージをインストールする

install.packages("e1071")

03. Rコードファイルを用意する

文書分類器.R
library(RMeCab)
library(e1071)

#基盤フォルダ ※trainとtestの親フォルダを指定
path <- "/home/owner/data/RDocSec"
#訓練データフォルダ
path.train <- paste(path,"train",sep="/")
#検証データフォルダ
path.test <- paste(path,"test",sep="/")

#結果フォルダ
path.result <- paste(path,format(Sys.time(), "%y%m%d%H%M%S"),sep="/") 
dir.create(path.result)
#途中データ格納用フォルダ
path.input <- paste(path.result,"input",sep="/") 
dir.create(path.input)
#分類済みデータ格納用フォルダ
path.output <- paste(path.result,"output",sep="/") 
dir.create(path.output)

#ファイル名分割記号
sep <- "@"

#訓練データファイルを一時フォルダに移動
gather.files <- function(from, to, prefix="", sep="_"){
  for(fname in dir(from, recursive=T)){
    fname.full <- paste(from, fname, sep = "/")
    fname.to <- gsub("/", sep, fname)
    #接頭辞指定の場合は、ファイル名に付与
    if (0 < nchar(prefix)) {fname.to <- paste(prefix, fname.to, sep = sep)}
    fname.to.full <- paste(to, fname.to, sep = "/")
    file.copy(fname.full,fname.to.full)
  }
}
gather.files(path.train, path.input, prefix="A", sep = sep)

#検証データファイルを結果フォルダに移動
gather.files(path.test, path.input, prefix="Q", sep = sep)

#Bag of wordsを作成
d.origin <- t(docMatrix2(path.input, pos = c("名詞"), weight = "norm"))
#記号が含まれる単語頻度列を削除したデータフレームに変換
ptn.rmv <- "^([a-zA-Z0-9。-゚ぁ-んァ-ヶー一-龠])+$"
d <- as.data.frame(d.origin[,regexpr(ptn.rmv,colnames(d.origin)) > -1])
#列名に接頭辞を付与 ※列名が数値だと他パッケージの関数でエラーを起こす。
colnames(d) <- paste("d.", colnames(d), sep = "")

#訓練データを取得 ※列数が足りない項目があるために警告が出る。-> 無視する。
d.info <- do.call(rbind, strsplit(rownames(d), sep))
d.train.index <- which(d.info[,1]=="A")
d.train <- d[d.train.index,]
d.train["tag"] <- factor(d.info[d.train.index,2])
#検証データを取得
d.test <- d[-d.train.index,]

#モデルを作成 ※laplace引数の値が適当か判断が付かない。
model <- naiveBayes(tag~., d.train, laplace = 0.1)
#予測
d.test.result <- predict(model, d.test)

#テキストファイルを分類配置
d.test.fname <- d.info[-d.train.index, 2]
for(dname in levels(d.test.result)){
  dname.full <- paste(path.output, dname, sep="/")
  dir.create(dname.full)
  file.copy(
    paste(path.test, d.test.fname[d.test.result == dname], sep="/"),
    paste(path.output, dname, sep="/"))
}

#途中データフォルダを削除
#file.remove(dir(path.input,full.names=T))
#file.remove(path.input)

04. 文書フォルダ・文書ファイルを用意する

mkdir ./train
mkdir ./train/現在設定
mkdir ./train/未来設定
mkdir ./test

|--文書分類器.R(Rコードファイル)
|
|--train(サンプル文書フォルダ)
| |
| |--現在設定(サンプル文書フォルダ。フォルダ名・フォルダ数は任意。フォルダ名=カテゴリ名として扱う)
| | |
| | |--a1.txt(サンプル文書ファイル。ファイル名・ファイル数は任意)
| | |--a2.txt
| |
| |--未来設定(サンプル文書フォルダ)
| | |
| | |--b1.txt(サンプル文書ファイル)
| | |--b2.txt
|
|--test(分類対象文書フォルダ)
 |
 |--x1.txt(分類対象文書ファイル。ファイル名・ファイル数は任意)
 |--x2.txt

05. 文書分類器.Rをコマンドラインから実行する

R --vanilla < 文書分類器.R

06. 分類結果フォルダを確認する

|--文書分類器.R(Rコードファイル)
|
|--yyyyMMddhhmmss(分類結果フォルダ。ファイル名は処理日時。自動生成)
 |
 |--output
   |--現在設定(カテゴリフォルダ)
   | |
   | |--x1.txt(分類済み文書ファイル)
   | |--x3.txt
   | 
   |--未来設定(カテゴリフォルダ)
     |
     |--x2.txt(分類済み文書ファイル)
     |--x4.txt

結果イメージ

・抽出成功
http://www.pixiv.net/novel/show.php?id=2529098
http://www.pixiv.net/novel/show.php?id=2905600
http://www.pixiv.net/novel/show.php?id=3013865
http://www.pixiv.net/novel/show.php?id=3168830
http://www.pixiv.net/novel/show.php?id=3521018
http://www.pixiv.net/novel/show.php?id=2533491
http://www.pixiv.net/novel/show.php?id=2727661
http://www.pixiv.net/novel/show.php?id=2931042
http://www.pixiv.net/novel/show.php?id=3082961
http://www.pixiv.net/novel/show.php?id=3205532
http://www.pixiv.net/novel/show.php?id=3526601
http://www.pixiv.net/novel/show.php?id=2559010
http://www.pixiv.net/novel/show.php?id=2952683
http://www.pixiv.net/novel/show.php?id=3109968
http://www.pixiv.net/novel/show.php?id=3618936
http://www.pixiv.net/novel/show.php?id=2583337
http://www.pixiv.net/novel/show.php?id=2857318
http://www.pixiv.net/novel/show.php?id=3000539
http://www.pixiv.net/novel/show.php?id=3160970
http://www.pixiv.net/novel/show.php?id=3407677
http://www.pixiv.net/novel/show.php?id=3676791

・抽出失敗
http://www.pixiv.net/novel/show.php?id=2598550
http://www.pixiv.net/novel/show.php?id=2802317
http://www.pixiv.net/novel/show.php?id=3276155

感想

百合三角関係小説(ex.えり↔にこ←まき)がサンプルデータとしても少なすぎるので、
みんな書くといいと思います。(提案)

関連ページ

-> ニコニコ大百科データからMeCab辞書を生成する
-> Pixiv小説検索APIの結果を元に小説本文を取得する
-> Rで決定木。日本語小説を世界観設定別に切り分けるキーワードを探る

24
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
23