理工系初学者のためのニューラルネットワークの仕組み

テクノロジー

最近は人工知能や機械学習という言葉をよく聞きます。それらの基本になる、ニューラルネットワークについて改めて学習したので記します。

なおこの記事は、「仕組みを理解するために初心者向けの書籍を読んでみたが、数式を読み解く中で何をやっているのかが分からなくなってきた」という理工系初学者向けに書いています(理工系向けなので、大学で習う数式の書き方(太字がベクトルを表す等)を知っていることを前提とします)。この記事で扱う範囲は勾配降下法による学習までであり、誤差逆伝播法は含んでいません。

やりたいこと:入力を与えると良い感じの値を出力する関数を作りたい

機械学習の本を読むと、数式やらコードやらが大量に出てきます。数学とプログラミングが得意な人なら1つずつ読めば理解できますが、時間がかかりますし、「部分部分は分かったけど、結局何をしているのかがよく分からない」という人もいるかと思います。少なくとも私はそうでした。

そこで、結局何をしているのかを先に頭に入れておきます。

入力を与えると、良い感じの値を出力する関数を作りたい。そのために、教師データを使って関数を良い感じに作り変える。

数学風に表現すると次の通りです。入力データを\bm{x} = (x_1, x_2, \cdots, x_N), 出力を\bm{y}, 最終的に作りたい関数をfとすると

\bm{y} = f(\bm{x})

となります。そして、このfをいかに作っていく(調整していく)かがディープラーニングの真骨頂です。

ニューラルネットワークの作り方

さて、この手の文脈で出てくる関数fの単純な形の1つは、2次元の入力を与えると1次元の出力を与えるもので、例えば次のようなものです(単純パーセプトロンと呼ぶ)。

y = h(x_1w_1 + x_2w_2 + b)

またはベクトル風に書くとこうなります。

y = h(\bm{w}^T\bm{x} + b)

ここでhとして出てくるものがいわゆる活性化関数で、最も単純なものはステップ関数(入力が0以上なら1, それ以外は0を返す)ものです。ここで、例えば上記の式なら、w_1 = w_2 = 0.5, b = -0.7として、x_1, x_2を0か1だとすると、ANDゲートを実装したことになります(数値例は参考文献から引用)。

これだけだと非常に単純なロジックしか実装できません。しかし、活性化関数をステップ関数だけでなくSigmoid関数やReLUなどに変えたり、次元数を増やしたり、層を重ねたり(1段目の出力を2段目の入力とする)、その他様々なテクニックを入れていくことで、かなり複雑なロジックを実装できます。これがニューラルネットワークと呼ばれるものです。

パラメータの学習

さて、ニューラルネットワークは単純パーセプトロンを発展させたものですが、活性化関数や次元数などを固定したとすると、後はパラメータ\bm{w}, bを変えることで関数の特性を変化させることができます。

先ほどは\bm{w}, bの具体的な数値を書きましたが、このような単純な例ならまだしも、実際に使われるような複雑なものだと、人間の頭で数値を考え出すのはほぼ不可能です。そこで以下では

パラメータを、教師データを使って学習させる(教師データに良い感じに合うようにパラメータを自動調整させる)

ことを考えます。

なお層を重ねたりする関係で次元を増やすと、上記の式は

\bm{y} = f(\bm{x}) = h(W\bm{x} + \bm{b})

と書くことができるので、以下ではこのように表すことにします。(行列として計算すると表記がシンプルになるほかに、高度に最適化された科学計算用ライブラリを直接的/間接的に使えるため計算速度が速くなるというメリットがある)

パラメータの学習と最適化

さて、パラメータをどうやって学習させればよいのでしょうか。ここでは、「最適化」と呼ばれる方法を使って学習していきます。

教師データのうち入力を\bm{x}、出力(正解)を\bm{t}とかくことにします。そして、損失関数Lを定義します。

損失関数とは、ニューラルネットワークの出力と正解の出力とでズレがあるほどほど大きくなる関数で、例えば誤差二乗和が使われます(ここで、\|\cdot\|L^2ノルムとします)。

 L = \frac{1}{2}\|\bm{t} - f(\bm{x})\|^2 = \frac{1}{2}\sum_i\left(t_i - f(\bm{x})_i\right)^2

そして、最適化の技法(ここでは勾配降下法を使う)でLが小さくなるようにパラメータを変えていけば、ニューラルネットワークの出力と正解の出力とのズレが小さくなるので、結果的に正解に近い結果を出すニューラルネットワークを得ることができます(これがそもそもの目的でした)。

ここで注意したいのは、何気なく書いたf\bm{x}によって当然変化しますが、W, \bm{b}によっても当然変化することです。そして、パラメータW, \bm{b}を最適化するのが目的であることに注意して下さい。(最適化に関する部分だけを読むとxを動かすような錯覚に陥ることがあるが、むしろxは固定するイメージ)

ここで、勾配\left(\frac{\partial L}{\partial W}|_{\bm{x} = \bm{x}}, \frac{\partial L}{\partial \bm{b}}|_{\bm{x} = \bm{x}}\right)を数値微分で計算し、適当な学習率\etaを乗じてパラメータを最適化していきます。

(W, \bm{b}) = (W, \bm{b}) - \eta \left(\frac{\partial L}{\partial W}, \frac{\partial L}{\partial \bm{b}}\right)

これを繰り返して、学習が進んだと思われる時点(損失関数の減り方が小さくなった時など)で学習を終了することで、目的のニューラルネットワークを得ることができます。

なお、原理的にはすべての教師データを使って学習すれば良いですが、データ量が多い場合は時間がかかって仕方がないので、一部のデータをランダムに選んで学習させる(確率的勾配降下法)といったテクニックが使われます。

テストデータでの検証

この学習で得られたニューラルネットワークに、教師データとは別のテストデータを与えて出力を見てみましょう。教師データとテストデータが似た性質を持つのであれば、恐らくそれなりに良い(正解に近い)結果が出てくるはずです。

もし全然違う結果が多数出てくるのであれば、ニューラルネットワークの構成が適切でないか、学習率\etaが適切でないか、入力値として使ったデータ(特徴量)が適切でないか、過学習を起こしているのだと考えられるため、色々と試行錯誤していく必要があります。このあたりのトピックは、世界のトップクラスの研究者が各国の研究機関や企業(Googleなど)で盛んに研究を行っている内容であり、またデータサイエンティストの腕の見せどころでもあります。

終わりに

人工知能は今やバズワードであり、色々な書籍やネット上の記事も多く出ています。

しかし、何をやりたいのかが明確でないと、読んでいても味気ないものです。そこで、簡単な数式なら理解できる理工系初学者向けに解説を書いてみました。

何を目指すかによって必要な理解度は異なります(AI界隈の研究者になるのか、仕事や教養として仕組みを理解したいのか、ただ使えればよいのか、口八丁で夢物語を語ってクライアントを騙すのか)。この記事が、仕組みを理解したい人にとっての一助になれば幸いです。

なお、この記事は参考文献やその他の書籍・記事をもとに私が独自に解釈したであり、私も上記が間違っていないとは言い切れないので、ぜひ他の文献も読んでみることをおすすめします。

参考文献: