R による文書分類入門

59
R による自然言語処理入門 Tokyo.R #31 (2013/06/01) @a_bicky 文書分類

description

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

Transcript of R による文書分類入門

Page 1: R による文書分類入門

R による自然言語処理入門Tokyo.R #31 (2013/06/01)

@a_bicky

文書分類

Page 2: R による文書分類入門

自己紹介• Takeshi Arabiki

‣ 平凡な Web エンジニア(主に JavaScript)

‣ Twitter & はてな: @a_bicky & id:a_bicky

‣ e-mail:

• 興味など機械学習、自然言語処理

• ブログあらびき日記 http://d.hatena.ne.jp/a_bicky/

Page 3: R による文書分類入門

R関係の主な発表

Rユーザ会 2011Tokyo.R #16

http://www.slideshare.net/abicky/r-9034336 http://www.slideshare.net/abicky/r-10128090

Tsukuba.R #9

http://www.slideshare.net/abicky/rtwitter

Page 4: R による文書分類入門

Rによる文書分類入門

Page 5: R による文書分類入門

基礎知識

Page 6: R による文書分類入門

形態素解析

• 文を形態素(意味の最小単位)に分割‣ 日本語自然言語処理における “単語” はたいてい形態素のこと

‣ e.g. 「お酒」→「お」+「酒」(形態素の定義は曖昧)

• 各形態素の品詞推定‣ e.g. 「お(接頭詞)」+「酒(名詞)」

自然言語で書かれた文を形態素(Morpheme, おおまかにいえば、言語で意味を持つ最小単位)の列に分割し、それぞれの品詞を判別する作業を指す。

引用: 形態素解析 - Wikipedia

つまり・・・

Page 7: R による文書分類入門

mecab による形態素解析

$ mecabハードルは高ければ高いほどくぐりやすいハードル名詞,一般,*,*,*,*,ハードル,ハードル,ハードルは助詞,係助詞,*,*,*,*,は,ハ,ワ高けれ 形容詞,自立,*,*,形容詞・アウオ段,仮定形,高い,タカケレ,タカケレば助詞,接続助詞,*,*,*,*,ば,バ,バ高い 形容詞,自立,*,*,形容詞・アウオ段,基本形,高い,タカイ,タカイほど 助詞,副助詞,*,*,*,*,ほど,ホド,ホドくぐり動詞,自立,*,*,五段・ラ行,連用形,くぐる,クグリ,クグリやすい 形容詞,非自立,*,*,形容詞・アウオ段,基本形,やすい,ヤスイ,ヤスイEOS

入力文

出力

Page 8: R による文書分類入門

ベクトル空間モデル

• 素性 (feature) の取り方はいろいろ• Unigram model (Bag-of-Words model)

‣ 1つの単語を1つの素性とする

‣ 単語の出現順は考慮しない(文書を単語の袋詰めとみなす)e.g. 「赤ちゃんと僕」と「僕と赤ちゃん」は同じベクトルになる

• N-gram model‣ 連続する n 単語を1つの素性とするe.g. 「赤ちゃんと僕」→ <s>赤ちゃん, 赤ちゃんと, と僕, 僕</s> 「僕と赤ちゃん」→ <s>僕, 僕と, と赤ちゃん, 赤ちゃん</s>

そせい

文書をベクトル空間の1点として表現する

Page 9: R による文書分類入門

単語の重み付け• 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}|

Page 10: R による文書分類入門

単語文書行列

D =

d1 d2 · · · dM

t1 0 1 . . . 0

t2 2 0 . . . 0...

......

. . ....

tV 1 0 . . . 2

各文書ベクトルを列に並べた行列e.g. あるコーパスに対する TF 値による単語文書行列

文書 の文書ベクトル文書 における単語 の出現回数

d2dM tV

Page 11: R による文書分類入門

単語文書行列の作成

> library(RMeCab)> > pos <- c("名詞", "動詞", "形容詞", "副詞", "連体詞")

> texts <- c("ハードルは高ければ高いほどくぐりやすい",

+ "タダより高いものはない")

> > D1 <- docMatrixDF(texts, pos = pos, weight = "tf")to make data frame

# 抽出する形態素の品詞

RMeCab を使うことで手軽に単語文書行列が作成可能

# TF 値による単語文書行列を作成

Page 12: R による文書分類入門

> D1 OBS.1 OBS.2 1 0 0 1 0 1 1 0 0 1 1 0 2 1

単語文書行列の作成

くぐるないものやすいタダハードル高い

RMeCab を使うことで手軽に単語文書行列が作成可能

Page 13: R による文書分類入門

N-gram による行列> > D2 <- t(docNgramDF(texts, type=1, pos=pos, N=2))

