Neural Networks

Sigmoid Activation Function

入力とパラメータの内積を、シグモイド関数を通して 0 < a < 1 の範囲に変換するモデルを、 Sigmoid (Logistic) activation function と呼ぶ。

バイアス項 Bias unit として、x(0) = 1 で固定し、theta(0) をオフセット値とする。入力値 x(0|1) に制限すると、theta の値に応じて AND / OR の論理回路を実現できる。

X = [0 0; 0 1; 1 0; 1 1];
X = [ones(length(X), 1), X];         % [1 0 0; 1 0 1; 1 1 0; 1 1 1]

theta1 = [-30; 20; 20];              % AND gate
z1 = X * theta1;                     % [-30; -10; -10; 10]
h1 = sigmoid(z1);                    % [0; 0; 0; 1]

theta2 = [-10; 20; 20];              % OR gate
z2 = X * theta2;                     % [-10; 10; 10; 30]
h2 = sigmoid(z2);                    % [0; 1; 1; 1]

Forward Propagation

Activation function を複数レイヤーに定義し、各レイヤーの出力を次のレイヤーへの入力とすることで、より複雑な論理回路を実現できる。このモデルは、神経回路のシミュレーションを元にしており、ニューラルネットワーク Neural network と呼ばれる。

   L1    |    L2    |    L3    |    L4
------------------------------------------
    [+1]-+     [+1]-+     [+1]-+
         |          |          |
  [x(1)]-+->[a2(1)]-+->[a3(1)]-+->[a4(1)]-> h(x)
         |          |          |
  [x(2)]-+->[a2(2)]-+->[a3(2)]-+
         |          |
         +->[a2(3)]-+
  • 入力 x のバイアス項として x(0) = 1 とする。
  • Layer1: 3つの入力 x から、3つの出力 a2 を算出する。バイアス項として a2(0) = 1 とする。
  • Layer2: Layer1 の4つの出力 a2 を入力とし、2つの出力 a3 を算出する。バイアス項として a3(0) = 1 とする。
  • Layer3: Layer2 の3つの出力 a3 を入力とし、1つの出力 a4 を算出する。
  • 最終レイヤーの出力 a4(1) が、予測値 h(x) となる。

Layer2 の2入力に NAND / OR ゲート、Layer3 の1入力に AND ゲートを置くことで、XOR ゲートとして機能する。

Theta1 = [30 -20 -20; -10 20 20];    % [{NAND}; {OR}]
Theta2 = [-30 20 20];                % [{AND}]

X = [0 0; 0 1; 1 0; 1 1];
X = [ones(length(X), 1), X];         % [1 0 0; 1 0 1; 1 1 0; 1 1 1]

z1 = X * Theta1';                    % [30 -10; 10 10; 10 10; -10 30]
a2 = sigmoid(z1);                    % [1 0; 1 1; 1 1; 0 1]
a2 = [ones(length(a2), 1), a2];      % [1 1 0; 1 1 1; 1 1 1; 1 0 1]

z2 = a2 * Theta2';                   % [-10; 10; 10; -10]
a3 = sigmoid(z2);                    % [0; 1; 1; 0]

このように、複数レイヤーの入出力を介して、前方に伝播させていく方法を Forward propagation と呼ぶ。

Multi-class Classification

3つ以上に分類するには、出力レイヤーのユニットを、分類の数だけ用意すればよい。

   L1    |    L2    |    L3    |
--------------------------------
    [+1]-+     [+1]-+
         |          |
  [x(1)]-+->[a2(1)]-+->[a3(1)]
         |          |
  [x(2)]-+->[a2(2)]-+->[a3(2)]
         |          |
         +->[a2(3)]-+->[a3(3)]
         |          |
         +->[a2(4)]-+

出力レイヤーのベクトルを a3、正解値を y としたとき、a3(y) のフラグが立つと考える。

  • y = 1 if a3 = [1; 0; 0]
  • y = 2 if a3 = [0; 1; 0]
  • y = 3 if a3 = [0; 0; 1]

分類数を K とすると、コスト関数は各出力の誤差平均を求めればよい。

Cost Function

