線形モデルによる多クラス分類

概要

この項はO’REILLYの「Pythonではじめる機械学習」の「2.3.3.6 線形モデルによる多クラス分類」を自分なりに理解しやすいようにトレースしたもの。扱いやすい仮想のデータセットを生成し、LinearSVCモデルでこれらを分類する流れを例示している。

例えば特徴量x1xnのデータxC1, C2の2クラスに分類する線形モデルは以下とおり。

(1)    \begin{gather*} y = b + w_1 x_1 + \cdots + w_n x_n \\ \left\{ \begin{array}{ll} y \ge 0 \quad \rightarrow \quad \boldsymbol{x} \in C_1 \\ y < 0 \quad \rightarrow \quad \boldsymbol{x} \in C_2 \end{array} \right. \end{gather*}

yの符号によってどちらのクラスに分類されるかを決定するが、1つの式で3つ以上のクラスを分類することはできない(ただし一般化線形モデル(GLM)であるLogistic回帰は多クラス分類が可能)。

このような2クラス分類を多クラス分類に拡張する方法の一つが1対その他(one-vs-rest, one-vs-the-rest, 1vR)という考え方で、1つの式によって、あるクラスとその他すべてのクラスを分けようというもの。この式の形は(1)と同じで、yの値は与えられたデータがそのクラスに属する確信度(confidence)を表す。クラスの数だけこの分類器(one-vs-the-rest-classifier)を準備し、あるデータが与えられたとき、最も確信度が高いクラスに属すると考える。たとえばn個の特徴量を持つデータの3クラス分類の場合、次のように3つの分類器を準備し、与えられたデータxycの値が最も大きいクラスに属する。

(2)    \begin{gather*} y_0 = b_0 + w_{01} x_1 + \cdots + w_{0n} x_n \\ y_1 = b_1 + w_{11} x_1 + \cdots + w_{1n} x_n \\ y_2 = b_2 + w_{21} x_1 + \cdots + w_{2n} x_n \end{gather*}

LinearSVCによる多クラス分類の例

データの準備

準備として、shikit-leran.datasetsmake_blobs()で、2つの特徴量と3つのクラスのデータセットを生成する。

LinearSVCによる学習

学習とモデルの形

scikit-learn.linear_modelLinearSVC(Linear Support Vector Classification)は多クラス分類のモデルを提供する。このモデルをmake_blobs()で生成したデータで学習させると、3行2列の係数(LinearSVC.coef_)と3要素の切片(LinearSVC.intercept_)を得る。

これらの係数の行と切片の要素は分類されるべきクラス、係数の列は特徴量に対応している。クラスに対するインデックスをc = 0, 1, 2、特徴量f0, f1に対するインデックスをf= 0, 1とすると、上記の結果は以下のような意味になる。

(3)    \begin{align*} w_{cf} &= \left[ \begin{array}{rrr} -0.17492222 & 0.23140089 \\ 0.4762125 & -0.06936704 \\ -0.18914556 & -0.20399715 \end{array} \right] \\ b_c &= [-1.07745632 \quad 0.13140349 \quad -0.08604899] \end{align*}

これらの係数、切片を用いたクラス分類の予測式は以下の通りで、LinearSVCではdecision function(決定関数)とされている。

(4)    \begin{equation*} y_c = b_c + w_{c0} \times f_0 + w_{c1} \times f_1 \end{equation*}

あるデータの特徴量f0, f1に対して上記のycが正の時にはそのデータはクラスc、負の時にはクラスc以外であると判定される。

coef_intercept_の値は、実行ごとにわずかに異なる(10−6くらいのオーダー)。LinearSVCのコンストラクターの引数にrandom_stateが含まれていて、ドキュメントに以下のような記述があった。

The underlying C implementation uses a random number generator to select features when fitting the model. It is thus not uncommon to have slightly different results for the same input data. If that happens, try with a smaller tol parameter.The underlying implementation, liblinear, uses a sparse internal representation for the data that will incur a memory copy.

Predict output may not match that of standalone liblinear in certain cases. See differences from liblinear in the narrative documentation.

訓練データに対する決定関数・確信度

データセットの100個の各データに対してyc (c = 0, 1, 2)を計算した結果は以下の通り。

たとえばNo.0のデータはクラス2に属するので確信度はy2が正となり、他の2つのクラスに対しては負の値になっている。

上の計算ではintercept_coef_を使ってもともとの決定関数の式から確信度を計算したが、LinearSVCのdecition_function()メソッドで同じ結果を得ることができる。たとえばNo.0~2のデータで計算してみると以下の通りで同じ結果。

テストデータに対する予測

3つのテストデータを用意してクラス分類をしてみる。

各データとも分類されたクラスに対応する確信度が最も高い。ただし2つ目のデータについては全てのクラスに対する確信度が負の値で、その中で最も値が大きいクラス2に分類されている。

これらを図示すると以下のようになり、クラス2に分類された▼のデータは確かにどのデータにも属していそうな位置にある。

以上のコードをまとめておく。

LinearSVCの決定境界

クラスごとのone-vs-restの決定境界

blobsデータは明確に分かれた3つのクラスに分類され、それぞれに対する決定関数の切片と係数が得られた。そこで、各決定関数の決定関数の意思決定境界(decision boundary)を描いてみる。意思決定境界は決定関数の値がゼロとなる線なので、以下の式で表される。

(5)    \begin{gather*} b_c + w_0 f_0 + w_1 f_1 = 0 \quad \rightarrow \quad f_1 = \frac{-(b_c + w_{c0} f_0)}{w_{c1}} \end{gather*}

3つの決定関数について決定境界を描いたのが以下の結果。

たとえばClass 0の実線は、Class 0の塊とその他(Class1, Class 2)の塊を1対その他で分けている。この線の上側では確信度はプラスで、下側ではマイナスとなっている。

全体を融合した決定境界

先の図の中で、各クラスの塊の近くでは、そのクラスの決定関数の値はプラスで他はマイナスとなっているが、真ん中の三角形の中や、その対角にある三角形の領域では、複数の確信度がマイナスあるいはプラスとなる。このような場合には、全クラスに対して着目するデータの決定関数値を計算し、その確信度が最も大きいクラスをそのデータのクラスラベルとして与える。

以下の図は、領域内の点について全て確信度を計算し、各点において最も確信度が大きいクラスをその点のクラスとして表現した図である。

各領域の境界が3つの決定関数から導かれた意思決定境界であり、その線上で決定関数の値が等しくなっている。

 

4件のコメント

  1. 実際に数式を挟んで説明をして下さったので、非常に理解の助けになりました。

    1. コメントありがとうございます。
      私自身の理解のために整理したものですが、お役にたったようで幸いです。

  2. なんとなく画像の解析方法に役立ちそうです。

    ありがとうございます

    1. コメントありがとうございます。
      自身の勉強のために整理したものですが、少しでもお役に立てたのなら光栄です。

コウ へ返信する コメントをキャンセル

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です