コンテンツにスキップ

EEIC前期実験i2 第3日

本日のメニュー

  • 線形識別
    • 分類問題の定義
    • 超平面での分離
    • パーセプトロン
    • kNNとベイズ分類
    • ロジスティック回帰
    • 多クラス拡張

はじめに

3日目は「教師あり学習」におけるもう一つの重要な問題である分類問題を扱っていく。回帰問題と異なり、分類問題では入力に対応する出力がカテゴリ情報 = 離散的なラベルとなる。

線形識別モデル

分類問題とは

これまで学んだ線形回帰では、入力変数から連続値を予測する問題を扱った。例えば、気温から電力消費量を予測したり、部屋の広さから家賃を予測したりする問題は回帰問題である。

一方、本日扱う分類問題では、入力データがどのカテゴリに属するかを予測する。

例えば、以下のような問題が分類問題に該当する。

  • メールがスパムかどうかを判定する
  • 手書き数字がどの数字であるかを判定する
  • 音声が特定の単語を含むかどうかを判定する
  • 画像に犬が写っているかどうかを判定する

分類問題では、予測対象は連続値ではなく離散的なラベルである。

例えば、スパムメール判定では、ラベル0が「通常メール」でラベル1が「スパムメール」を意味しているとして、メールから得られる特徴量を入力としてこのラベルを予測する。

二値分類

最も単純な分類問題は二値分類である。二値分類では、データを2つのクラスに分類する。

例えば、身長に応じて乗れるものに制限のあるネズミーランド(仮名)というものがあったとして、これまでのデータから利用の可否(クラス0/1)を予測する問題を考える。

身長(cm) クラス
150 0
155 0
160 0
170 1
175 1
180 1

この場合、160cmと170cmの間に境界を置けば、ある程度分類できそうである。

例えば、

  • 165cm未満ならクラス0
  • 165cm以上ならクラス1

とすればよい。

このような境界値を決める考え方は、実は後述の線形識別モデルを \(D=1\)で適用した場合と同様の考え方となる。


線形識別関数

線形識別モデルでは、入力ベクトル \(\mathbf{x}\) に対して線形関数

\[ g(\mathbf{x}) = \mathbf{w}^{\mathsf T}\mathbf{x}+b \]

を定義する。

ここで、

  • \(\mathbf{w}\) は重みベクトル
  • \(b\) はバイアス項

である。

分類は、この識別関数の符号によって行う。

\[ \hat{y} = \begin{cases} 1 & (g(\mathbf{x}) \ge 0) \\ 0 & (g(\mathbf{x}) < 0) \end{cases} \]

つまり、識別関数の値が正であればクラス1、負であればクラス0と判定する。線形回帰では予測値そのものに意味があった。一方、線形識別モデルでは識別関数の値そのものではなく、その符号に意味がある。またこのとき\(g(\mathbf{x})=0\) は境界を表すのでこれを決定境界や決定面と呼ぶ。


1次元の場合

まず、入力が1次元の場合を考える。

識別関数は

\[ g(x)=wx+b \]

となる。

分類境界は \(g(x)=0\) を満たす点である。よって \(wx+b=0\) より

\[ x=-\frac{b}{w} \]

が分類境界となる。

これは単なる閾値判定と同じである。

例えば、\(g(x)=x-165\) とすると、

  • \(x < 165\) のときクラス0
  • \(x \ge 165\) のときクラス1

となる。

したがって、1次元の線形識別モデルは「閾値を学習するモデル」と解釈できる。入力が1次元のため、超平面が0次元 = 点 となる。

演習(手動設定閾値による分類)

以下のデータに対して、\(g(x) = x - 165\) を決定境界とする分類を行うプログラムを実装せよ。

[150, 155, 160, 165, 170, 175, 180]
  • 出力は0 または 1を要素とするintのndarrayとする。
  • ヒント
    • for文は不要である

ここまでの例では境界値を人手で設定したが、機械学習ではこれをデータから学習することになる。

2次元の場合

入力が2次元の場合を考える。

入力ベクトルを

\[ \mathbf{x} = \begin{bmatrix} x_1 \ x_2 \end{bmatrix}^{\mathsf T} \]

とすると、識別関数は

\[ g(\mathbf{x}) = w_1x_1+w_2x_2+b \]

となる。

分類の境界は \(g(\mathbf{x})=0\) を満たす点の集合である。

したがって、

\[ w_1x_1+w_2x_2+b=0 \]

が決定境界となる。この式は2次元平面上では直線(1次元)を表す。

例えば、

\[ g(\mathbf{x}) = x_1+x_2 \]

の場合、

\[ x_1+x_2=0 \]

が決定境界となる。この直線より上側では識別関数が正となり、下側では負となる。


法線ベクトル

