入力データを作成して、学習させる

早速、訓練データとテストデータを作成してみたいと思います。非常に簡単な例として、一次関数のグラフを書いて、適当に点をプロットして、そのグラフよりも下にある点を+1、そのグラフよりも上にある点を-1としたものをデータとして与えることを考えます。適当にPerlでプログラムを書いてみました。

第一引数がxの範囲(0<x<与えた値)、第二引数がxの範囲(0<y<与えた値)、第三引数がグラフの傾き、第四引数が出力データ数です(あまり細かいチェックはしていません…)。このプログラムを実行すると、次の出力が得られます。

とりあえず、一次関数の傾きが1のものと5のもののデータを、訓練用とテスト用それぞれ100データ生成し、訓練用のデータを学習させ、識別までさせてみようと思います。

イメージとしては、次のような感じです。

150119

まずは、傾きが1のもの。

次に、傾きが5のもの。

両方共、PrecisionもRecallも高い数値が出ています。狙いどおりの結果になったと思います。

これより先の文章は(これまでにも増して)、さらにいい加減なものですが…

これを、仮に、モデルを入れ替えて識別させてみるとどうでしょう。つまり、y<xのモデルにy<5xのデータを与えてみた場合と、y<5xのモデルにy<xのモデルを与えてみた場合の出力を試しに見てみようと思います。

上のほうが、y<5xのデータに対して、y<xのモデルで識別した場合です。Precisionが100%ですね。逆にy<xのデータに対してy<5xのモデルで識別した場合はRecallが100%となっています。考えてみればなんとなく分かることですが、学習によって推定された境界線と、実際にテストとして与えたデータを重ねてみると、上記の結果になることは視覚的に分かると思います…、が、多分間違った使い方のような気もしています。

とはいえ、とりあえず、実際にデータを作成して訓練と識別を実際にしてみることで、SVMの使い方が具体的になったと思います。

次は、もう少しSVMが中でしている計算などを追ってみたいのですが、少し勉強のため日が開くと思います…。

モデルを評価する(補足)

交差検証という名称について

前のエントリーで、交差検証について書きましたが、交差検定と呼ばれることもあります(ありました?)。ただ、検定というと、統計学の用語であって、あらぬ誤解を生む可能性があるので、交差検証又は交差確認という言葉を使うほうが良いかもしれません。

精度と再現率の調和平均について

また、前のエントリーで、精度と再現率はトレードオフの関係と書きました。そこで、これら2つの調和平均を計算して、この値が高ければ、バランスの良いモデルができているんじゃないか、と判断することができそうです。

精度と再現率の調和平均のことをF値(F-measure)と呼んでいます。

 F = \displaystyle \frac{2 \cdot Precision \cdot Recall}{Precision + Recall}

また、どちらかにウェイトを置いて計算するときは、次の式を用います。

 F_{\beta} = \displaystyle \frac{(1+\beta^{2}) \cdot Precision \cdot Recall}{\beta^{2} \cdot Precision + Recall}

例えば再現率を重視するスコアとして、F3スコア(下の式でβの値を3にしたもの)を用いる場合があります。

モデルを評価する

作成したモデルが良いものであるか、そうでないかを判断するにはどうすればよいでしょうか。よく使われる手法としては、交差検証(分割交差検証、n-fold cross-validation)が行われます。

n-fold cross-validation

これは、クラスとベクトルが全て分かっているデータを用意したときに、そのデータをnグループに分割し、n-1のグループ(訓練用のグループ)のデータを使ってモデルを作成し、残りの1グループ(テスト用のグループ)でどれだけ正解に近いクラス分けができるかを数値的に検証するものです。これを、テスト用のグループを変えることによってn通り検証し、数値結果を平均して、全体のモデルの良さを計算するのが、分割交差検証です。

数値的な評価

正解のクラスというのが既に分かっていて、それとは別にSVMによってクラスに属するか属さないかという出力が得られます。この2つの組み合わせは、以下のマトリクスに分けることが出来ます。

150116

つまり、文にすれば下記の4通りがあるということです。

  • 正解データではクラスに属すものであって、SVMもクラスに属すものと判定した(上の表のAのもの。正しい判断をしている)
  • 正解データではクラスに属すものではないのに、SVMはクラスに属すものと判定した(上の表のBのもの。間違った判断をしている)
  • 正解データではクラスに属すものであるのに、SVMはクラスに属さないものと判定した(上の表のCのもの。間違った判断をしている)
  • 正解データではクラスに属さないものあって、SVMもクラスに属さないものと判定した(上の表のDのもの。正しい判断をしている…かもしれない)

正解っぽいのは、AとDに含まれるものです。TinySVMでは、テスト用のデータのうち、AかDに属したものの割合を、Accuracyとして計算しています。

 Accuracy = \displaystyle \frac{A+D}{A+B+C+D}