number of extracted terms = 7to make matrix now> D2 Row1 Row2 1 0 0 1 0 1 1 0 1 0 0 1 1 0

[くぐる-やすい][もの-ない][タダ-高い][ハードル-高い][高い-くぐる][高い-もの][高い-高い]

# 2-gram (bigram) による行列を作成

Page 14: R による文書分類入門

疎行列

• 単語文書行列は多くの場合疎行列• 非零要素のインデックスとその値だけを保持(省メモリ化)

‣ データの格納形式には CSC、CSR、COO などがある

• R の代表的なパッケージは Matrix‣ 基本的な操作は普通の行列と同様に行うことが可能

‣ 疎行列に対応していない関数は普通の行列に変換する必要あり

‣ 普通の行列では R の制限で作成できない大規模な行列も作成可能

行列の多くの要素が 0 である行列

Page 15: R による文書分類入門

疎行列への変換

> library(Matrix)> (sm <- as(D1, "CsparseMatrix"))7 x 2 sparse Matrix of class "dgCMatrix" OBS.1 OBS.2 1 . . 1 . 1 1 . . 1 1 . 2 1

くぐるないものやすいタダハードル高い

# CSC 形式の疎行列に変換

Page 16: R による文書分類入門

> str(sm)Formal class 'dgCMatrix' [package "Matrix"] with 6 slots ..@ 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)

非零の要素の値

Page 17: R による文書分類入門

CSC 形式CSC (= Compressed Sparse Column)

i 0 3 5 6 1 2 4 6

x 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 8

0 列目はここから1 列目はここから

Page 18: R による文書分類入門

疎行列の操作

> 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.2 0 1 0 1

# 3行目と5行目を抽出

ものタダ

# 各文書の単語数を算出

# 各単語の出現回数を算出

ものタダ

# 普通の行列に変換

基本的な操作は普通の行列と同様に行うことが可能

Page 19: R による文書分類入門

文書分類

Page 20: R による文書分類入門

文書分類• 今回扱うのは2クラス分類

‣ e.g. 受信したメールがスパムメールかどうか

• 扱う手法‣ 決定木(CART)

‣ ナイーブベイズ

‣ 最大エントロピー (ME) モデル

‣ サポートベクターマシン (SVM)

Page 21: R による文書分類入門

サンプルデータ

> 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 のものだけ使用

# クラスラベル

# 単語文書行列

Page 22: R による文書分類入門

サンプルデータ

> > 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 データを使用

Page 23: R による文書分類入門

ナイーブベイズ

Page 24: R による文書分類入門

ナイーブベイズデータの生成確率(条件付き確率)を最大化するクラスを選択

• 単純なモデルなので実装が楽(R で10行!!)

‣ cf. 10行でナイーブベイズ ~Rって便利だね!~ - あらびき日記

• 学習も高速

• 特定のクラスに出現しない単語の対処が必要(ディスカウンティング)

y = argmaxy

N�

i=1

logP (wi|y) + logP (y)

Page 25: R による文書分類入門

確率的言語モデル• 単語列 の同時確率 を与えるモデル• 文書の生成方法をモデル化

‣ に従って単語列を生成することで文書を生成可能

wN1 = w1w2 · · ·wN

w NM

unigram の例(各単語が独立と仮定)

P (wN1 )

P (wN1 )

P (d) = P (wN1 ) =

N�

i=1

P (wi)

Page 26: R による文書分類入門

Unigram Mixtures

w NM

クラスごとに unigram を割り当てるモデル

• カテゴリの異なる文書は単語の出現確率も異なるはず• 各文書は1つのクラス(トピック)から生成されると仮定

P (d) =�

y

P (y)N�

i=1

P (wi|y)

y = argmaxy

N�

i=1

P (wi|y)P (y)

ナイーブベイズはこの値を最大化するクラスを真のクラスと推定する

y

Page 27: R による文書分類入門

ディスカウンティング• ナイーブベイズの問題点

‣ あるクラスの学習データに存在しない単語を含む文書は決してそのクラスに分類されない(ゼロ頻度問題)

- e.g. 0.9 x 0.95 x 0.8 x 0.99 x 0 = 0

• 加算法‣ 全単語に関して出現頻度を一律 +δ する

‣ あるクラスの学習データに現れない単語でも δ回出現しことになる

• 単純グッド・チューリング推定法‣ 加算法より洗練されたディスカウンティング方法

‣ cf. 単純グッド・チューリング推定法 (Simple Good-Turing Estimation) とは何ぞや? - あらびき日記

Page 28: R による文書分類入門

ナイーブベイズを実装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")}

# 各クラスにおける単語出現頻度

# ラプラススムージングによるクラスごとの単語の出現確率

# 各クラスの生成確率# 各クラスに所属する文書数