識別関数

\[ g(\mathbf{x}) = \mathbf{w}^{\mathsf T}\mathbf{x}+b \]

において、重みベクトル \(\mathbf{w} = \begin{bmatrix}w_1,w_2\end{bmatrix}^{\mathsf T}\) は決定境界に垂直な方向を表す。

例えば、

\[ \mathbf{w} = \begin{bmatrix} 1,1 \end{bmatrix}^{\mathsf T} \]

であれば、

\[ x_1+x_2+b=0 \]

という直線が決定境界となる。

このとき、\(\begin{bmatrix}1,1\end{bmatrix}^{\mathsf T}\) は直線に垂直な方向を向いている。重みベクトルは決定境界そのものではなく、決定境界に垂直な方向を表している。

高次元への拡張

3次元では、

\[ w_1x_1+w_2x_2+w_3x_3+b=0 \]

が平面を表す。

線形識別では\(\mathbf{x} \in \mathbb{R}^D\) のベクトル空間において、\(g(x)=0\) は超平面で定義される。

さらに一般の \(D\) 次元では、

\[ g(\mathbf{x}) = \mathbf{w}^{\mathsf T}\mathbf{x}+b=0 \]

は超平面と呼ばれ、\(D\)次元における\(D-1\)次元部分空間である。そのため、線形識別モデルは「超平面によって入力空間を2つに分割するモデル」と解釈できる。超平面は高次元空間における平面の一般化である。1次元では0次元の点、2次元では1次元の直線、3次元では2次元平面が対応する。

演習(決定境界の描画)

以下の手順で、2次元の人工データを生成し、その決定境界を可視化せよ。

  1. データには2つのクラスが割り当てられている。クラス0は平均\((-2,-2)\)の標準正規分布から、クラス1は平均\((2,2)\)の標準正規分布から生成されるものとし、データ数はそれぞれ50個(合計100個)である。
  2. クラスごとに異なる色で点を描画する。
  3. 決定境界はデータを見ながら手動で重みベクトルを決定し、いくつかの重みベクトルで決定境界を描画してみる。

線形識別モデルの学習

これまでの例では、\(\mathbf{w}\)\(b\) を人手で設定していた。しかし実際には、どのような決定境界が適切かは分からない。そこで、訓練データを用いて重みを自動的に決定したい。

例えば、以下のようなデータが与えられたとする。

\(x_1\) \(x_2\) クラス
-2 -1 0
-1 -2 0
2 1 1
1 2 1

人間であれば、2つのクラスを分離する直線を目で見て描ける。機械学習では、この作業をアルゴリズムによって自動化する。最も基本的な線形識別モデルの学習アルゴリズムがパーセプトロンである。

パーセプトロン

パーセプトロンとは

パーセプトロンは1950年代にローゼンブラットによって提案された最も基本的な線形識別モデルである。

入力ベクトル\(\mathbf{x}\) に対して、

\[ g(\mathbf{x}) = \mathbf{w}^{\mathsf T}\mathbf{x}+b \]

を計算し、その符号によって分類を行う。

構造そのものはさきほど学んだ線形識別モデルと同じである。パーセプトロンの特徴は、重みをデータから学習するための更新則を持つことである。パーセプトロンは新しい識別関数ではない。線形識別関数の重みを学習するアルゴリズムと考えるとよい。

誤分類の修正によるパーセプトロンの更新

パーセプトロンでは、訓練データを順番に観察し、誤分類した場合のみ重みを更新する。正しく分類できているサンプルについては何もしない。誤分類したサンプルについては、「正しいクラスの方向へ決定境界を移動する」ように重みを更新する。この単純な考え方だけで、線形分離可能なデータに対しては適切な決定境界を学習できる。

パーセプトロンでは、各サンプルを順番に観察し、誤分類した場合のみ重みを更新する。

まず、クラスラベルを\(t \in \{-1,+1\}\) で表すことにする。このラベルづけは誤分類のみを扱う時に非常によい役割を果たす。

識別関数 \(g(\mathbf{x}) = \mathbf{w}^{\mathsf T}\mathbf{x}+b\) に対して、\(tg(\mathbf{x}) \gt 0\) であれば正しく分類できている。一方 \(tg(\mathbf{x}) \le 0\) であれば誤分類である。ラベルを正負にすることで、識別関数と正解ラベルの積の符号が、識別を正しくできたかをそのまま表すことになる。

よって誤分類した場合、重みを

\[ \mathbf{w} \leftarrow \mathbf{w} + \eta t \mathbf{x} \]

によって更新する。

ここで、\(\eta\) は学習率、\(t\) は正解ラベルである。

また、バイアス項は

\[ b \leftarrow b+\eta t \]