しかし、あまりこのAccuracyが重要視されることは、著者の個人的な印象ではあまり無いように思えます。というのも、例えばテストデータが1000あって、そのうちクラスに属すものが10程度しか無かった場合、全てをクラスに属さないと判定すれば、それだけでAccuracyが99%となるからです。

それよりも重要な事は、クラスに属すべきものが、正しくクラスに属すと判定されることです。つまり上の表で言うとAの部分にどれだけ入ったかが重要です。ただし、Aに属すデータの数は、テストするデータのサイズにもよりますし、クラスに含まれるデータの数にもよります。従って割合で示す必要があるのですが、この割合を計算する方法が、2つあります。

一つは、精度(Precision, 適合率)であり、これは、SVMがクラスに属すと判断したもののうち、本当の正解でもクラスに属すものであった割合を言います。

 Precision = \displaystyle \frac{A}{A+B}

もう一つは、再現率(Recall)であり、これは、本当の正解でクラスに属すものであったもののうち、どれだけSVMがクラスに属すと判断したかの割合を言います。

 Recall = \displaystyle \frac{A}{A+C}

これら2つは基本的にトレードオフの関係にあるものです。つまり、SVMが全てのデータに対してクラスに属すと判定すれば、再現率は1となります。しかし、精度は相当低いものとなるでしょう。逆に、クラスに属すと判断するハードルを相当上げれば、精度は上がるでしょうけれど、再現率は下がりそうですね。

この2つの値が、うまく調和するように入力データやSVMを調整する必要がありそうです。

次回は、SVMにオリジナルのデータを入力して観察してみたいと思います。

SVMに入力するデータについて

前回のエントリーでSVMにはベクトルを入力すると言いました。また、学習のためには、そのベクトルがそのジャンルに含まれるか含まれないか、という目印も必要です。

これまでジャンル、という曖昧な言葉を使っていましたが、今後は、そのような事を表す言葉で、機械学習でよく使われる用語である「クラス」、という言葉を使おうと思います。

つまり、クラスとベクトルの2つの情報を使って学習させるということです。

以下は、TinySVMの訓練データのフォーマットです。TinySVMのページから、入力データに関する部分を以下に引用します。

1行が1つのデータに相当し、行頭に+1か-1、その後に整数と実数をコロンでつないだものが連なっています。行頭の+1か-1がクラスに属すかどうか(+1なら属す、-1なら属さない)を示し、その後のデータがベクトルを表現しています。

コロンの前がベクトルの添字、コロンの後がそのベクトルの添字で示される要素の値を示します。添字がなければ、その要素は0となります。

150115

クラスに属すか属さないかを、ベクトルの要素を使って識別するのですが、これらの要素のことを「素性」と呼びます。なお、すじょう、ではなく、「そせい」と読みます。

SVMに与える情報として、どのような素性が役に立ちそうか、どの素性を用いればより正確に分類ができるかは、解こうとする問題にもよるため、この素性が良い、というのは一概には言えませんし、ある種職人芸的な部分でもあります。

とりあえず入力データについては分かったので、次は評価について書いてみたいと思います。

TinySVM: svm_learnのパラメータについて

前回は、TinySVMのインストールと実行をしてみました。ここで少し、実行時に使ったパラメータについて観察してみます。

TinySVM svm_learnのパラメータ

150114

svm_learnの実行のテストに使ったコマンドは上に書いたとおりですが、前回のエントリーで、最後から2番めのパラメータは入力データのパス、最後のパラメータがsvm_learnが出力するモデルファイルのパスであることを書きました。

ところで、それよりも前のパラメータは何でしょうか…。この答えが、図にも書いてあるように、SVM自体のパラメータとなっています。図にはかなりいい加減に「SVMの性格を決めるパラメータ」と適当に書いてありますが、ただ、このパラメータを変えると、同じ入力データでも生成されるモデルは変わってきます。

パラメータの詳しい説明は、Manpage of SVM_LEARNにあるとおりですが、これらについての説明は、SVMの数式を若干出す必要があることもあって、とりあえず今は省略します。

良いモデルを作るには

結局モデルを作るためには、良い入力データを与え、それにマッチしたSVMを用いることが重要です。

ところで、SVMで入力するデータはベクトルです。ベクトルといっても、大きさと向きを持った量というよりは、行列の行ベクトル(若しくは列ベクトル)という感じで、数を並べたものと考えるほうが良いでしょう。

画像を分類したり、文書を分類したりする時、そのままのデータをSVMは理解できません。従って、人間がそれらのデータからベクトルを作成してSVMに与えるのです。

このベクトルの作り方が上手でないと、SVMが優秀だとしても、良いモデルは作れません。従って、この入力データ作り、というのが、また一つの問題としてあるのです。

次回は、SVMに与える入力データの形式についてまとめてみたいと思います。

1 2 3