#contents * [[RMeCab]] の出力に [[topicmodels:http://cran.md.tsukuba.ac.jp/web/packages/topicmodels/index.html]] の LDA を適用 [#u97160a7] > test <- docMatrix2( "data/morikita") library (RMeCab) > install.packages("slam") > library(slam) > test.sparse <- as.simple_triplet_matrix( t(test) ) test <- docMatrix2( "morikita") # フォルダを指定 > install.packages("topicmodels") > library(topicmodels) install.packages("slam") library(slam) test.sparse <- as.simple_triplet_matrix( t(test) ) #スパースな行列に変換 library (tm) # この2行で重みを設定 test.sparse2 <- as.DocumentTermMatrix ( test.sparse, weighting = weightTf ) # ## sudo apt-get install libgsl0-dev # Ubuntuの場合,これが必要 install.packages("topicmodels") library(topicmodels) # # class(test.sparsea) <- "DocumentTermMatrix" # 不要 topic.mod <- LDA(test.sparse2, control = list(alpha = 0.1), k = 5) > class(test.sparse) <- "DocumentTermMatrix" > topic.mod <- LDA(test.sparse, control = list(alpha = 0.1), k = 5) LDA関数はinputのクラスが,sparse な行列であり, かつ tm パッケージ独自の DocumentTermMatrix クラスで あることを前提にしてます. そこで RMeCab の出力を as.simple_triplet_matrix 関数で sparse な triplet_matrix に変え,そのクラス属性を "DocumentTermMatrix" に変更すると, LDA 関数への input になると思われます. * 語彙の統合 [#rfc958e8] 「Rによるテキストマイニング入門」には 記載されていませんが,&color(red){&size(18){docDF()};};という関数があります. &ref(SoftArchive/manual100831.pdf); に少し記載があります. > res <- docDF("doc", type=1, N=1) file_name = doc/doc1.txt opened file_name = doc/doc2.txt opened file_name = doc/doc3.txt opened number of extracted terms = 18 now making a data frame. wait a while! > res TERM POS1 POS2 doc1.txt doc2.txt doc3.txt 1 。 記号 句点 1 1 1 2 いる 動詞 非自立 0 0 1 3 だ 助動詞 * 1 0 0 4 で 助詞 接続助詞 0 0 1 5 です 助動詞 * 1 1 0 ... デフォルトでは全品詞を抽出しますが,品詞情報から選り分けて "*","格助詞", "係助詞", "句点","非自立") を省く場合は %in% 演算子 を使って以下のようにします. > res2 <- res[ !(res$POS2 %in% c("*","格助詞", "係助詞", "句 点","非自立")), ] > res2 TERM POS1 POS2 doc1.txt doc2.txt doc3.txt 4 で 助詞 接続助詞 0 0 1 10 学ぶ 動詞 自立 0 0 1 11 学生 名詞 一般 1 1 0 12 彼女 名詞 代名詞 0 1 1 ... あるいは名詞は抽出するが,ただし細分類が"*","数詞", "接尾", "代名詞"を 除く場合は > res4 <- res[ res$POS1 %in% c("名詞","形容詞") & !(res$POS2 %in% c("*","数詞", "接尾", "代名詞")), ] > res4 TERM POS1 POS2 doc1.txt doc2.txt doc3.txt 11 学生 名詞 一般 1 1 0 13 数学 名詞 一般 0 1 1 14 真面目 名詞 形容動詞語幹 1 0 0 16 科 名詞 接尾 0 1 0 17 良い 形容詞 自立 0 1 0 18 難しい 形容詞 自立 0 0 1 ただし,これはデータフレームですので,操作する 場合には行列に変える必要があるかもしれません > res3 <- as.matrix(res2[, -(1:3)]) > rownames(res3) <- res2[,1] > res3 doc1.txt doc2.txt doc3.txt で 0 0 1 学ぶ 0 0 1 学生 1 1 0 彼女 0 1 1 数学 0 1 1 ... * 日本語の stopwords [#gfd88518] MeCabの品詞情報が以下 にあります. MeCabの品詞情報は IPA 素性辞書に そっています http://chasen.aist-nara.ac.jp/snapshot/ipadic/ipadic/doc/ipadic-ja.pdf IPA辞書については以下に解説があります. http://parame.mwj.jp/blog/0209 特に以下のページの下にある ChaSen 品詞体系 (IPA品詞体系) http://www.unixuser.org/~euske/doc/postag/index.html に,MeCab の標準辞書は準拠しています. ここを参考に docDF() の出力から,POS1 列と POS2 列の内容を %in% 演算子で選り分けて,独自にstopwordを 定義されるがのベストではないかと思います. 私自身は独自にstopword を用意していません.日本語テキスト マイニングに関わる仲間たちも,テキストごと,あるいジャンル ごとに stopwordsを定義しているのが現状のようです. IPA品詞体系 から判断するに,たとえば ,&color(red){&size(18){docDF()};}; 出力の POS1 が名詞 や動詞,形容詞でも,POS2 が 「接尾」,「非自立」などのタームは, 内容語というよりは機能語に近いので,削除対象になると思います. * 言葉の「正規化」 [#taa22ba7] 表記の統一については,有料ソフトでは,ある程度 自動的にこれを行なってくれる場合があるようですが (ただし完全ではありません),いずれにせよ 最後は分析者自身による確認が必要です. これは残念ながら手作業しかありません.あとは この作業をできるだけ効率的に行なうだけです. 手作業で行なう場合,以下の二つが考えらえるでしょうか. - 1) ひらがな,あるいはカタカナで始まる単語は,漢字に 統一できる可能性がある(いぬ,イヌ -> 犬) そこで,データから,ひらがな,あるいはカタカナで始まる単語 を探してチェックする. > res <- docDF("data/doc", pos = c("名詞","形容詞","動詞"), type = 1) # 以下とりあえず力技でカタカナとひらがなを用意してしまいます > kana <- c("\\<あ|\\<ア|\\<か|\\<カ|\\<さ|\\<サ|\\<た|\\<タ| \\<な|\\<ナ|\\<は|\\<ハ|\\<ま|\\<マ|\\<や|\\<ヤ|\\<ら|\\<ラ| \\<わ|\\<ワ|\\<ん|\\<ン|\\<が|\\<ガ|\\<ざ|\\<ザ|\\<だ|\\<ダ| \\<ば|\\<バ|\\<ぱ|\\<パ|\\<ゃ|\\<い|\\<イ|\\<き|\\<キ|\\<し| \\<シ|\\<ち|\\<チ|\\<に|\\<ニ|\\<ひ|\\<ヒ|\\<み|\\<ミ|\\<り| \\<リ|\\<ゐ|\\<ヰ|\\<ぎ|\\<ギ|\\<じ|\\<ジ|\\<ぢ|\\<ヂ|\\<び| \\<ビ|\\<ぴ|\\<ピ|\\<ゅ|\\<ュ|\\<う|\\<ウ|\\<く|\\<ク|\\<す| \\<ス|\\<つ|\\<ツ|\\<ぬ|\\<ヌ|\\<ふ|\\<フ|\\<む|\\<ム|\\<ゆ| \\<ユ|\\<る|\\<ル|\\<ぐ|\\<グ|\\<ず|\\<ズ|\\<づ|\\<ヅ|\\<ぶ| \\<ブ|\\<ぷ|\\<プ|\\<ょ|\\<ョ|\\<え|\\<エ|\\<け|\\<ケ|\\<せ| \\<セ|\\<て|\\<テ|\\<ね|\\<ネ|\\<へ|\\<ヘ|\\<め|\\<メ|\\<れ| \\<レ|\\<ゑ|\\<ヱ|\\<げ|\\<ゲ|\\<ぜ|\\<ゼ|\\<で|\\<デ|\\<べ| \\<ベ|\\<ぺ|\\<ペ|\\<っ|\\<ッ|\\<お|\\<オ|\\<こ|\\<コ|\\<そ| \\<ソ|\\<と|\\<ト|\\<の|\\<ノ|\\<ほ|\\<ホ|\\<も|\\<モ|\\<よ| \\<ヨ|\\<ろ|\\<ロ|\\<を|\\<ヲ|\\<ご|\\<ゴ|\\<ぞ|\\<ゾ|\\<ど| \\<ド|\\<ぼ|\\<ボ|\\<ぽ|\\<ポ") > res$TERM[grep(kana, res$TERM)] この出力が,それほど多くなければ,手作業で表記のずれを 統一していけるのではないでしょうか. アルファベットや数字を含む単語なら > res$TERM[grep("[[:alnum:]]", res$TERM, perl = T)] でしょうか. - 2) 同義語を統一する まず同義語のリストがあるとすれば,たとえば docDF() の 出力は以下のように整理できます. > res <- docDF("data/doc", pos = c("名詞","形容詞","動詞"), type = 1) res TERM POS1 POS2 doc1.txt doc2.txt doc3.txt 1 いる 動詞 非自立 0 0 1 2 学ぶ 動詞 自立 0 0 1 3 学生 名詞 一般 1 1 0 4 彼女 名詞 代名詞 0 1 1 5 数学 名詞 一般 0 1 1 6 真面目 名詞 形容動詞語幹 1 0 0 7 私 名詞 代名詞 1 0 0 8 科 名詞 接尾 0 1 0 9 良い 形容詞 自立 0 1 0 10 難しい 形容詞 自立 0 0 1 > wordlist <- list(c("*", "動詞と形容詞の", "自立", "良い", "難しい", "学ぶ" ), c("**", "名詞", "代名詞", "彼女","私") ) # "良い", "難しい", "学ぶ" を ”*” "動詞と形容詞の", "自立"にまとめてしまう # "彼女","私" を "**" 名詞", "代名詞", にまとめてしまう > res2 <- res > dummy <- res[1,] > dummy[,1:3] <- "" > dummy[,4:ncol(dummy)] <- 0 > for(i in 1:length(wordlist)){ idx0 <- any( res2$TERM %in% wordlist[[i]][1]) if(!idx0){ dummy[, 1:3] <- wordlist[[i]][1:3] res2 <- rbind(res2, dummy) } idx <- which(res2$TERM %in% wordlist[[i]][-(1:3)] ) if(length (idx) > 0){ res2[res2$TERM == wordlist[[i]][1] ,4:ncol(dummy)] <- colSums(res2[idx, 4:ncol(dummy)]) res2 <- res2[-idx,] } } > res2 TERM POS1 POS2 doc1.txt doc2.txt doc3.txt 1 いる 動詞 非自立 0 0 1 3 学生 名詞 一般 1 1 0 5 数学 名詞 一般 0 1 1 6 真面目 名詞 形容動詞語幹 1 0 0 8 科 名詞 接尾 0 1 0 11 * 動詞と形容詞の 自立 0 1 2 12 ** 名詞 代名詞 1 1 1 問題は同義語リストをどうやって作るかですが,次のような データベースがあります. http://nlpwww.nict.go.jp/wn-ja/ SQLite3 データベースが使えることが前提となりますが 以下のようにすると,同義語のリストを作成できます. ## install.packages("DBI") ## install.packages("RSQLite") > library(RSQLite) > drv <- dbDriver("SQLite") > con <- dbConnect(drv, dbname="wnjpn.db") > test.table <- dbGetQuery(con, ".tables") > test.table1 <- dbGetQuery(con, "select DISTINCT lemma from word where wordid in (select wordid from sense where synset in ( select synset from sense where wordid in (select wordid from word where lemma=\"犬\")))") > test.table2 <- dbGetQuery(con, "select DISTINCT lemma from word where wordid in (select wordid from sense where synset in ( select synset from sense where wordid in (select wordid from word where lemma=\"日本\")))") # 以上,面倒でしょうから,日本語wordnetから抽出するためのパッケージを用意しています. > wordlist <- list( test.table1$lemma , test.table2$lemma) > wordlist [[1]] [1] "canis_familiaris" "dog" "domestic_dog" "spy" [5] "undercover_agent" "いぬ" "まわし者" "イヌ" [9] "スパイ" "ドッグ" "回し者" "回者" [13] "密偵" "工作員" "廻し者" "廻者" [17] "探" "探り" "洋犬" "犬" [21] "秘密捜査員" "諜報員" "諜者" "間者" [25] "間諜" "隠密" "飼い犬" "飼犬" [[2]] [1] "japan" "nihon" "nippon" "日本" ただ完全ではありません.上の出力にあるように,”日本”を 検索しても,にほん、にっぽん、ニッポン、ニッポンは出て きませんので,手作業で加えるしかありません. とりあえず,ひらがな,あるいはカタカナ,アルファベットで表記 された単語を調べ,統一することから始めてはどうでしょうか.