によって更新する。更新式から正例を誤分類した場合には決定境界を正例側へ移動し、負例を誤分類した場合には負例側へ移動していると解釈できる。

演習(パーセプトロンの実装)

さきほどの演習で生成した2クラス100個のデータを対象にパーセプトロンを実装せよ。

  • クラス0を-1 、クラス1を1 でラベルづけする。
  • 決定境界の初期値を\(g(x) = x_1 - x_2 = 0\) とする。

手順としては以下のようになる。

  1. 点を1つずつ取り出す
  2. 誤識別している場合には重みベクトルとバイアスを更新する(この時点で決定境界が変化)
  3. 全ての点にこれを繰り返す。
  4. 1-3 を一塊(これを1エポックという)とし、このエポックを繰り返す。

実装して点と決定境界を可視化しながら、以下の点を確認してみよ。

  • 学習前後で決定境界がどのように変化するか
  • 学習率を変更すると結果はどのように変化するか
  • エポック数を増やすとどのように変化するか

また1点ずつ取り出し、更新する部分は複数点で行うことも可能である(これは深層学習の言葉ではバッチサイズと呼ばれる)。時間があればバッチサイズを変更した更新にも挑戦してみるとよい。

パーセプトロン収束定理

パーセプトロンには重要な性質がある。

訓練データが線形分離可能であれば、有限回の更新で必ず収束する。

ここで一本の直線(または超平面)によって完全にクラスを分離できる状態を線形分離可能という。この結果はパーセプトロン収束定理として知られている。一方、線形分離不可能な場合には収束しない。したがって、パーセプトロンが適切に機能するかどうかは、データが線形分離可能かどうかに依存する。

XOR問題

パーセプトロンの限界を理解するために、XOR問題を考える。

入力と出力は以下のように与えられる。

\(x_1\) \(x_2\) クラス
0 0 0
0 1 1
1 0 1
1 1 0

これを平面上に配置すると、

(0,1) ●        ○ (1,1)


(0,0) ○        ● (1,0)

となる。

同じクラスが対角線上に現れるため、一本の直線では分離できない。

演習(XOR問題に対するパーセプトロン)

以下のデータに対してパーセプトロンを学習させよ。

1
2
3
4
5
6
7
X = np.array([
    [0, 0],
    [0, 1],
    [1, 0],
    [1, 1]
])
t = np.array([-1, 1, 1, -1])

学習を長時間実行した場合でも収束しないことを確認せよ。

このようにXOR問題は入力データに基底関数を用いる等の工夫をしない限り、線形識別モデルでは解けない。この問題が後のニューラルネットワーク研究の発展につながった。


パーセプトロンの限界

パーセプトロンは単純で理解しやすいアルゴリズムである。しかし、いくつかの重要な問題がある。

まずデータが線形分離可能である必要があるが、現実のデータでは必ずしもこの仮定は妥当ではない。2つめの問題は確率の情報が得られないことである。これは識別の不確実性を表現できないことを意味している。実際のデータでは、境界付近に存在するサンプルも多い。そのようなサンプルについては、「どちらのクラスであるか」だけでなく、「どの程度そのクラスらしいか」も知りたいことが多い。

分類と確率

ここで改めて分類問題の目的を考えてみる。パーセプトロンでは、\(\hat y\) というクラスラベルを直接予測していた。しかし、本当に知りたいのはラベルそのものではない。例えば、身長からクラスを予測する場合、「クラス1」という結果だけでは情報が不足している。むしろ、「クラス1である確率 0.95」あるいは「クラス0である確率 0.55」のような情報が欲しい。

このような確率は事後確率と呼ばれる。\(P(C_k|\mathbf{x})\) は、「特徴量 \(\mathbf{x}\) が与えられたとき、そのサンプルがクラス \(C_k\) に属する確率」を表している。

k近傍法(k-Nearest Neighbors)

事後確率をどのように求めるか

さきほど分類問題の本質は事後確率\(P(C_k|\mathbf{x})\) を推定することであると説明した。では、この事後確率はどのように求めればよいのだろうか。

最も単純な考え方は、「入力に近いサンプルを集め、その中で各クラスがどのくらい現れるかを数える」ことである。この考え方に基づく手法が k近傍法(k-Nearest Neighbors; kNN)である。

最近傍のサンプルを探す

まず、ある入力\(\mathbf{x}\) が与えられたとする。

訓練データ中の各サンプルとの距離を計算し、距離が近い順に並べる。

例えば、

サンプル 距離 クラス
A 0.3 1
B 0.4 1
C 0.5 0
D 0.7 1
E 0.8 0

であったとする。

このとき、\(k=3\)とすると、最も近い3個のサンプルはA,B,C である。

そのうち、

  • クラス1が2個
  • クラス0が1個

存在する。

