BoW+SVMで文書分類(2)

はじめに

Livedoor Newsコーパスを学習データとして、カテゴリ分類する分類器を作成する記事の続き。

前回、文書分類を行う為の前準備として、各文書を数値化(ベクトル化)するところまでを行った。
今回は、前回作成した文書ベクトルをインプットにSVMを使い文書分類器を作るところまでを行う。

Livedoor Newsコーパスをトレーニングデータとテストデータに分割

Livedoor Newsコーパスは、カテゴリ毎にディレクトリが切られており、その中に1文書1ファイルで作成されている。このディレクトリ名がカテゴリ(教師ラベル)で、各ファイルをベクトル化したものをインプットとして機械学習させる。
また、作成した文書分類器の精度を検証する為のテストデータもこのLivedoor Newsコーパスのデータを使うこととする。
各カテゴリ毎に、80%を学習用データ、20%をテスト用データとして分けておく。

SVMとは

サポートベクターマシン(SVM)とは、教師あり学習データから、各データ点との距離が最大となるマージン最大化超平面を求めることでパラメータを学習する方法である。
話を単純にする為に、下図のような2次元平面の赤点のデータと緑点のデータ(教師ありデータ)を考えてみる。

svm

上図のように赤点と緑点を分割する最適なラインを求めることで、未知のデータに対してもそのラインの左上にあるのなら赤グループ、右下にあるのなら緑グループと分類することができるようになる。
ただし、赤点と緑点を分けるラインは複数考えられれ、上図の例ではいくつかの例としてH1からH3を描いている。
サポートベクターマシンは、各点からラインへ垂直に伸ばした線の距離(マージン)を最大化するようなラインのパラメータを学習する。
今回の例ではマージンが最大となるH1のパラメータが求められる。

上図は単純な2次元の線形サポートベクターマシンの例であるが、今回は300次元のデータに対して、複数カテゴリへの分類を非線形SVMを用いて行ってみる。
尚、SVMには非線形のカーネル関数が複数存在するが、今回はRBFを用いて行う。

Scikit-learnのSVMを用いてパラメータ学習

Pythonの機械学習ライブラリであるScikit-learnを用いて実際に分類器を作成してみる。
SVMでは、分類の精度を高める為に、ハイパーパラメータを決める必要がある。
幸いScikit-learnではGrid Searchの機能があり、複数のパラメータをリスト形式で渡してあげることで、最適なパラメータを見つけてくれる。

  • コストパラメータ(C):誤分類をどれくらい許容するのか決定
  • RBFカーネルのパラメータ(Γ):Γ値が大きいほど複雑な決定境界となり、小さいほど単純な境界となる

またScikit-learnでは、学習データを自動でランダムに分割して交差検定(クロスバリデーション)を行ってくれる。
デフォルトでは3-Fold Cross Validationとなっており、データを3分割しての交差検定を行う。

テストデータで精度の確認

さて、分類器のモデルはできたので、最初に分割した20%のデータで分類器の精度を検証してみる。

結果としては、以下の通りなのだが、最終テストスコアが0.795と思ったほどの精度がでていない。
学習データの再調整やSVMハイパーパラメータの調整を行いつつ、再テストを実施し、精度を上げていく必要がありそうだ。

BoW+SVMで文書分類(1)

はじめに

機械学習を用いドキュメント分類を行う為には、文書自体を数値(ベクトル)として扱う必要がある。文書を数値として扱う代表的な方法としては、Bag of Words(BoW)がある。これは、全文書中に登場する単語を並べて、各単語の出現頻度をベクトルで表す表現である。
今回、Livedoor Newsコーパスの各文書をBoWでベクトル化し、そのデータを用いて、カテゴリ分けする文書分類器を作成してみる。

Livedoor Newsコーパスについて

以下のURLよりLivedoor Newsコーパスをダウンロードできる。
Livedoor Newsコーパスは、ニュースカテゴリ毎にディレクトリが分かれている為、文書分類器作成の学習データとして適している。

Livedoor Newsコーパス
9カテゴリ、7386文書

各種インストール

Python3及び以下のライブラリ群を用いて実装した。

  • Mecab、mecab-python: 形態素解析
  • Gensim: Python用トピックモデルライブラリ
  • scikit-learn:Python用機械学習ライブラリ

手順

BoW+SVMでの文書分類器作成までの大まかな手順は以下の通り。

  1. Livedoor Newsコーパスの各文書をベクトル表現に変換
  2. Livedoor Newsコーパスをトレーニングデータとテストデータに分割
  3. SVMを使い学習
  4. SVMのパラメータ調整
  5. テストデータに適用

Livedoor Newsコーパスの各文書をベクトル表現に変換

BoWで各文書をベクトル表現に変換

機械学習を行う前準備として、各文書をBoWにてベクトル表現に変換する。
「はじめに」でも述べた通り、BoWとは全文書中に登場する単語を並べて、各文章でのそれぞれの単語の出現頻度を表したものである。
例えば、以下の2つの文書から各文書のベクトルを求めてみる。

これら2つの文書に登場する全単語を並べると以下の通りとなる。

上記から各文章のベクトルは、1番目の要素=単語”John”の出現回数、2番目の要素=単語”likes”の出現回数、、、といった形で表せる。
ちなみに上記(1)、(2)をベクトルで表すと以下の通りとなる。

実際には、文書量が多いと登場する単語数も膨大となる為、「全文書での出現頻度が極端に少ない単語」「どの文書にも登場するような一般的すぎるような単語」などは外してベクトルを作成する。
今回は、「出現頻度が20文書未満の単語」及び、「30%以上の文書で登場する単語」を排除した。この時点で、登場する総単語数は約9000となり、9000次元のベクトルとなった。

