Deep Learning

【やってみた】ゼロから作るDeep Learning① -第2章

はじめに

今回の記事は、ゼロから作るDeep Learning(以下ゼロつく)の取り組みについてです。

私はゼロつくをE資格取得を目的として勉強し始めました。E資格を取得することで、機械学習やディープラーニングなどの知識を体系的に学ぶことができます。
試験合格、ないしディープラーニングの理解を深めるため、自分なりに書籍で学んだことをアウトプットしていきます。
この記事で学習したいという方はぜひ、書籍と併せて読んでいただければと思います。

このブログでは第2章からやっていきたいと思います。
第1章はPythonの基礎的な文法がメインだからです。
Pythonに触れたことがない人が、ゼロつくからディープラーニングを学ぶことは少ないケースのように感じます。
もちろんゼロつくでも学ぶことはできますが、他の書籍で軽く触れてから取り組む方が効率的だと思いました。

第2章はパーセプトロンというアルゴリズムについてです。
ニューラルネットワークやディープラーニングを学ぶための基礎となるので、中身を理解することが重要です。

本の内容を丸写しすることは無断転載など問題があるため、避けるようにします。
無断転載などの問題については以下のブログを参考にさせていただきました。
https://blog.jnito.com/entry/2018/01/23/075856

パーセプトロンとは

パーセプトロンとは先述の通り、ニューラルネットワークやディープラーニングを学ぶための基礎です。
複数の信号を入力として受け取り、ひとつの信号を出力します。
信号というとイメージしにくいかもしれません。数値と読み替えてもよいと思います。
出力は、0か1の二値のみです。

入力は\(x_1\),\(x_2\)などで表され、出力は\(y\)、重みは\(w_1\),\(w_2\)などで表されます。
重みは入力の重要度をコントロールします。重みが大きければ大きいほど、その重みに対応する入力の重要度が高いと言えます。

そして、入力に重みを掛け、総和したものが設定した閾値(限界値)を超えた場合に1を出力、超えなければ0を出力します。
これがパーセプトロンの仕組みです。
ちなみに出力が1を出力することを、発火するといいます。
数式で表すと以下のようになります。
$$
y = \begin{cases}
0 \quad (w_1 x_1 + w_2 x_2 \leq \theta) \\
1 \quad (w_1 x_1 + w_2 x_2 > \theta)
\end{cases}
$$

さらに、バイアスという概念を追加します。
先に数式で表しておきます。
$$
y = \begin{cases}
0 \quad (b + w_1 x_1 + w_2 x_2 \leq 0) \\
1 \quad (b + w_1 x_1 + w_2 x_2 > 0)
\end{cases}
$$
先ほどの数式に追加されたのは\(b\)だけです。
これがバイアスを表しています。
入力×重みの総和が閾値を超えた場合に1を出力と先述しましたが、ここにバイアスの和を足すだけです。
入力×重み + バイアスの和 が閾値を超えた場合に1ということになります。

バイアスは発火のしやすさをコントロールするパラメータです。
バイアスの値が小さいほど、入力×重みの値が大きくないと発火しません。

単純な論理回路

パーセプトロンを考える際に、ゲートという考え方が必要になります。
ここで言うゲートを日本語訳するとしたら、論理回路になるでしょうか。
ゲートは複数あり、以下のものがあります。

  • ANDゲート
  • NANDゲート
  • ORゲート
  • XORゲート

このゲートについて説明していきます。

ANDゲート

ANDゲートとは、入力が2で出力が1のゲートです。
2つの入力が1のときのみ1を出力し、それ以外を0と出力します。

実装

def AND(x1, x2):
  w1, w2, theta = 0.5, 0.5, 0.7
  tmp = x1*w1 + x2*w2
  if tmp <= theta :
    return 0
  elif tmp > theta :
    return 1

print(AND(0, 0))
print(AND(1, 0))
print(AND(0, 1))
print(AND(1, 1))

#出力
0
0
0
1

入力が(1, 1)のときのみ出力が1になっていることがわかります。

バイアスを導入した場合は以下のようになります。

import numpy as np

def AND(x1, x2) :
  x = np.array([x1, x2])
  w = np.array([0.5, 0.5])
  b = -0.7
  tmp = np.sum(w*x) + b
  if tmp <= 0 :
    return 0
  else :
    return 1

NANDゲート

NANDゲートは、Not ANDゲートです。文字通りANDの逆にしたもので、入力が(1, 1)のときにのみ0を出力します。

実装

def NAND(X1, x2) :
  x = np.array([x1, x2])
  w = np.array([-0.5, -0.5])
  b = 0.7
  tmp = np.sum(w*x) + b
  if tmp <= 0 :
    return 0
  else :
    return 1

ORゲート

ORゲートは、入力のうち少なくとも1つが1であれば出力が1となるゲートです。

実装

def OR(x1, x2) :
  x = np.array([x1, x2])
  w = np.array([0.5, 0.5])
  b = -0.2
  tmp = np.sum(w*x) + b
  if tmp <= 0 :
    return 0
  else :
    return 1

パーセプトロンの限界

これまで、AND、NAND、ORゲートに触れましたが、パーセプトロンを用いることで実装できました。
しかし、次に触れるXORゲートでは難しくなります。

XORゲート

これまでのゲートはシンプルでわかりやすかったですが、XORゲートは少し複雑です。
XORゲートは排他的論理和と呼ばれます。
それぞれの入力が同じ場合に0を出力します。
例えば、入力が(0, 0)だと出力は0、(1, 1)でも0です。
(0, 1)や、(1, 0)の場合に1を出力します。

ここで同じように実装したいところですが、これまでと同じやり方では実装できません。
そこで、多層パーセプトロンを用いることで、XORゲートを表現できるようになります。
実装で見てみます。

実装

def XOR(x1, x2) :
  s1 = NAND(x1, x2)
  s2 = OR(x1, x2)
  y = AND(s1, s2)
  return y

print(XOR(0, 0))
print(XOR(1, 0))
print(XOR(0, 1))
print(XOR(1, 1))

# 出力
0
1
1
0

XORゲートができていることがわかります。
コードを見てわかるように、XORゲートはAND、NAND、ORゲートを組み合わせてできています。
このように、層を重ねていることから多層パーセプトロンと呼びます。

ANDゲートのみ等のような、単層のパーセプトロンでは線形領域しか表せませんが、多層にすることで非線形の領域も表すことができると言えます。
この章で扱ったパーセプトロンの仕組みが次章のニューラルネットワークでも重要になってきます。