したがって、

\[ P(C_1|\mathbf{x}) \approx \frac{2}{3} \]

と推定できる。


kNNによる分類

事後確率が推定できれば、分類は簡単である。最も確率の高いクラスを選択すればよい。例えば、\(P(C_0|\mathbf{x}) = 0.3\)\(P(C_1|\mathbf{x})=0.7\)ならば、\(\hat y = 1\) と予測するといった具合である。

分類器としてのkNN

kNNは多数決による分類器として説明されることが多い。しかし本質的には事後確率推定器として解釈できる。

距離の計算

kNNでは距離の定義が重要である。

最もよく用いられるのはユークリッド距離である。

2つのベクトル\(\mathbf{x} = (x_1,x_2,\ldots,x_D)\)\(\mathbf{z} = (z_1,z_2,\ldots,z_D)\)

の距離は

\[ d(\mathbf{x},\mathbf{z}) = \sqrt{\sum_{i=1}^D (x_i-z_i)^2} \]

で定義される。距離が小さいほど、特徴が似ていると考える。

NumPyによる実装

まずは最も単純な\(k=1\)の場合の実装例である。

import numpy as np

X_train = np.array([
    [-2, -1],
    [-1, -2],
    [ 2,  1],
    [ 1,  2]
])

y_train = np.array([0, 0, 1, 1])

x = np.array([0.5, 1.0])

distance = np.sum((X_train - x)**2, axis=1)

nearest = np.argmin(distance)

pred = y_train[nearest]

print(pred)

演習(kNNの写経)

上記を写経し実行してみよ。

演習(\(k>1\)での実装)

改めて人工データを生成し、kNNを実装せよ。

  1. データには2つのクラスが割り当てられている。クラス0は平均\((-2,-2)\)の正規分布から、クラス1は平均\((2,2)\)の正規分布から生成されるものとし、データ数はそれぞれ50個(合計100個)である。先ほどより分散を大きく設定し、分散共分散行列を単位行列の4倍とする。
  2. クラスごとに異なる色で点を描画する。
  3. さらにテストデータとして平均\((0,0)\) の標準正規分布から20点ほどサンプルを生成する。

\(k\)を変化できるようにし、kNNにより事後確率を計算した上でテストデータのクラスを決定せよ。

  • k を変更すると分類結果はどう変化するか。
  • k=1 と k=5 の違いを説明せよ。
  • k を極端に大きくすると何が起こるか。

なお距離行列の計算はfor文を用いずブロードキャスト等を駆使して効率的に書いてみること。二つのベクトルセット間の距離行列はnumpyであれば1行で書くことも可能である。距離に基づく並べ替えにはnp.argsort()なども利用できる。


kNNによる事後確率推定

kNNの重要な特徴は、事後確率を直接推定できることである。

例えば、近傍10サンプルのうち、クラス0が3個、クラス1が7個であったとする。このとき、\(P(C_0|\mathbf{x})\approx0.3\), \(P(C_1|\mathbf{x})\approx0.7\) と推定できる。

分類だけでなく、「どの程度そのクラスらしいか」も分かる。これはパーセプトロンにはなかった性質である。


kNNの問題点

kNNは単純で強力な手法であるが、いくつかの欠点も存在する。まず学習後も全ての訓練データを保持しなければならない点が挙げられる。これは学習データサイズが巨大な場合は非常に問題になる。また予測のたびに全サンプルとの距離を計算する必要があり、計算量が大きい。さらに特徴量の次元が大きくなると、「近いサンプル」という概念が曖昧になる。この現象は次元の呪いと呼ばれている。

メロンパンサクサク問題

突然だが、みなさんはメロンパンは好きだろうか。メロンパンの魅力のひとつはおそらく表面クッキー生地のサクサクした食感であろう。このサクサク、仮にメロンパンを3次元の球と仮定し、半径の外側10%がサクサクと考えると、3次元メロンパンのサクサク度は約27%である。3割の贅沢感である。

話を機械学習の特徴空間に戻そう。高次元空間では全ての点が互いに遠くなり、近傍探索の効果が弱くなる。このことを次元の呪いとよぶ。高次元の球の中心にある点がいるとして、半径1の範囲を近傍と仮定する。この中にある点のうち、表面半径10%部分にある体積は\(D=20\)ぐらいになると、なんと約88%になるのだ。このように高次元球の体積の大半が球面に集中してしまう現象を球面集中現象と呼ぶ。これは機械学習における高次元問題の解釈の一つであり、これを解決するために次元圧縮や適切な特徴量選択を行っていく必要があるのだ。

ところで高次元メロンパンを想像すると、このサクサクを3次元空間よりたっぷり楽しめる。お得である。これをメロンパンサクサク問題という。興味がある人は検索してみよう。