Page 29: R による文書分類入門

ナイーブベイズを実装

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]}

# 予測用の関数

Page 30: R による文書分類入門

R でナイーブベイズ> model <- myNaiveBayes(trainData, trainTopic)> pred <- predict(model, testData)> (tbl <- table(pred, truth = testTopic)) truthpred 16 20 16 193 33 20 27 166> sum(diag(tbl)) / sum(tbl)[1] 0.8568019

# 正解率

Page 31: R による文書分類入門

決定木 (CART)

Page 32: R による文書分類入門

決定木 (CART) の概要根ノードから各ノードの判定基準に従って辿り着いた葉ノー ドによりクラスを分類

Yes No

Yes No

C1

C1 C2

A0

A1

• 量的変数と質的変数の混在する素性を容易に扱える• 構築したモデルの解釈や分類結果の要因の解明がしやすい• 大規模な素性を扱うには不向き• R では CART が使われる• CART は二分木を生成する

Page 33: R による文書分類入門

• 不純度の減少を最大化させるようにノードを生成= ノード生成後の不純度を最小化させるようにノードを生成

‣ 不純度:

はノード A に存在する i 番目のクラスのデータの割合

‣ Gini 係数:

‣ 情報エントロピー:

クラスの分布に偏りがあるほど不純度は小さくなる(小さい程良い)

‣ 不純度の減少量:

CART の学習

I(A) =�

i

f(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

Page 34: R による文書分類入門

CART の学習例

Yes No

AL AR

A

(50, 50)

(15, 32) (35, 18)

素性1 > 0

クラス1とクラス2のデータが50個ずつある場合

Page 35: R による文書分類入門

クラス1とクラス2のデータが50個ずつある場合

Yes No

AL AR

A

(50, 50)

(15, 32) (35, 18)p1AL =

15

47

p2AL =32

47

p1AR =35

53

p2AR =18

53

p(AL) =47

100 p(AR) =53

100

p1A =50

100

p2A =50

100

p(A) = 1

素性1 > 0

∆I = p(A)2�

i=1

piA(1− piA)− p(AL)2�

i=1

piAL(1− piAL)−2�

i=1

piAR(1− piAR)

= 0.058

CART の学習例

Page 36: R による文書分類入門

Yes No

AL AR

A

(50, 50)

(7, 29) (43, 21)

p1A =50

100

p2A =50

100

p(A) = 1

素性2 > 0

∆I = p(A)2�

i=1

piA(1− piA)− p(AL)2�

i=1

piAL(1− piAL)−2�

i=1

piAR(1− piAR)

p1AL =7

36

p2AL =29

36

p1AR =43

64

p2AR =21

64

p(AL) =36

100 p(AR) =64

100

= 0.105 こちらの分割方法の方が不純度の減少量が大きい(良い分割方法)

CART の学習例クラス1とクラス2のデータが50個ずつある場合

Page 37: R による文書分類入門

1-SE ルール

1 2 3 4 5 6

Yes No

Yes No

C1

C2

A0

A1

Yes No

Yes No

A2

A3 A4

A5C2

葉ノードの数

CVエラー

クロスバリデーション (CV) エラーとその標準偏差を基準に枝刈り

CVエラーの最小値

枝刈りすることで過学習を抑制

Page 38: R による文書分類入門

1 2 3 4 5 6

Yes No

Yes No

C1

C2

A0

A1

Yes No

Yes No

A2

A3 A4

A5C2

CVエラーの最小値+標準偏差

クロスバリデーション (CV) エラーとその標準偏差を基準に枝刈り

葉ノードの数

CVエラー

枝刈りすることで過学習を抑制

1-SE ルール

Page 39: R による文書分類入門

1 2 3 4 5 6

Yes No

Yes No

C1

C2

A0

A1

Yes No

Yes No

A2

A3 A4

A5C2

CVエラーの最小値+標準偏差を最初に下回る点

クロスバリデーション (CV) エラーとその標準偏差を基準に枝刈り

葉ノードの数

CVエラー

枝刈りすることで過学習を抑制

1-SE ルール

Page 40: R による文書分類入門

1 2 3 4 5 6

Yes No

Yes No

C1

C2

A0

A1

Yes No

Yes No

A3 A4

A5C2

枝刈り C1

クロスバリデーション (CV) エラーとその標準偏差を基準に枝刈り

葉ノードの数

CVエラー

枝刈りすることで過学習を抑制

1-SE ルール

Page 41: R による文書分類入門

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 20 16 88 6 20 132 193> sum(diag(tbl)) / sum(tbl)[1] 0.6706444

Page 42: R による文書分類入門

ME モデル

Page 43: R による文書分類入門

最大エントロピー (ME) モデル

P (y|x) = 1

Z(x)exp

��

i

λifi(x, y)

�=

1

Z(x)exp

�λTf(x, y)

Z(x) =�

y∈Yexp

�λTf(x, y)

�(規格化定数)

経験的分布の特性を満たしつつエントロピーを最大にするモデル

• 柔軟に素性を設定することが可能• 出力が確率

cf. 確率的言語モデル 6章

Page 44: R による文書分類入門

素性関数

f�b,s�(x, y) =

�1 if b(x) is true and y = s0 otherwise

素性の有無を表す2値関数

• e.g.文書のクラスが class1 で最初が数字で始まれば1,そうでなければ0

• 単語文書行列を扱う場合は「コーパスの語彙数」x 「クラス数」個の素性関数が存在し、出現頻度などを返す関数

f<begins−with−number,class1>

Page 45: R による文書分類入門

ME モデルの学習対数尤度を最大化するパラメータを求める

• 解探索アルゴリズム‣ L-BFGS(省メモリな準ニュートン法)

‣ GIS (Generalized Iterative Scaling)

• L1、L2 正則化で過学習を防ぐことも‣ L2 正則化をする場合の目的関数は次のとおり

L(P |λ) =�

(xi,yi)

logP (yi|xi)

L(P |λ) =�

(xi,yi)

logP (yi|xi)−1

2σ2||λ||2

← 凸関数

Page 46: R による文書分類入門

R で ME モデル> library(maxent)> model <- maxent(trainData, trainTopic)> pred <- predict(model, testData)[, "labels"]> (tbl <- table(pred, truth = testTopic)) truthpred 16 20 16 190 36 20 30 163> sum(diag(tbl)) / sum(tbl)[1] 0.8424821

Page 47: R による文書分類入門

SVM

Page 48: R による文書分類入門

サポートベクターマシン(SVM)2つのクラス間のマージンを最大化させるモデル

y = sgn [f(x)] =

�1 if f(x) ≥ 0−1 if f(x) < 0

f(x) =�

xi∈SV

αik(xi,x)

• パラメータ数の割に過学習に陥りにくい• カーネル関数により複雑な素性を容易に扱うことが可能• 構築したモデルの解釈や分類結果の要因の解明が難しい• 多クラス分類をするには一工夫必要cf. カーネル多変量解析 4章

Page 49: R による文書分類入門

= = =

高次元空間に写像することで非線形問題を線形問題にする

変換

0

0

0

0

0

線形分離不可能(非線形問題) 線形分離可能(線形問題)

カーネル法の概要

Page 51: R による文書分類入門

入力 特徴ベクトル カーネル多変量解析

入力空間 特徴空間入力空間

x f(x) =n�

i=1

αik�x(i),x)

