And Gate
ゼロから作るDeep Learning 1を進めていく.
いつかやりたいといいつつやってないので、そろそろやるかの気分で始めた.
とりあえずsiv3Dオンリーで進めるけど、そのうち外部ライブラリを使うかもしれない.
ということでまずは線形分離から.
最初にAndの真理表を考えてみる.
| x1 | x2 | y |
|---|---|---|
| 0 | 0 | 0 |
| 1 | 0 | 0 |
| 0 | 1 | 0 |
| 1 | 1 | 1 |
Andは単純でとの値で両方が1の場合に1になる.
たったそれだけ.
これをがx座標,がy座標の座標軸を作る.
そして、yが0なら座標の点は青,1なら座標の点は赤にする.
これを解くために以下のような式を導入する.
こんな感じで先ほどのxと重みとバイアスで表していく.
この式より小さければ0,大きければ1となるようにするのである.
そしてイコールの時が直線で、線分で分けられるため決定曲線とかいうね.
まあいうだけでは分かりにくいので、まずはコードで書いて可視化してみよう.
用意するのは重みとバイアスのみ.
値は別段ほかでもOKだけど、本の通りに設定.
そして、式通りに書くだけ.
今回は0or1なので、boolで返すようにしてみる.
bool AndGate::Evaluate(const Vec2 value)
{
double result = Dot(value, m_weight) + m_bias;
return result > 0.0;
}
は与えられているとする.
この時イコールであるとすると以下のような式変形ができるはず.
これで決定境界が求まった、後はこれを定義してみればOK.
今回は座標軸のように返すようにしてみる.
Vec2 AndGate::GetDecisionBoundary(const double x)
{
return Vec2{ x, -(x * m_weight.x + m_bias) / m_weight.y };
}
まずは描画したい範囲内のxの一番小さい値と一番大きい値でy値を計算.
そのy値を使って直線を入れれば終わり.
// 決定境界
Vec2 left = andGate.GetDecisionBoundary(MIN_X_VALUE);
Vec2 right = andGate.GetDecisionBoundary(MAX_X_VALUE);
left = ConvertPoint(left); right = ConvertPoint(right);
Line{ left, right }.overwrite(*m_image, Palette::Green);
判定後は点を描画.
// 分類データ
Array<Vec2> points = { {0,0},{0,1},{1,0},{1,1} };
for (const auto& point : points)
{
bool result = andGate.Evaluate(point);
Vec2 convert = ConvertPoint(point);
Circle{ convert, 5 }.overwrite(*m_image, result ? Palette::Red : Palette::Blue);
}

先ほど言ったように青が0で赤が1.
緑が決定境界としてある.
ちゃんと分けられているのが分かる.
これが今回のやりたいこと,直線で区分するということである.