シンプルis正義

工学の世界ではシンプルさは正義である。kNN認識のような考え方は、「とにかく似ているものを探す」というシンプルな考え方に基づいており、ときにはそれがとても強い性能を示すこともある。例えば画像認識の世界では、2010年以降、大量の画像で強い深層学習モデルを訓練することで強い認識器(ResNetなど)が作られてきた。一方、2020年以降にはCLIPといった強い特徴量抽出器(画像から高次元特徴ベクトルを抽出するもの)が作られ使えるようになった。そして、CLIP特徴量ベクトルで単純に似ているものをkNN的に探すという方式は大変に強いベースラインとなっている。すなわち、「大量データでモデルを訓練し、テスト時はそれを使う」に対し「大量データで特徴量抽出器を訓練し、テスト時はkNN的に使う」というアプローチもあるということだ。LLMの世界では再度「大量データで巨大VLMを訓練」が主流になっているともいえる。このように、技術の歴史を読み解くことは面白い。

ちなみに、深層学習やLLMとは異なり、kNNはシンプルさゆえにGPU必須というわけではないメリットがある。近傍探索を近似でいいので高速に実行することを目指す分野を近似最近傍探索という。このような技術はLLMにデータを注入する際も利用することができ、ベクトルデータベースという名前で注目を集めている。

ベイズ分類

クラス条件付き分布

kNNでは、\(P(C_k|\mathbf{x})\) を近傍サンプルの頻度から推定した。

しかし、もし各クラスのデータ分布が分かっているならば、サンプルを数えなくても事後確率を計算できるはずである。

例えば、1次元空間において

  • クラス0は平均 -2 の正規分布
  • クラス1は平均 +2 の正規分布

に従うと分かっていれば、\(P(C_k|\mathbf{x})\) を理論的に計算できる。

この考え方に基づく手法がベイズ分類である。

ここで、まずは\(p(\mathbf{x}|C_k)\) を考える。これはクラス条件付き分布と呼ばれる。クラスが与えられたときに、特徴量がどのような値を取るかを表している。

例えば、男女の身長分布を考える場合、\(p(x|\text{男性})\), \(p(x|\text{女性})\) がクラス条件付き分布に対応する。

正規分布によるモデル化

実際のデータ分布は複雑である。

しかし、多くの場合、正規分布は有効な近似として利用できる。1次元の正規分布は

\[ p(x) = \frac{1}{\sqrt{2\pi\sigma^2}} \exp \left( -\frac{(x-\mu)^2} {2\sigma^2} \right) \]

で表される。

ここで、\(\mu\) は平均、\(\sigma^2\) は分散である。

演習(正規分布人工データの生成)

1次元空間において、2つの正規分布から人工データを生成し、可視化せよ。可視化にはmatplotlib.pyplot の histを用いて、サンプルの頻度が縦軸、横軸が\(x\)となるように表示する。

  • 平均がそれぞれ2, -2、分散は1とする。
  • 各分布からそれぞれ500個ずつデータを生成する。
  • ヒストグラムのビンの数(解像度)は30とし、色の透明度を表す\(alpha\)は0.5 に設定する
  • 各データにはラベルをつけるとよい

さらに以下をすすめよ。

  1. 平均を変更するとどうなるか確認せよ。
  2. 分散を変更するとどうなるか確認せよ。

ベイズの定理

クラス条件付き分布が分かれば、事後確率を計算できる。

そのために利用するのがベイズの定理である。

\[ P(C_k|\mathbf{x}) = \frac{p(\mathbf{x}|C_k)P(C_k)}{p(\mathbf{x})} \]

ここで、

  • \(P(C_k)\) は事前確率
  • \(p(\mathbf{x}|C_k)\) はクラス条件付き分布
  • \(P(C_k|\mathbf{x})\) は事後確率

である。

ベイズの定理はデータが与えられた時のクラス情報(\(P(C_k|\mathbf{x})\))と、クラスが与えられた時の特徴量情報(\(P(\mathbf{x}|C_k)\))を結びつける最重要定理の一つである。前者のモデル化は識別的アプローチ、後者のアプローチは生成的アプローチと呼ばれ、ベイズの定理は生成的アプローチによるモデル(生成モデル)で識別問題を解くための方法論である。

演習(式変形、実装なし)

ベイズの定理を同時確率\(p(\mathbf{x},C_k)\) から導出せよ。

分類・認識問題における生成モデルと識別モデル