�= wTφ(x)

(カーネル関数)

k�x(i),x

�= φ(x(i))Tφ(x)

k

カーネル関数が高次元空間での計算を隠蔽(カーネルトリック)

カーネル法の概要

Page 52: R による文書分類入門

カーネル関数• 線形カーネル

‣ 現在の特徴空間で SVM などを適用させたい時に使用

• ガウスカーネル‣ データの特性を維持したまま無限次元空間に写像

• 多項式カーネル‣ 素性間の相互作用も考慮した空間に写像

‣ 文字列カーネル cf. 文字列カーネルSVMによる辞書なしツイート分類

‣ 文字列を部分文字列の出現回数から成る空間に写像

cf. 自然言語処理におけるカーネル法の利用 (PDF)

カーネル関数によって写像する特徴空間は異なるk(x,x�) = xTx�

k(x,x�) = exp(−β�x− x��2)

k(x,x�) = (xTx� + c)p

Page 53: R による文書分類入門

SVM の学習dカーネル空間で2クラス間のマージン を最大化するように学習

‣ ソフトマージン最大化

‣ 誤分類されるものにはペナルティを設けることで誤分類を許容

‣ 凸二次計画問題に帰着できる(SMO などで解く)

||w||2 = αTKα kij = k(xj ,xi)K = (kij), ,

カーネル関数

minξ,α

1

2||w||2 + C

n�

i

ξi

Subject to ∀i : yif(x) ≥ 1− ξi

サポートベクトル

f(x) =�

xi∈SV

αik(xi,x)

Page 54: R による文書分類入門

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 20 16 184 28 20 36 171> sum(diag(tbl)) / sum(tbl)[1] 0.8472554

Page 55: R による文書分類入門

まとめ

Page 56: R による文書分類入門

・・・の前に

Page 57: R による文書分類入門

ごめんなさいm(_ _)m

Page 58: R による文書分類入門

やれなかったこと• 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

Page 59: R による文書分類入門

まとめ

自然言語処理おもしろいですね!