TF-IDFによる重み付け

ここで作成したBoWモデルに対して、より文書の特徴を捉えられるようTF-IDFを用いて重み付けを行った。
TFとはTerm Frequencyの略で、ある文書中の単語の出現頻度を表している。
DFとはDocument Frequencyの略で、どれくらいの文書でその単語が現れたのかを表しており、IDFとは、DFに対して対数を取ったものである。
この2つの値を掛けたものをそれぞれの単語の重みとしている。

LSIによる次元削減

さて、これである文書の特徴を表しているベクトルが作成できたわけであるが、このままではベクトルの次元数が大きすぎる為、学習コストが非常にかかってしまう。また有益な結果を得る為のサンプル数も非常に多くなってしまうのも問題である。
その為、文章の特徴を損なわなずにベクトルの次元削減を行う必要がある。

今回は、LSI(Latent Semantic Indexing)を用いて、次元削減を行ってみる。
LSIとは、SVD(Singular Value Decomposition:特異値分解)を用いた次元圧縮の方法で、単語の持つ潜在的な意味を軸に取ろうという発想である。
LSIを用いて、9000次元から300次元まで圧縮を行った。

今回は、機械学習の前準備として、文書群をそれぞれの文書の特徴を表しているベクトルに変換するところまでを行った。
次回は、これらのデータを用いて、学習及びパラメータ調整を行ってみる。

Word2Vec

はじめに

ここ数ヶ月、日本語の類義語分類に使えないかと、Word2Vecについて色々と調べてきたので以下に纏めてみる。

Word Embeddings

まず大前提として、自然言語を機械学習処理で扱う為には、文書や単語を数値として扱う必要がある。

$W : words \to \mathbb{R}^n$.

通常、自然言語処理に出てくる単語を数値で表す場合、高次元のベクトルを使って表す。(200〜500次元程度、word2vecのデフォルトは100次元)
例えば、「花」という単語が[0, 0, 0, 1, 0, 0.8, ….]といったベクトルで表すことができるようになる。
このように単語からベクトルへ変換する方法は多数存在しており、単純に全出現単語を並べて各次元でその単語かどうかを判断する方法やニューラルネットワークを使うものなどがある。

Word Embeddingとは、このうちニューラルネットワークなどを用いて単語の素性値を機械学習によって学習させ、ベクトル化する方法であり、分散表現とも呼ばれている。
Word Embeddingを使うことで、自然言語処理の各種タスクを効率よく行うことができるようになる。
Word Embeddingを使った有名な話としては、
$W(King)-W(Queen) \simeq W(Man) - W(Woman)$.
といったように、数式で単語を表せてしまうというものがある。

Word2Vec

Word2Vecとは、いわゆるWord Embeddingを作成する為の2層ニューラルネットワークのことであり、単語の特徴を文章のコンテキストから学習させている。
Word2Vecの学習後のモデルを使うことで、各単語を数百次元程度のベクトルとして表せるようになり、ベクトルのコサイン類似度を計算することで、単語同士の類似度を表すことができる。

例えば、「王」という単語に似ている単語の一覧も学習済みのWord2Vecのモデルを使うことで簡単に出すことができる。

又、2つの単語の類似度の計算も非常に低コストで行うことができる。
例えば、我々が学習させたWord2Vecのモデルでの「買う」と「購入する」の類似度は、
0.905990661338
なんて、計算される。

この結果を見る限り、類義語の抽出ができるのではと考えられるのだが、実際にはWord2Vecのみで類義語かどうかを判断するのは難しい。
例えば、「買う」と「売る」のコサイン類似度は、
0.847663039921
と非常に高い数値となっており、反対の意味を表す単語も抽出されてしまう。

これは、Word2Vecのアルゴリズムに由来しており、以下の説明を見ていただくと理解できると思う。

Continuous Bag-of-Words Model(CBOW)

Word2VecにはSkip-gramとContinuous Bag of Words(CBOW)の2つのアルゴリズムがある。

CBOWモデルは、コンテクスト(前後の単語)を使って対象語を推測する方法であり、$w_{t}$を推測する為の入力は、$w_{t-2}$, $w_{t-1}$, $w_{t+1}$, $w_{t+2}$となる。
前後いくつの単語を使って対象語を推測するのかを「ウィンドウサイズ」と言う。
Googleの研究者であり、Word2Vecの考案者であるMikolovによるとCBOWは学習時間がSkip-gramよりも少なく、頻出する単語に対してはSkip-gramより若干精度が高いとのこと。

CBOW

Skip-gram

反対にSkip-gramは、ある語を使って、前後のコンテクストを推測する方法である。
入力は$w_{t}$であり、アウトプットが、$w_{t-2}$, $w_{t-1}$, $w_{t+1}$, $w_{t+2}$となる。
Skip-gramは学習データが少なくてもある程度の精度がでるとされている。

skip-gram

まとめ

上記アルゴリズムを見ていただければわかる通り、Word2Vecはあくまで文脈から単語の特徴を計算しているため、類似度が高いからといって単語の意味が近いとは限らない。
どちらかと言うと同じような文脈で登場する単語同士は類似度が高い傾向にあり、例えば「好き」、「嫌い」といったように同じ文脈で登場するような単語は反対の意味であったとしても類似度が高い傾向にある。
とは言え、Word2Vecを使って単語をベクトル化させることで、文書分類など他の自然言語処理へのインプットとさせることは有用であると考える。