教師あり学習による分類・認識問題においてクラス事後確率のモデル化が重要であることをここまでで見てきた。離散ラベル付きのデータを集めてきた時、クラスが与えられた時の特徴量情報の方には生成分布というモデルを仮定しやすい一方、データが与えられた時のクラス情報は直接のモデルが仮定しにくい。これが上記のベイズの定理を経由して定式化する一つの要因である。深層学習の登場以前は、統計的機械翻訳、音声認識などはこのベイズの定理による定式化を基本としていた。このアプローチを生成モデルによるアプローチとよぶ。また通信路モデルと関わりが深いことから、ベイズの定理を介したこのモデル化を「雑音のある通信路モデル(Noisy Channel Model)」と呼んだりする。生成モデルはモデルを立てやすく、学習を組み立てやすい一方、仮定しているモデルが精緻であることが求められ、データが大規模化する中で現実のデータと生成モデルの仮定にギャップが生じるようになってきた。深層学習の登場によりデータを大量に扱い、本来モデル化するべきクラス事後確率をニューラルネットワークで直接求めるアプローチ(これを識別モデルによるアプローチという)が再注目され、現在に至っている。なお識別モデル自体は深層学習以前にも研究されており、有名なところでは条件付き確率場(Conditional Random Field; CRF)などがある。ぜひ調査してみるとよい。

分類境界はどこに現れるか

2クラス問題を考える。

クラス0とクラス1の事後確率が等しくなる点が決定境界となる。つまり\(P(C_0|x)=P(C_1|x)\) となる位置である。

ベイズの定理から\(p(x|C_0)P(C_0)=p(x|C_1)P(C_1)\) となる。クラスの事前確率が同じと仮定するとこれは「両クラスの尤度が釣り合う位置」を意味している。


演習(ベイズ分類器の実装)

各クラスの生成分布として正規分布を仮定したベイズ分類器を実装せよ。特徴量空間の次元を2次元とする。以下の手順を考える。

  1. 学習データを以前の演習と同様、あらかじめ適宜設定した正規分布から生成する。個数は各クラス50個とする。
  2. 別途テストデータを原点付近にある正規分布から20個ほどサンプリングする。
  3. 学習データの平均と分散を改めて計算する(これは正規分布のパラメータを最尤推定していることになる)。この時、生成時のパラメータとどの程度近いかを確認せよ。
  4. 2で生成されたサンプルについて、各クラスに正規分布に基づく確率を計算し、この大小を比較して分類結果とする。

複数のデータサンプルが与えられたときに正規分布からの確率値または対数確率を出力する関数を実装することになる。この際サンプル配列に対してfor文を用いない実装を工夫してみよ(これは確率、尤度計算の速度に直結するため非常に重要である)

kNNとベイズ分類の違い

ここで、これまで学んだ2つの方法を比較してみよう。

手法 事後確率の求め方
kNN 近傍サンプルを数える
ベイズ分類 分布を仮定して計算する

kNNはデータから直接推定する方法である。

一方、ベイズ分類は「データはある分布に従う」という仮定を利用する。そのため、データが少なくても安定しやすく、計算量が小さいという利点がある。

等分散ガウス分布

ここで興味深い状況を考える。

クラス0とクラス1が、

同じ分散を持つ正規分布に従うと仮定する。

つまり、

\[p(x|C_0) = \mathcal{N} (x;\mu_0,\sigma^2) \]
\[ p(x|C_1) = \mathcal{N} (x;\mu_1,\sigma^2) \]

とする。

このとき、事後確率の比

\[ \frac{ P(C_1|x) }{ P(C_0|x) } \]

を考えると、対数を取った結果が

\[ wx+b \]

という線形関数になる。

演習(式変形・実装なし)

上記の結果を式変形から導け。

これは非常に重要な結果である。なぜなら、線形識別モデルが突然現れたのではなく、「等分散ガウス分布を仮定したベイズ分類器」から自然に導かれたことを意味するからである。

ロジスティック回帰

対数オッズを直接モデル化する

前節にて、等分散ガウス分布を仮定すると、

\[\log \frac{ P(C_1|\mathbf{x}) } { P(C_0|\mathbf{x}) }= \mathbf{w}^{\mathsf T}\mathbf{x}+b \]

となることを見た。

この左辺のことを対数オッズと呼ぶ。対数オッズは、「クラス1らしさとクラス0らしさの比率」を表している。

ここで重要な発想は、クラス条件付き分布そのものを考えるのではなく、対数オッズを直接モデル化するということである。生成モデルから改めて識別モデルに戻ってくる。この対数オッズを入力から予測する分類モデルをロジスティック回帰と呼ぶ。

シグモイド関数

対数オッズが

\[ z=\mathbf{w}^{\mathsf T}\mathbf{x}+b \]

で表されると仮定する。

このとき、

\[ P(C_1|\mathbf{x}) = \frac{1} {1+\exp(-z)} \]

となる。

この関数をシグモイド関数という。シグモイド関数は分類問題で特に重要であり