ニューラルネットワークのコスト関数は、ロジスティック回帰と同様であるが、予測値を求めるには Forward propagation で各レイヤーを通して算出する必要がある。

Theta1 = [-30 10 10 10; -10 20 20 20; 20 -10 -10 -10; -20 10 10 10];
Theta2 = [10 -20 -20 -10 -10; -10 10 10 0 10; 20 -20 -20 -10 -10];
X = [0 0 0; 0 0 1; 0 1 0; 1 1 1];
m = size(X, 1);

a1 = X;                         % 4 x 3
a1 = [ones(m, 1) a1];           % 4 x 4
z2 = a1 * Theta1';              % 4 x 4
a2 = sigmoid(z2);
a2 = [ones(size(a2, 1), 1) a2]; % 4 x 5
z3 = a2 * Theta2';              % 4 x 3
h = sigmoid(z3);

Regularization を行なう場合は、各レイヤーにパラメータがある点に注意する。バイアス項は除外する。

t1 = Theta1;
t2 = Theta2;
t1(:, 1) = 0;
t2(:, 1) = 0;

lambda = 0.1;
J = J + (sum(sum(t1 .^ 2)) + sum(sum(t2 .^ 2))) * lambda / (2 * m);

Sigmoid Gradient Function

ネイピア数 e を底とする指数の微分は (e^x)' = e^x であることを利用して、シグモイド関数 g(z) を微分すると g'(z) = g(z) * (1 - g(z)) となる。

Backpropagation

ニューラルネットワークの各ユニットのパラメータ(ニューロンの重み)を求めるには、ロジスティック回帰と同様に最急降下法を用いる。各ユニットの偏微分を求めるためには、最終出力の誤差から各レイヤーを逆に伝播して算出する必要がある。この方法を、誤差逆伝播法 Backpropagation と呼ぶ。

出力レイヤーの誤差は、予測値ベクトルから正解値ベクトルを引いたものになる。

中間レイヤーの誤差は以下の式で求められる。各パラメータ自身が次のレイヤーに伝播させてしまった誤差を算出すると考えればよい。バイアス項は含めなくてよい。

入力レイヤーの誤差は存在しないので算出する必要はない。

ユニットの入力 a(l) に、直後のレイヤーの誤差を掛け合わせたものが、各パラメータの偏微分となる。

Regularization を行なう場合は、各パラメータ毎にペナルティを与えればよい。コスト関数と同様に、バイアス項は除外する。

Numerical Gradient

Backpropagation を正しく行なえているかどうかは、一つのパラメータのみ極小値で増減させて、二つのコスト関数を適用した差分が Backpropagation で得た偏微分とほぼ相違ないこと(1e-9 以下が目安)をチェックすればよい。

function grad = numericalGradient(J, theta)
  m = length(theta);
  grad = zeros(m, 1);

  E = 0.01; % epsilon;
  for i = 1:m
    theta1 = theta; theta1(i) = theta1(i) + E;
    theta2 = theta; theta2(i) = theta2(i) - E;
    grad(i) = (J(theta1) - J(theta2)) / (2 * E);
  end
end

すべてのパラメータに対してコスト関数を適用するため、非常に処理時間がかかる。あくまで Backpropagation が正しくおこなえているかのチェックのみで、実際の学習処理に含めてはならない。

Symmetry Breaking

ニューラルネットワークにおいては、レイヤーの出力として、次のレイヤーの各ユニットへ同じ入力が与えられる。このため入力に対するパラメータ(重み)が同じ値の場合、同一レイヤー内の全てのユニットの出力が同じ値になってしまう。

  • 初期パラメータを全て 0 にすると、バイアス項のみが伝播する。
  • 初期パラメータを全て 1 にすると、全てのユニットの出力が、前ユニット出力の総和のシグモイド値になる。

このため Backpropagation を開始する際の初期パラメータは、ランダムである必要がある。-ε .. ε の範囲でランダムに設定するとよい。

E = 0.01 % epsilon
Theta1 = rand(3, 4) * (2 * E) - E; % initialize to 3 x 4 random matrix
Theta2 = rand(3, 5) * (2 * E) - E; % initialize to 3 x 5 random matrix