R による文書分類入門

23,015 views

Published on

Tokyo.R #31 の発表資料です。

こちらも参考にどうぞ。
R による文書分類入門 & KNB コーパスの文書分類 - あらびき日記
http://d.hatena.ne.jp/a_bicky/20130602/1370179340

R による文書分類入門

  1. 1. R による自然言語処理入門Tokyo.R #31 (2013/06/01)@a_bicky文書分類
  2. 2. 自己紹介• Takeshi Arabiki‣ 平凡な Web エンジニア(主に JavaScript)‣ Twitter & はてな: @a_bicky & id:a_bicky‣ e-mail:• 興味など機械学習、自然言語処理• ブログあらびき日記 http://d.hatena.ne.jp/a_bicky/
  3. 3. R関係の主な発表Rユーザ会 2011Tokyo.R #16http://www.slideshare.net/abicky/r-9034336 http://www.slideshare.net/abicky/r-10128090Tsukuba.R #9http://www.slideshare.net/abicky/rtwitter
  4. 4. Rによる文書分類入門
  5. 5. 基礎知識
  6. 6. 形態素解析• 文を形態素(意味の最小単位)に分割‣ 日本語自然言語処理における 単語 はたいてい形態素のこと‣ e.g. 「お酒」→「お」+「酒」(形態素の定義は曖昧)• 各形態素の品詞推定‣ e.g. 「お(接頭詞)」+「酒(名詞)」自然言語で書かれた文を形態素(Morpheme, おおまかにいえば、言語で意味を持つ最小単位)の列に分割し、それぞれの品詞を判別する作業を指す。引用: 形態素解析 - Wikipediaつまり・・・
  7. 7. mecab による形態素解析$ mecabハードルは高ければ高いほどくぐりやすいハードル 名詞,一般,*,*,*,*,ハードル,ハードル,ハードルは 助詞,係助詞,*,*,*,*,は,ハ,ワ高けれ 形容詞,自立,*,*,形容詞・アウオ段,仮定形,高い,タカケレ,タカケレば 助詞,接続助詞,*,*,*,*,ば,バ,バ高い 形容詞,自立,*,*,形容詞・アウオ段,基本形,高い,タカイ,タカイほど 助詞,副助詞,*,*,*,*,ほど,ホド,ホドくぐり 動詞,自立,*,*,五段・ラ行,連用形,くぐる,クグリ,クグリやすい 形容詞,非自立,*,*,形容詞・アウオ段,基本形,やすい,ヤスイ,ヤスイEOS入力文出力
  8. 8. ベクトル空間モデル• 素性 (feature) の取り方はいろいろ• Unigram model (Bag-of-Words model)‣ 1つの単語を1つの素性とする‣ 単語の出現順は考慮しない(文書を単語の袋詰めとみなす)e.g. 「赤ちゃんと僕」と「僕と赤ちゃん」は同じベクトルになる• N-gram model‣ 連続する n 単語を1つの素性とするe.g. 「赤ちゃんと僕」→ <s>赤ちゃん, 赤ちゃんと, と僕, 僕</s>「僕と赤ちゃん」→ <s>僕, 僕と, と赤ちゃん, 赤ちゃん</s>そせい文書をベクトル空間の1点として表現する
  9. 9. 単語の重み付け• TF (Term-Frequency) 値‣ 各文書における単語の出現頻度• IDF (Inverse Document Frequency) 値‣ コーパス(文書集合)内で対象の単語を含む文書の割合の逆数の対数• TF-IDF 値‣ TF 値と IDF 値を掛けあわせた値‣ 特定の文書にだけ出現する単語の値が大きくなるcf. 情報検索アルゴリズム 3.2 節参照idf(t, D) = log|D||{d|d ∈ D, t ∈ d}|tfidf(t, d, D) = tf(t, d)idf(t, D)tf(t, d) = |{x|x ∈ d, x = t}|
  10. 10. 単語文書行列D =d1 d2 · · · dMt1 0 1 . . . 0t2 2 0 . . . 0...............tV 1 0 . . . 2各文書ベクトルを列に並べた行列e.g. あるコーパスに対する TF 値による単語文書行列文書 の文書ベクトル文書 における単語 の出現回数d2dM tV
  11. 11. 単語文書行列の作成> library(RMeCab)>> pos <- c("名詞", "動詞", "形容詞", "副詞", "連体詞")> texts <- c("ハードルは高ければ高いほどくぐりやすい",+ "タダより高いものはない")>> D1 <- docMatrixDF(texts, pos = pos, weight = "tf")to make data frame# 抽出する形態素の品詞RMeCab を使うことで手軽に単語文書行列が作成可能# TF 値による単語文書行列を作成
  12. 12. > D1OBS.1 OBS.21 00 10 11 00 11 02 1単語文書行列の作成くぐるないものやすいタダハードル高いRMeCab を使うことで手軽に単語文書行列が作成可能
  13. 13. N-gram による行列>> D2 <- t(docNgramDF(texts, type=1, pos=pos, N=2))number of extracted terms = 7to make matrix now> D2Row1 Row21 00 10 11 01 00 11 0[くぐる-やすい][もの-ない][タダ-高い][ハードル-高い][高い-くぐる][高い-もの][高い-高い]# 2-gram (bigram) による行列を作成
  14. 14. 疎行列• 単語文書行列は多くの場合疎行列• 非零要素のインデックスとその値だけを保持(省メモリ化)‣ データの格納形式には CSC、CSR、COO などがある• R の代表的なパッケージは Matrix‣ 基本的な操作は普通の行列と同様に行うことが可能‣ 疎行列に対応していない関数は普通の行列に変換する必要あり‣ 普通の行列では R の制限で作成できない大規模な行列も作成可能行列の多くの要素が 0 である行列
  15. 15. 疎行列への変換> library(Matrix)> (sm <- as(D1, "CsparseMatrix"))7 x 2 sparse Matrix of class "dgCMatrix"OBS.1 OBS.21 .. 1. 11 .. 11 .2 1くぐるないものやすいタダハードル高い# CSC 形式の疎行列に変換
  16. 16. > str(sm)Formal class dgCMatrix [package "Matrix"] with 6slots..@ i : int [1:8] 0 3 5 6 1 2 4 6..@ p : int [1:3] 0 4 8..@ Dim : int [1:2] 7 2..@ Dimnames:List of 2.. ..$ : chr [1:7] "くぐる" "ない" "もの" "やすい" ..... ..$ : chr [1:2] "OBS.1" "OBS.2"..@ x : num [1:8] 1 1 1 2 1 1 1 1..@ factors : list()疎行列の構造行のインデックス (0-origin)列の開始ポインタ (0-origin)非零の要素の値
  17. 17. CSC 形式CSC (= Compressed Sparse Column)i 0 3 5 6 1 2 4 6x 1 1 1 2 1 1 1 1(i,j) (0,0) (3,0) (5,0) (6,0) (1,1) (2,1) (4,1) (6,1)p 0 4 80 列目はここから1 列目はここから
  18. 18. 疎行列の操作> sm[c(3, 5), ]2 x 2 sparse Matrix of class "dgCMatrix"OBS.1 OBS.2. 1. 1> colSums(sm)[1] 5 4> rowSums(sm)[1] 1 1 1 1 1 1 3> as.matrix(sm[c(3, 5), ])OBS.1 OBS.20 10 1# 3行目と5行目を抽出ものタダ# 各文書の単語数を算出# 各単語の出現回数を算出ものタダ# 普通の行列に変換基本的な操作は普通の行列と同様に行うことが可能
  19. 19. 文書分類
  20. 20. 文書分類• 今回扱うのは2クラス分類‣ e.g. 受信したメールがスパムメールかどうか• 扱う手法‣ 決定木(CART)‣ ナイーブベイズ‣ 最大エントロピー (ME) モデル‣ サポートベクターマシン (SVM)
  21. 21. サンプルデータ> library(maxent) # cf. help(maxent)> data <- read.csv(system.file("data/NYTimes.csv.gz",+ package = "maxent"))>> subdata <- subset(data, Topic.Code %in% c(16L, 20L))>> topic <- factor(subdata$Topic.Code)> corpus <- Corpus(VectorSource(subdata$Title))>> D <- as.matrix(t(DocumentTermMatrix(corpus)))maxent パッケージの New York Times データを使用# 2クラス分類なので Topic.Code が 16 と 20 のものだけ使用# クラスラベル# 単語文書行列
  22. 22. サンプルデータ>> rownames(D)[which(rownames(D) == "...")] <- "X..."> set.seed(0)>> trainIndex <- sample.int(ncol(D), ncol(D) * 0.5)> trainData <- t(D[, trainIndex])> testData <- t(D[, -trainIndex])> trainTopic <- topic[trainIndex]> testTopic <- topic[-trainIndex]# データの半分を学習データとして使用# rpart でエラーになるので単語名を変更maxent パッケージの New York Times データを使用
  23. 23. ナイーブベイズ
  24. 24. ナイーブベイズデータの生成確率(条件付き確率)を最大化するクラスを選択• 単純なモデルなので実装が楽(R で10行!!)‣ cf. 10行でナイーブベイズ ∼Rって便利だね!∼ - あらびき日記• 学習も高速• 特定のクラスに出現しない単語の対処が必要(ディスカウンティング)ˆy = arg maxyNi=1log P(wi|y) + log P(y)
  25. 25. 確率的言語モデル• 単語列 の同時確率 を与えるモデル• 文書の生成方法をモデル化‣ に従って単語列を生成することで文書を生成可能wN1 = w1w2 · · · wNw NMunigram の例(各単語が独立と仮定)P(wN1 )P(wN1 )P(d) = P(wN1 ) =Ni=1P(wi)
  26. 26. Unigram Mixturesw NMクラスごとに unigram を割り当てるモデル• カテゴリの異なる文書は単語の出現確率も異なるはず• 各文書は1つのクラス(トピック)から生成されると仮定P(d) =yP(y)Ni=1P(wi|y)ˆy = arg maxyNi=1P(wi|y)P(y)ナイーブベイズはこの値を最大化するクラスを真のクラスと推定するy
  27. 27. ディスカウンティング• ナイーブベイズの問題点‣ あるクラスの学習データに存在しない単語を含む文書は決してそのクラスに分類されない(ゼロ頻度問題)- e.g. 0.9 x 0.95 x 0.8 x 0.99 x 0 = 0• 加算法‣ 全単語に関して出現頻度を一律 +δ する‣ あるクラスの学習データに現れない単語でも δ回出現しことになる• 単純グッド・チューリング推定法‣ 加算法より洗練されたディスカウンティング方法‣ cf. 単純グッド・チューリング推定法 (Simple Good-TuringEstimation) とは何ぞや? - あらびき日記
  28. 28. ナイーブベイズを実装myNaiveBayes - function(x, y) {lev - levels(y)ctf - sapply(lev, function(label) {colSums(x[y == label,])})ctp - t(t(ctf + 1) / (colSums(ctf) + nrow(ctf)))nc - table(y, dnn = NULL)cp - nc / sum(nc)structure(list(lev = lev, cp = cp, ctp = ctp),class = myNaiveBayes)}# 各クラスにおける単語出現頻度# ラプラススムージングによるクラスごとの単語の出現確率# 各クラスの生成確率# 各クラスに所属する文書数
  29. 29. ナイーブベイズを実装predict.myNaiveBayes - function(model, x) {prob - apply(x, 1, function(x) {colSums(log(model$ctp) * x)})prob - prob + log(as.numeric(model$cp))level - apply(prob, 2, which.max)model$lev[level]}# 予測用の関数
  30. 30. R でナイーブベイズ model - myNaiveBayes(trainData, trainTopic) pred - predict(model, testData) (tbl - table(pred, truth = testTopic))truthpred 16 2016 193 3320 27 166 sum(diag(tbl)) / sum(tbl)[1] 0.8568019# 正解率
  31. 31. 決定木 (CART)
  32. 32. 決定木 (CART) の概要根ノードから各ノードの判定基準に従ってり着いた葉ノー ドによりクラスを分類Yes NoYes NoC1C1 C2A0A1• 量的変数と質的変数の混在する素性を容易に扱える• 構築したモデルの解釈や分類結果の要因の解明がしやすい• 大規模な素性を扱うには不向き• R では CART が使われる• CART は二分木を生成する
  33. 33. • 不純度の減少を最大化させるようにノードを生成= ノード生成後の不純度を最小化させるようにノードを生成‣ 不純度:はノード A に存在する i 番目のクラスのデータの割合‣ Gini 係数:‣ 情報エントロピー:クラスの分布に偏りがあるほど不純度は小さくなる(小さい程良い)‣ 不純度の減少量:CART の学習I(A) =if(piA)∆I = p(A)I(A) − p(AL)I(AL) − p(AR)I(AR)f(p) = p(1 − p)f(p) = −p log(p)piA
  34. 34. CART の学習例Yes NoAL ARA(50, 50)(15, 32) (35, 18)素性1 0クラス1とクラス2のデータが50個ずつある場合
  35. 35. クラス1とクラス2のデータが50個ずつある場合Yes NoAL ARA(50, 50)(15, 32) (35, 18)p1AL=1547p2AL=3247p1AR=3553p2AR=1853p(AL) =47100 p(AR) =53100p1A =50100p2A =50100p(A) = 1素性1 0∆I = p(A)2i=1piA(1 − piA) − p(AL)2i=1piAL(1 − piAL) −2i=1piAR(1 − piAR)= 0.058CART の学習例
  36. 36. Yes NoAL ARA(50, 50)(7, 29) (43, 21)p1A =50100p2A =50100p(A) = 1素性2 0∆I = p(A)2i=1piA(1 − piA) − p(AL)2i=1piAL(1 − piAL) −2i=1piAR(1 − piAR)p1AL=736p2AL=2936p1AR=4364p2AR=2164p(AL) =36100 p(AR) =64100= 0.105 こちらの分割方法の方が不純度の減少量が大きい(良い分割方法)CART の学習例クラス1とクラス2のデータが50個ずつある場合
  37. 37. 1-SE ルール1 2 3 4 5 6Yes NoYes NoC1C2A0A1Yes NoYes NoA2A3 A4A5C2葉ノードの数CVエラークロスバリデーション (CV) エラーとその標準偏差を基準に枝刈りCVエラーの最小値枝刈りすることで過学習を抑制
  38. 38. 1 2 3 4 5 6Yes NoYes NoC1C2A0A1Yes NoYes NoA2A3 A4A5C2CVエラーの最小値+標準偏差クロスバリデーション (CV) エラーとその標準偏差を基準に枝刈り葉ノードの数CVエラー枝刈りすることで過学習を抑制1-SE ルール
  39. 39. 1 2 3 4 5 6Yes NoYes NoC1C2A0A1Yes NoYes NoA2A3 A4A5C2CVエラーの最小値+標準偏差を最初に下回る点クロスバリデーション (CV) エラーとその標準偏差を基準に枝刈り葉ノードの数CVエラー枝刈りすることで過学習を抑制1-SE ルール
  40. 40. 1 2 3 4 5 6Yes NoYes NoC1C2A0A1Yes NoYes NoA3 A4A5C2枝刈り C1クロスバリデーション (CV) エラーとその標準偏差を基準に枝刈り葉ノードの数CVエラー枝刈りすることで過学習を抑制1-SE ルール
  41. 41. R で決定木 library(mvpart) model - rpart(topic ~ .,+ data.frame(trainData, topic = trainTopic)) pred - predict(model, data.frame(testData),+ type = class) (tbl - table(pred, truth = testTopic))truthpred 16 2016 88 620 132 193 sum(diag(tbl)) / sum(tbl)[1] 0.6706444
  42. 42. ME モデル
  43. 43. 最大エントロピー (ME) モデルP(y|x) =1Z(x)expiλifi(x, y)=1Z(x)expλTf(x, y)Z(x) =y∈YexpλTf(x, y)(規格化定数)経験的分布の特性を満たしつつエントロピーを最大にするモデル• 柔軟に素性を設定することが可能• 出力が確率cf. 確率的言語モデル 6章
  44. 44. 素性関数fb,s(x, y) =1 if b(x) is true and y = s0 otherwise素性の有無を表す2値関数• e.g.文書のクラスが class1 で最初が数字で始まれば1,そうでなければ0• 単語文書行列を扱う場合は「コーパスの語彙数」x 「クラス数」個の素性関数が存在し、出現頻度などを返す関数fbegins−with−number,class1
  45. 45. ME モデルの学習対数尤度を最大化するパラメータを求める• 解探索アルゴリズム‣ L-BFGS(省メモリな準ニュートン法)‣ GIS (Generalized Iterative Scaling)• L1、L2 正則化で過学習を防ぐことも‣ L2 正則化をする場合の目的関数は次のとおりL(P|λ) =(xi,yi)log P(yi|xi)L(P|λ) =(xi,yi)log P(yi|xi) −12σ2||λ||2← 凸関数
  46. 46. R で ME モデル library(maxent) model - maxent(trainData, trainTopic) pred - predict(model, testData)[, labels] (tbl - table(pred, truth = testTopic))truthpred 16 2016 190 3620 30 163 sum(diag(tbl)) / sum(tbl)[1] 0.8424821
  47. 47. SVM
  48. 48. サポートベクターマシン(SVM)2つのクラス間のマージンを最大化させるモデルy = sgn [f(x)] =1 if f(x) ≥ 0−1 if f(x) 0f(x) =xi∈SVαik(xi, x)• パラメータ数の割に過学習に陥りにくい• カーネル関数により複雑な素性を容易に扱うことが可能• 構築したモデルの解釈や分類結果の要因の解明が難しい• 多クラス分類をするには一工夫必要cf. カーネル多変量解析 4章
  49. 49. ===高次元空間に写像することで非線形問題を線形問題にする変換00000線形分離不可能(非線形問題) 線形分離可能(線形問題)例カーネル法の概要
  50. 50. カーネル法の概要入力 特徴ベクトル 線形多変量解析入力空間 特徴空間入力空間x f(x) = wTφ(x)単純に高次元空間に写像すると計算量が増える
  51. 51. 入力 特徴ベクトル カーネル多変量解析入力空間 特徴空間入力空間x f(x) =ni=1αikx(i), x)= wTφ(x)(カーネル関数)kx(i), x= φ(x(i))Tφ(x)kカーネル関数が高次元空間での計算を隠 (カーネルトリック)カーネル法の概要
  52. 52. カーネル関数• 線形カーネル‣ 現在の特徴空間で SVM などを適用させたい時に使用• ガウスカーネル‣ データの特性を維持したまま無限次元空間に写像• 多項式カーネル‣ 素性間の相互作用も考慮した空間に写像‣ 文字列カーネル cf. 文字列カーネルSVMによる辞書なしツイート分類‣ 文字列を部分文字列の出現回数から成る空間に写像cf. 自然言語処理におけるカーネル法の利用 (PDF)カーネル関数によって写像する特徴空間は異なるk(x, x) = xTxk(x, x) = exp(−βx − x2)k(x, x) = (xTx+ c)p
  53. 53. SVM の学習dカーネル空間で2クラス間のマージン を最大化するように学習‣ ソフトマージン最大化‣ 誤分類されるものにはペナルティを設けることで誤分類を許容‣ 凸二次計画問題に帰着できる(SMO などで解く)||w||2= αTKα kij = k(xj, xi)K = (kij), ,カーネル関数minξ,α12||w||2+ CniξiSubject to ∀i : yif(x) ≥ 1 − ξiサポートベクトルf(x) =xi∈SVαik(xi, x)
  54. 54. R で SVM library(kernlab) model - ksvm(trainData, trainTopic,+ kernel = vanilladot, kpar = list(),+ scaled = FALSE) pred - predict(model, testData) (tbl - table(pred, truth = testTopic))truthpred 16 2016 184 2820 36 171 sum(diag(tbl)) / sum(tbl)[1] 0.8472554
  55. 55. まとめ
  56. 56. ・・・の前に
  57. 57. ごめんなさいm(_ _)m
  58. 58. やれなかったこと• LSI cf. 潜在的意味インデキシング(LSI)徹底入門 - あらびき日記• LDA(topicmodels パッケージ)• 文書クラスタリング cf. Rで学ぶクラスタ解析‣ 階層的クラスタリング(hclust 関数)‣ k-means(kmeans 関数)• 系列ラベリング cf. HMM, MEMM, CRF まとめ - あらびき日記‣ HMM‣ MEMM• データの前処理‣ 文書中の URL の除去(置換)‣ Unicode 正規化 cf. abicky/RUnicode · GitHub• KNB コーパスを使ってごにょごにょ cf. KNB corpus parser for R
  59. 59. まとめ自然言語処理おもしろいですね!

×