\[ \sigma(z) = \frac{1} {1+\exp(-z)} \]

と表記することも多い。

この表記において

\[ P(C_1|\mathbf{x}) = \sigma \left( \mathbf{w}^{\mathsf T}\mathbf{x}+b \right) \]

となる。


シグモイド関数の性質

シグモイド関数には次の性質がある。

出力は常に0から1の範囲に入る

\(0 < \sigma(z) < 1\) である。そのため確率として解釈できる。

境界は0.5である

\(\sigma(0)=0.5\) である。したがって、

\[ \mathbf{w}^{\mathsf T}\mathbf{x}+b=0 \]

が決定境界となる。これは線形識別モデルと同様である。

大きな正値では1に近づく

\(z \rightarrow \infty\) ならば \(\sigma(z)\rightarrow1\) となる。

大きな負値では0に近づく

\(z \rightarrow -\infty\) ならば\(\sigma(z)\rightarrow0\)となる。


演習(シグモイド関数の描画)

1次元において-10から10の範囲でシグモイド関数をプロットせよ。

  1. \(z=0\) でどのような値を取るか。
  2. \(z\) が大きくなるとどうなるか。
  3. \(z\) が小さくなるとどうなるか。

最尤推定

ロジスティック回帰では、\(\mathbf{w}\)\(b\)を訓練データから推定する必要がある。そのために最尤推定を用いる。

訓練データ

\[ \{(\mathbf{x}_n,t_n)\}_{n=1}^{N} \]

が与えられたとする。

事後確率を

\[ y_n = P(C_1|\mathbf{x}_n) \]

とすると、

尤度関数は

\[ L= \prod_{n=1}^{N} y_n^{t_n} (1-y_n)^{1-t_n} \]

となる。

交差エントロピー損失

尤度の対数を取ると、

\[ \log L = \sum_n \left[ t_n \log y_n + (1-t_n)\log(1-y_n) \right] \]

となる。通常は負号を付けて最小化問題として扱う。

\[ E = -\sum_n \left[ t_n \log y_n + (1-t_n)\log(1-y_n) \right] \]

これを交差エントロピー(クロスエントロピー)損失と呼ぶ。

なぜ二乗誤差ではないのか

ロジスティック回帰は確率モデルであるため、最尤推定から自然に交差エントロピー損失が導かれる。二乗誤差をクラスラベルを表すベクトル(多クラスの場合1-of-K表現と呼ぶ)に適用すると、ラベルが仮定するモデルとミスマッチであり、外れ値に非常に弱くなる。回帰の時も述べた通り、採用する誤差は背景にあるモデルと密接に関係している。


演習(交差エントロピー損失の可視化)

正解ラベルを\(t=1\)とし、\(y_n\) の値を変化させて交差エントロピー損失の様子を可視化し、その変化を考察せよ。

ロジスティック回帰実装

交差エントロピーの最小化については、一般に解析解を求めることが困難であるため、勾配降下法を用いるのが一般的である。ロジスティック回帰では、交差エントロピー損失

\[ E = -\sum_{n=1}^{N} \left[ t_n\log y_n + (1-t_n)\log(1-y_n) \right] \]

を最小化する。

ここで、

\[ y_n = \sigma(z_n) \]
\[ z_n = \mathbf{w}^{\mathsf T}\mathbf{x}_n+b \]

である。

勾配降下法を用いるためには、

\[ \frac{\partial E} {\partial \mathbf{w}} \]

を求める必要がある。


まず、

\[ \sigma(z) = \frac{1} {1+\exp(-z)} \]

を微分する。

計算すると、

\[ \frac{d\sigma}{dz} = \sigma(z) \left( 1-\sigma(z) \right) \]

となる。

したがって、

\[ \frac{dy_n}{dz_n}= y_n(1-y_n) \]

である。


1サンプル分の損失

\[ E_n= - \left[ t_n\log y_n + (1-t_n)\log(1-y_n) \right] \]

を考える。

まず、

\[ \frac{\partial E_n} {\partial y_n} = -\frac{t_n}{y_n} + \frac{1-t_n}{1-y_n} \]

である。

これを整理すると、

\[ \frac{\partial E_n} {\partial y_n}= \frac{y_n-t_n} {y_n(1-y_n)} \]

となる。


連鎖律より、

\[ \frac{\partial E_n} {\partial z_n} = \frac{\partial E_n} {\partial y_n} \frac{\partial y_n} {\partial z_n} \]

である。

先ほど求めた式を代入すると、

\[ \frac{\partial E_n} {\partial z_n}= \frac{y_n-t_n} {y_n(1-y_n)} y_n(1-y_n) \]

となる。

ここで分母と分子が打ち消し合い、

\[ \frac{\partial E_n} {\partial z_n}= y_n-t_n \]

