関数近似から学ぶ、深堀りしすぎないニューラルネットワーク入門

道下です。今更ながら、LLMの盛り上がりなどで注目されているニューラルネットワークについて最近学びました。
ニューラルネットについてインターネットなどでちょっと調べた程度だと、大体上のような図が出てきて、ニューラルネットは人間の脳を模しているとか層が何種類かあるといった話が始まり、結局これは何をするためのもので、どういう仕組みで色々な問題が解けるのかが全然わからない、というのがこれまでの私の状況でした。今回はある程度書籍などを通してニューラルネットについて学んだ後に学習以前の気持ちを振り返って、「この点を最初に理解しておくべきだった」と思った内容を記事にしました。
想定読者
自身で本格的に機械学習を行う方というよりは、
- MLOpsなどの文脈でモデルの管理やデプロイを行う必要がある
- AIを絡めたビジネスの意思決定を行う必要がある
といった方が機械学習の話題についていくために必要最低限のイメージを掴む一助になればと思っています。具体的には以下のような事項について、詳細は省きつつ本質的な部分を理解していただくことを目指します。
- ニューラルネットの学習と推論とは何なのか
- ニューラルネットの学習済みモデルとはなにか。何が入っているのか
高度な数学的知識は仮定しておらず、おおむね高校1年生程度の知識で読めるかと思っています(私自身、大学では文系でした)。
注意点として、この記事はニューラルネットワークの正確な定義や技術的な詳細については書いていません。ニューラルネットそのものについて詳しく説明するというよりも、前提として関数近似という考え方を理解することで、ニューラルネットの役割や長所などについて概要レベルで理解しようという趣旨になります。
関数近似で問題を解く
関数としてのAI
ニューラルネットについて考えるために、何か具体的で多少は実用的な例として、手書き数字の識別を考えてみます。これは以下のような手書きの数字画像を与えられた時に、それに何が書かれているかを答えるというタスクです。以下の画像はMNISTという有名なデータセット(取得元:https://ossci-datasets.s3.amazonaws.com/mnist/train-images-idx3-ubyte.gz)から抽出したものです。MNISTは機械学習の研究や教育、学習などでよく使われています。

手書き数字の識別ができるAIがほしいという時、実際のところ私達が欲しているものは「関数」であると言えます。
- \(f(x)=2x\)という関数が3という入力に対して6という出力を返す
- \(f(x,y)=x \cdot y\)という関数が\(x=2\),\(y=3\)という入力に対して6という出力を返す
のと同じように、左上の画像を入力として受け取ったら「3」という出力を返すような関数が欲しいのです。
数字をそのまま入力として与える場合と画像を与える場合とでは違うように感じるかもしれませんが、本質的には変わりません。MNISTデータセットの手書き数字は28*28=784ピクセルのグレースケール画像で、各ピクセルは255段階の明度で表されます。全てのピクセルの明度を並べれば784個の数字の羅列にできます。したがって、手書き数字を受け取る関数は\(f(x_1, x_2, \ldots, x_{784})\)という784個の数字を入力として受け取る関数と定義できるのです。\(f(x,y)=xy\)のような関数よりも変数の個数が多いだけです。
私達が欲しいのは、あらゆる28*28のグレースケール画像が何の数字を表しているのかを、人間が見て判断するのと同じように答えてくれる784変数関数です。そのような関数はどうすれば得られるのでしょうか。
関数近似
これに対する一つの回答が関数近似です。ここで扱う関数近似は、パラメータを持った関数に対してパラメータを調整することで、所望の関数に近づけることを指します(厳密には異なるものもありますがこの記事の範囲内ではこの理解で大丈夫でしょう)。
先ほどのMNISTの手書き数字データには、入力画像とそれが表す正解の数字が対応付けられて保存されています。このように既知の入力と出力の対応データ(学習用データといいます)が存在する場合は、その対応をなるべく再現できるような関数近似を行います(教師あり学習)。
ニューラルネットで解きたい問題は最初から正解がわかっているものだけではないため、この説明がそのまま当てはまらないケースもありますが、この記事では教師あり学習を念頭において説明を進めます。教師ありの枠組みで関数近似のイメージを掴んでもらえれば、教師なしなどの他の手法もそれほど苦労せずに理解できると思っています。
このような抽象的な説明ではわかりにくいと思うので、以降で実際に関数近似を視覚的に体感していただきたいと思います。
関数近似を体感してみる
一変数関数の多項式近似から
関数近似手法の例として、まず多項式近似を見ていきます。後でもう少し詳しく説明しますが、関数には様々な表現方法があります。その中でどの表現方法を使って近似を行うかが、関数近似手法ごとに異なるというわけです。多項式近似は名前の通り、\(y = a_0 + a_1 x + a_2 x^2 + \dots + a_n x^n\)のような多項式という表現方法を用いて関数を近似します。\(x^n\)の項はいくらでも増やすことができますが、ここでは\(x^4\)ぐらいまでにしておきます。
たとえばあるアイスクリーム店の売上データがあるとします。青い点が実際の売上データをプロットしたものだとしましょう。x軸が気温、y軸が売上(10000円単位)を表します。
これらの点になるべくフィットするような曲線を表す関数を求められたら、ある程度気温から売上を予測することができそうです。ここでは、\(y=a + bx + cx^2 + dx^3 + ex^4\)という式のa,b,c,d,eという係数を適切に設定することで、青い点群にフィットする関数を作ってみたいと思います。
実際にこれを体験するために、グラフの下にあるスライダーで各係数を増減させてみてください。たとえば2次以上の項の係数(c~e)をゼロにしたままaとbだけを調整すると、中学1年で習う一次関数\(y=ax+b\)の形になり直線を表します。そこからより高次の項を増やしていくと関数の形をより柔軟に調整できます。パラメータが増えるにつれ関数の表現力が上がるということを体感してください。このUIでは4次の項までですが、より高次の項を増やせばもっといろいろな曲線を表現できます。
さて、正解例を見るとかなり点群にフィットしたグラフが得られていることがわかると思います。正解例の曲線が表している関数はおおよそ\[y = 15.688203 + 1.288113 x + 0.058026 x^2 - 0.003789 x^3 + 0.00005 x^4\]です。もしも何らかの未知の入力、たとえばデータに含まれていない16℃という入力に対して売上を予測したければ、この関数のxに16を入力として与えればいいのです。つまり、\[f(16)= 15.688203 \cdot 16 + 1.288113 \cdot 16 \\ + 0.058026 \cdot 16^2 - 0.003789 \cdot 16^3 + 0.00005 \cdot 16^4\]を計算して、約38.91が得られます。単純な例ではありますが、予測モデルとして機能する関数を得ることができました。
多項式近似は最適なパラメータを得られる公式のようなもの(最小二乗法)が知られており、正解例もそのようにして計算しています。現実の問題を解く際に、グラフを見ながら人間が手でパラメータを調整するようなことはないと思います。あくまでも説明のためのUIです。

多変数にしてみる
先ほどの例は、変数が気温のみの一変数関数でした。手書き数字認識が784変数関数であったように、現実の問題の多くはたくさんの変数を持ちます。引き続き多項式近似で、今度は多変数の例を体感してみましょう。
今度はx:気温 y:湿度という2つの変数によってz:売上が決まるようなデータが与えられたとします。以下ではxyz座標系に売上データを赤い点でプロットしています。\(z = a x^2 + b y^2 + c xy + d x + e y + f\)という関数のパラメータを調整してこれを近似してみます。
ここでも先ほどと同様に係数a,b,c,d,e,fをスライドして点群にフィットする面を作ってみてください。二変数になっただけでも先ほどより挙動が理解しにくくなり難しくなったと思います。項数があまり多くないので正解例を見てもそれほどフィットしていないように感じるかもしれません。
ここで得られた正解例の関数は\[z = -0.636x^2 - 0.052y^2 + 0.129xy + 34.158x + 0.621y - 450.244\]です。これに対してもやはり未知の入力、たとえば\((x,y)=(25,60)\)を与えると、49.77という予測が得られます。
ここまでで、関数近似というのがどういったものかイメージを掴んでいただけたかと思います。既知の入力データに対して関数パラメータの調整を行って良い近似が得られれば、未知のデータに対しても答えを出せることがわかりました。
二変数の時にも述べた通り、多項式近似では項をどんどん増やしていけば関数の表現力が上がり、(一定の条件を満たせば)いくらでも良い一様近似が得られます。そのため、ここまでの延長で多項式を784変数にして大量のパラメータを持たせれば、手書き数字を入力として受け取って正解の数値を返すような関数も理論上は作ることができます。ただしそれは理論上の話であり、後述するように、調整するのが非現実的なパラメータ数になってしまいます。
関数近似を効率よく行うには
大量のパラメータをどう探索するのか
なぜ多項式近似で手書き数字認識の関数を得るのは難しいのでしょうか。問題は、入力変数が増えると関数パラメータも増えて、理想のパラメータを得るのが大変になるということです。一変数のときは4つのパラメータでそれなりに良い近似が得られましたが、二変数になると6つのパラメータを使ってもあまりフィットしていないように見えたはずです。ある程度良い近似を得ようと思うと、変数の増加に対してパラメータ数が爆発的に増加するのです。さらに、一変数から二変数になった時、各パラメータの変化が最終的な出力にどう影響するかを理解するのがかなり難しくなったと思います。(先に述べた通り、実際には多項式近似のパラメータは微調整を繰り返さなくても計算によって求めることができますが、それでも784変数関数の理想のパラメータを計算するのは現実的に困難です。)
現実には、何らかのアルゴリズムを用いてコンピュータに関数パラメータを探索させる方法がよく使われます。ただし、コンピュータが人間よりはるかに高速に計算できるとしても大量の変数を持つ関数を近似するには工夫が必要です。パラメータをどう増減すると出力にどう影響するのかわからない状況で闇雲に増やしたり減らしたりするような方法では、コンピュータでも手に負えないぐらいの時間がかかります。ではどうすれば効率よくパラメータを探索できるのでしょうか。それを考えるためには関数の表現方法から見直す必要があります。
関数の表現方法
ここまでは多項式という表現方法を用いる多項式近似を例に説明してきましたが、前に少し触れた通り、関数の表現方法は他にも色々あります。表現できる関数の幅や得意な関数の形状、パラメータ探索の難しさなどは表現方法によって異なります。コンピュータによるパラメータ探索と相性が良いものもあれば悪いものもあります。関数パラメータを効率よく探索するには、そもそも関数の表現方法から吟味する必要があるのです。
イメージを持っていただくために、多項式以外の関数の表現方法をいくつか見てみましょう。
フーリエ級数
多項式以外の代表的な関数の表現方法として「フーリエ級数」があります。これは、三角関数(sin波やcos波)を組み合わせることで関数を表現する方法です。
数学的な知識をほとんど仮定しない記事なのであまり深入りする気はありませんが、多項式が\(x^n\)のようなべき乗の和で様々な関数を表せたように、三角関数の和でも様々な関数を表せるのです。
入出力の列挙
数式だけが関数の表現方法ではありません。極端な例に思うかもしれませんが、以下のように入力と出力を書き並べたものも関数の表現方法と言えます。
x | y |
1 | 2 |
2 | 4 |
3 | 6 |
もちろんこの書き方ではここまでで扱ったような実数関数のように無限の点を持つ関数は扱えません。数式に比べれば冗長で頼りなく感じるかもしれません。しかし入力と出力の間に数学的な関係を見出すことができないような関数など、数式で表現するのは難しくともこの方法でなら表現できるというものも存在します。
ニューラルネットワーク
ニューラルネットワークも関数の表現方法の一種です。ニューラルネットによって表現された関数のパラメータは、ある種のアルゴリズムを使うことで効率よく探索することができます。これによって、多項式近似のような手法では難しかった手書き数字認識のような問題に答える関数を得ることができます。
次節でニューラルネットについて見ていきます。
ニューラルネットワーク
ニューラルネットワークによる関数近似も体感してみる
ニューラルネットをタイトルに掲げておきながら申し訳ないのですが、この記事ではニューラルネットの一般的な定義を述べません。というのもこの記事の目的のためには、「ニューラルネットは関数の表現方法の1種で、パラメータの探索を効率よく行えるものなのだ」と知ってもらえれば充分だと思うからです。ニューラルネットがどのような関数を表現するかの詳しい説明はインターネットで簡単に見つかると思うので、ここでは省略します。
というわけでいきなりニューラルネットの具体例を1つ出し、それがどんな関数を表現しているのか説明します。一変数の多項式近似で使った気温とアイスクリームの売上データを、以下のようなニューラルネットで近似してみます。(なお、実際にはこの例でニューラルネットを使う利点は特にありません。ニューラルネットによる関数近似を体感するためだけの例です。また、このニューラルネットはパラメータ数が過剰気味ですが、後の手書き数字認識の説明に繋げるためにあえてそのようにしています。)
このニューラルネットが表しているのは次のような計算です。まず、一番左にあるxが入力です。今回近似するアイスクリームの売上の関数でいうと気温が与えられます。xは真ん中の層の\(h_1\),\(h_2\)というニューロンにつながっています。xと\(h_1\)を結ぶ矢印には\(w_1\),\(b_1\)というパラメータがあります。wはweight(重み)、bはbias(バイアス)を表しており、入力データに対して重みを掛けてバイアスを足すというのがニューラルネットの最も基本的な動作です。したがって、\(h_1\)への入力は\(x \cdot w_1 + b_1\)となります。
ここが少し難しそうに見えるのですが、\(h_1\)では入ってきた値に対して活性化関数と呼ばれる関数を適用します。ここでの活性化関数は以下のように定義されるシグモイド関数を使います(eはネイピア数)。
\[\sigma(z) = \frac{1}{1 + e^{-z}}\]
いきなりよくわからない関数が出てきて混乱したかもしれません。申し訳ないのですが、この記事ではなぜシグモイド関数を使うのかを詳しく説明するつもりはありません。今回使うニューラルネットではこのような関数を適用するのだということで受け容れてください。一見複雑そうに見えるかもしれないですが、四則演算やべき乗の計算を行っているだけで、やっている事自体はそれほど難しいことではありません。

したがって、シグモイド関数\(\sigma(z)\)を使って、\(h_1\)の値は\(\sigma(x \cdot w_1 + b_1)\)と表せます。同様に\(h_2\)も計算します。
その後\(h_1\),\(h_2\)から次の矢印へ進む時も同じように重みを掛けてバイアスを足します。そうして得られた2つの値を足したものが最終的な出力\[y =w_3 \cdot h_1 + b_3 + w_4 \cdot h_2 + b_4\]です。\(h_n\)という中間の変数を使わずに表すと、\[y =w_3 \cdot \sigma(x_1 \cdot w_1 + b_ 1) + b_3 + w_4 \cdot \sigma(x_1 \cdot w_2 + b_2) + b_4\]になります。σも展開すると、\[y = w_3 \cdot \frac{1}{1 + e^{-(x_1 \cdot w_1 + b_1)}} + b_3 + w_4 \cdot \frac{1}{1 + e^{-(x_1 \cdot w_2 + b_2)}} + b_4\]ですね。
今までに比べると複雑に見えますが、四則演算とべき乗以外のことは行っていません。具体的なxや\(w_n\), \(b_n\)の値が与えられれば、代入して関数の値を計算することは中学までの知識でできるはずです。
さて、今までと同じようにグラフ化してパラメータ調整を体感してみましょう。
ニューラルネットでもパラメータを調整することで様々な曲線が表現できることがわかったと思います。実際、ニューラルネットも多項式同様に、一定の条件のもとで任意の連続関数を一様近似できます(普遍性定理)。
これまで同様に正解例の関数を数式で表すと\[f(x) = 16.70 \cdot \frac{1}{1 + e^{-(0.23x - 3.10)}} + 5.60 \ + 17.10 \cdot \frac{1}{1 + e^{-(0.38x - 1.50)}} + 5.60\]となります。未知の入力16℃をこの関数に与えれば、約38.83という出力が得られます。
後述しますが、これまで何度も正解例の関数に実際の値を代入するところを示していたのは、実はこれがニューラルネットの推論に該当する行為だからです。
ニューラルネットで手書き数字認識もできる
先に述べた通りニューラルネットはコンピュータによるパラメータ探索と相性が良いため、多くの学習用データを用意してコンピュータにパラメータを探索させれば、手書き数字認識のような多くの入力変数を持つ複雑な問題でもかなり良い近似を得ることができます。
たとえば、書籍『ゼロから作るDeep Learning』※1のサポートサイトに掲載されているニューラルネットの実装(MITライセンス)は以下のような構成になっており、適切に学習させることでMNISTデータセットの手書き数字認識問題に大して90%以上の正答率を出すことができます。
このニューラルネットについて少し説明します。各層の横のカッコ内の数字は層のノード数です。入力層が784個のノードからなるのは784変数関数だからです。隠れ層のノード数は任意で、良い結果が出るようにニューラルネットの設計者が調整します。ここでは50になっています。出力層については、手書き数字が0~9のうちどれであるかを確率で出力します。たとえば手書き数字が3である確率が90%、2である確率が10%と判断した場合は[0,0,0.1,0.9,0,0,0,0,0,0]のように出力します。この中で最も確率が高いものをニューラルネットの回答とみなせます。層と層を繋ぐエッジには先ほどと同様に重みとバイアスというパラメータがあり、各層の入力に重みをかけてバイアスを足す(中間層ではシグモイド関数を適用する)というのも同じです。基本的にはノードとエッジの数が増えただけで、先ほど体感していただいたニューラルネットとやっていることに大きな違いはありません(出力層にsoftmaxという活性化関数を使っているという違いはあります)。
この記事では、説明のわかりやすさのために、28×28ピクセルをフラットに並べて処理する形式で手書き数字認識問題を扱ってきましたが、実際の画像認識タスクでは空間構造を保ったまま処理できる畳み込みニューラルネット(CNN)などの手法が用いられることが一般的です。

残念ながら、ニューラルネットがなぜコンピュータでのパラメータ探索と相性が良いかを説明しようとするとこの記事が長くなり過ぎてしまいます。ですが大まかに言えば以下のような感じです。ニューラルネットで表現された関数には、関数の出力と理想の出力との間のズレを減らすために各パラメータをどれくらい増減すべきかを効率よく計算する手法(誤差逆伝播法)があります。この仕組みによって、数百万ものパラメータを持つような大規模なネットワークでも、コンピュータが自動的にパラメータ調整を進めていくことができます。
もちろん、必ずしもすべての問題で完全に最適なパラメータが見つかるわけではありませんが、この「効率よく調整できる」という性質が、ニューラルネットが多くの場面で使われている大きな理由のひとつです。
当初の疑問に答える
ここまでの内容を踏まえれば、冒頭で言及した疑問に答えられます。
学習と推論とは何なのか。
ニューラルネットの学習とはパラメータの探索のことです。この記事ではパラメータ調整をスライダーで行っていただきましたが、実際には関数を適用して得られた出力を理想の出力と比較してパラメータを調整するということを、大量の学習用データに対してコンピュータで何度も繰り返します。
ニューラルネットの推論は、ニューラルネットで近似して得られた関数に入力値を与えて出力を得ることです。
学習済みモデルとはなにか。何が入っているのか。
学習済みモデルとは、抽象的にはパラメータの探索を経て得られた関数そのもののことを指します。他方で、実体のあるファイルを指して学習済みモデルということもあります。この意味での学習済みモデルとは、調整済みの関数パラメータの集まりです。アイスクリームの売上をニューラルネットで近似した例では、\(w_1,w_2,w_3,w_4,b_1,b_2,b_3,b_4 \)の値を保存したものが学習済みモデルということになります。現実の問題を解く際はパラメータ数が数百万やもっと大きな数になることが多いので、結果として学習済みモデルのサイズは大きくなります。ニューラルネットの構成がわかっていればこれらのパラメータを使って関数を復元することができるので、パラメータの集まりは学習済みモデルの物理的な実体と言えます。
※1 斎藤康毅(2016)『ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装』 株式会社オライリー・ジャパン