が得られる。

さらに、

\[ z_n = \mathbf{w}^{\mathsf T} \mathbf{x}_n+b \]

より、

\[ \frac{\partial z_n} {\partial \mathbf{w}}= \mathbf{x}_n \]

である。

したがって、

\[ \frac{\partial E_n} {\partial \mathbf{w}}= (y_n-t_n)\mathbf{x}_n \]

となる。

全サンプルについて和を取れば、

\[ \boxed{ \frac{\partial E} {\partial \mathbf{w}}= \sum_{n=1}^{N} (y_n-t_n) \mathbf{x}_n } \]

を得る。

同様に、

\[ \boxed{ \frac{\partial E} {\partial b}= \sum_{n=1}^{N} (y_n-t_n) } \]

となる。


実装の簡便性からデータ行列

\[ X = \begin{bmatrix} \mathbf{x}_1,\mathbf{x}_2,\ldots,\mathbf{x}_N \end{bmatrix} \in \mathbb{R}^{D\times N} \]

を用いると、

\[ \boxed{ \nabla_{\mathbf{w}} E= X(\mathbf{y}-\mathbf{t}) } \]

と書ける。ここで \(\mathbf{y} = [y_1, y_2, \dots, y_n]^\mathsf{T}, \mathbf{t} = [t_1, t_2, \dots, t_n]^\mathsf{T}\) とした。

この式の形に着目すると「予測値と推定値の差」と「入力値」を掛け合わせたものになっている。実は前回の線形回帰の勾配に着目するとこちらも同様の形式となっていることがわかる。この形は実は深層学習に発展した場合でも同様の形式が表れるため非常に重要である。この形式により、誤差関数を定義するだけで勾配を計算することが容易になるのである。

演習(ロジスティック回帰実装)

これまで同様に2クラスデータを生成し、ロジスティック回帰による分類器の学習を実装せよ。

  1. 学習率を適宜設定することになる。学習率で変化の様子を観察せよ。
  2. 勾配法の反復によって決定境界がどのように変わるかを可視化せよ。

多クラス分類

二値分類の限界

これまで扱ったロジスティック回帰は2クラス分類を対象としていた。

しかし実際には、

  • 手書き数字認識
  • 音声認識
  • 画像分類

など、多数のクラスを扱う問題も多い。

そこでロジスティック回帰を多クラスへ拡張する。


ソフトマックス関数

各クラスに対して

\[ a_k= \mathbf{w}_k^{\mathsf T} \mathbf{x} +b_k \]

を計算する。

その後、

\[ P(C_k|\mathbf{x})= \frac{ \exp(a_k) }{ \sum_j \exp(a_j) } \]

を計算する。この関数をソフトマックス関数という。

ソフトマックスの性質

ソフトマックス関数は入力されたものの最大値を選んでくる関数(max関数)を確率的に拡張したものとみなせる。いくつかの性質がある。まず全ての確率の和が1になる。

\[ \sum_k P(C_k|\mathbf{x})= 1 \]

である。

また上述の通り、これはmax関数の拡張なので、最も大きなスコアを持つクラスが高い確率を得る。すなわち\(a_k\)が大きいほど、\(P(C_k|\mathbf{x})\)も大きくなる。

シグモイドとの関係

実は、シグモイド関数はソフトマックス関数の特殊な場合である。

2クラスの場合、

\[ P(C_1|\mathbf{x})= \frac{ \exp(a_1) }{ \exp(a_0)+\exp(a_1) } \]

となる。

これを変形すると、

\[ P(C_1|\mathbf{x})= \frac{1} {1+\exp(-(a_1-a_0))} \]

となり、シグモイド関数と一致する。

まとめ

本日は線形識別モデルの基本を学んだ。

まず、線形識別関数によって超平面を定義し、その符号によって分類を行った。続いてパーセプトロンを学び、線形識別関数を学習できることを確認した。さらに、分類問題の本質が事後確率推定であることを理解するために、kNNとベイズ分類を学んだ。

最後に、対数オッズを直接モデル化するロジスティック回帰を導入し、多クラス分類への拡張としてソフトマックス関数を学んだ。

本日学んだ内容を整理すると次のようになる。

手法 事後確率 学習
パーセプトロン × 誤分類修正
kNN 不要
ベイズ分類 分布推定
ロジスティック回帰 最尤推定

ロジスティック回帰で得られた知見は、誤差関数の設定を回帰と分類で切り替えただけのように見えるが、そこには本日学んだような背景知識が存在する。深層学習へ発展する際も適切なロス(誤差)設計は大変重要となる。なお、2日目に学んだ基底関数による特徴空間の拡張は本日の話全てに導入可能である。興味がある人は導出、実装を行ってみると良い。