
[!] この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
最近はスマートフォン用アプリケーション、あるいは家電や車、ライフラインを管理するシステムなどに至るまで、あらゆる場面でAI(artificial intelligence)が利用されているというのはみなさん周知の事実かと思います。
このAI、ひと昔前までは専門知識の無い人にはなかなか敷居が高く、自分でどうこうするのは難しいものでした。しかし、今やこのAIに関する技術はより身近になってきており、多くの企業から「簡単にAIが作成できる」という触れ込みでソリューションが公開されていることはご存知でしょうか。
実際に、ちょっとAIを試したり、アプリケーションに組み込むといった形で利用すること自体は、非常に簡単になってきており、専用のアプリケーションを使えば一般の方でもGUIを用いて簡単にAIを作成できる環境が整いつつあります。
また、我々開発者がAIを作ってみようとした場合においても、多くのプログラミング言語でAI関連の開発用のライブラリが開発されており、非常に少ないコード量である程度思った通りのAIを開発することが可能になっています。
以下はAIを用いたソフトウェアの構成の例です。
オレンジ色の部分が開発者が自分でプログラムを書いて作成する部分、青い部分はありものを利用したり、GUIを使って簡単に作成するイメージです。
今回この図の一番右のパターンで、AI(中でも多くの場面で利用されているニューラルネットワークという機械学習モデル)をあえてスクラッチしてみようというのがブログのテーマになります。
スクラッチする意味
スクラッチとは
本題に入る前に「スクラッチ」とは何のことか皆さんご存じでしょうか。
いわゆるDJの方がするあれのことや、ひっかいたりすることではもちろんありません。IT業界(特に開発者の界隈)で「スクラッチ」するとは、「最初から開発する」という意味になります。
つまり、今回は「ニューラルネットワークをプログラムで実装する」というケースにおいて、世に多く存在する便利なライブラリを利用することなく1から実装してみようということになります。
なぜスクラッチするのか
それではなぜそんな面倒なことをするのでしょうか。AIを「使う」だけであれば前述の通り、現在では多くのライブラリやアプリケーションのおかげで比較的簡単に使うことが出来ます。しかし、その状態ではAIを「ブラックボックス」つまり「なんなのか中身はよくわからない」という状態で使っていることになってしまい、以下の問題が発生します。
- うまくいかない場合にどこに問題があるのかわからない
- 問題にどう対処したらいいのかわからない
- うまくいっていても本当に今後も問題ないのかわからない
- 細かいカスタマイズができない
また、ソフトウェア開発者にとって「自身の開発したソフトウェアで何が起きているのかわからない」というのは、たとえ思った結果を得られていたとしても気持ちが悪いものです。
何が言いたいのかというと、「 知るというのは大事 」ということです。
そして知らなければスクラッチ開発など到底できません。逆に、スクラッチ開発していくことで、座学だけでは本当は理解していなかったことを、目の前で動く形で体感しながら学ぶことができます。
それに特にAIというものに対して、「いったい中で何が起きているんだろう」、「どうやってこんなことを実現しているんだろう」と疑問に思ってモヤモヤしていた人の知的好奇心も満たすことができると思います。
具体的に何を作るのか
今回ニューラルネットワークをスクラッチすると言いました。それでは簡単にニューラルネットワークについて説明したいと思います。
ニューラルネットワークは上記のようなモデルになります(上記は正確には「多層パーセプトロン」あるいは「全結合ニューラルネットワーク」という分類のものになります)。ニューラルネットワークは人間の脳を模したモデルとなっており、ニューロンと呼ばれるものがネットワーク状に連結している構造になっています。構成要素は以下の通りです。
- ニューロン
図の中の○で描かれたものがニューロン(あるいはノードなどとも言う)にあたります。このニューロンは1つ1つがパーセプトロンと言われるモデルになっています(パーセプトロンについては後述)。 - 層
図をみて層状になっているのが分かりますでしょうか。入力データを受けているニューロンの3つが「入力層」、出力側の3つのニューロンが「出力層」と呼ばれ、間の4つずつのニューロンは中間層(あるいは隠れ層)と呼ばれます。
ニューラルネットワークはこのような構造をしており、数値を受け取って数値を出力するいわゆる関数のようなものになります。
ニューラルネットワークに関するもう少しだけ詳しい解説
人間の脳はたくさんの神経細胞がネットワークを構成しているような作りをしていると言われ、ニューラルネットワークはそれをモデル化していると言えます。 上記の画像の例であれば入力として3つの数値(例えば[1,0,1])を受け取り、それに対応する3つの数値(例えば[0,1,1])を出力しているモノをイメージしていただけるとよいと思います。誤解を恐れずに言えばニューラルネットワークは1つの関数のようなものです。いくつかの数値(データ)を受け取り、それに対して目的に則した数値(データ)を出力します。 こんなものがニューラルネットワーク?これがAI?とお思いでしょうか。こんなもので人間に囲碁で勝利したり、画像の中から特定の人を判別したりするとはなかなか考えにくいかもしれません。しかし、人間も目や耳などの五感というセンサーで受け取った情報を電気信号に変換し、それを神経細胞が信号でネットワーク状にやりとりを行い、適切な判断のもとで適切な信号(例えば筋肉をどう動かすかなど)に変換して出力しています。 AIも同様で上記のようなモデルの前後に必要な入力データを数値データに変換し、ネットワークの出力を適切な形で処理する機能を通して出力することで便利な機能を実現しています。ニューラルネットワークとパーセプトロン
ニューラルネットワークは数値を受け取って数値を出力するもので、ネットワークの中では数値を足し算したり、掛け算したりといった計算しか行っていません。AIと言えば 学習して賢くなる(精度を向上させる) というイメージがあると思いますが、ニューラルネットワークは計算しているだけ、つまり学習したものを 直接記憶はしていない ということです。
ではその計算とはいったいどんなことをしているのか、ニューロンの中をみてみましょう。
パーセプトロン
1つのニューロンは前述の通り、パーセプトロンというモデルになっています。パーセプトロン(あるいは形式ニューロン)は以下のようなモデルです。
図中で使用している記号の意味は以下の通りです。
記号 | 名前 | 備考 |
---|---|---|
![]() | 入力値 | |
![]() | 重み | 各入力値に個別に掛け算される値で、当該ニューロンにとっての入力値の重み(重要さ)を表現している値です。 |
![]() | バイアス | ニューロン全体の値の大きさを調整する役割があります。 |
![]() | 活性化関数 | 最終的にニューロンから出力される値を調整し、出力の表現力を豊かにする役割があります。詳細は割愛しますが、シグモイド関数やReLU関数などよく利用される関数があるのでそこから選択することが多いです。 |
![]() | 出力 |
パーセプトロンが行うことは図にある①~③になります。
①:各入力値に対して重みWn
を掛け算する
②:①の各入力値に重みを掛けたもの全てとさらにバイアス(b
)を足し算する
③:②で計算された結果を活性化関数a()
に通して、結果を出力とする
このようなパーセプトロンが連なっているのがニューラルネットワークということになります。
学習について
ここまでの話でニューラルネットワークが入力値を受け取った後にどんな計算をして値を出力しているかがお分かりいただけたと思います。しかし、これだけではAIが画像を判別したり、株価を予測したりできる説明がつきませんね。
さて、どのようにしてそんなことを実現しているのでしょうか。AIと言えば学習です。AIは学習して賢くなる(つまり精度をあげる)ものですよね。ニューラルネットワークはニューロン内の 重み、バイアス といった前述のパラメータを、入力に対して都合の良い出力を得られるように調整することでそれを実現します。つまりニューラルネットワーク(AI)の 学習 とはこの 重みやバイアスといったパラメータを調整すること を言います。
では具体的にどのようにしてこの調整を行うのでしょうか。これについてはさらに 勾配降下法 や 誤差逆伝搬法 といった内容について説明する必要がありますが、これらについては具体的な実装と合わせて次回のブログで記載したいと思います。
どんなニューラルネットワークを作るのか
それではニューラルネットワークの説明はこのくらいにして、今回のブログのテーマである「スクラッチ開発するニューラルネットワーク」で具体的にどんなことができるAIを作るのかについて記載したいと思います。
MNIST
AIに触れる人にとってのHello world的な題材でMNIST(MNIST handwritten digit database, Yann LeCun, Corinna Cortes and Chris Burges ⧉)というものがあります。MNISTは手書き数字の白黒画像データ(※)で、1枚に1文字の手書きの数字画像が6万枚以上用意されています。この手書きの数字画像データの1文字分のデータを入力として、0~9のどの数字であるかを判別するという題材です。 ※1文字の画像は28x28のグレースケール(1つの画像分のデータとしては縦28x横28=784個の数値データで、1つの数値は色を表現した0[黒]~255[白]の値)
上記はデータを抜粋し、並べて1つの画像にしたものです。今回作成するニューラルネットワークはこのMNISTを題材としたいと思います。つまり、スクラッチしたニューラルネットワークで手書きの数字が何なのか?を判別するAIを作成するということになります。
具体的には
- 入力
28x28のグレースケール画像データをフラットにした784の数値(0~255)データ - 出力
10個の数値配列データで、入力された画像の数字にあたるindexの数値が1、他が0というデータ (例えば入力されたのが2であれば[0,0,1,0,0,0,0,0,0]という配列データ)
このような形のニューラルネットワークになります。
開発要件
最後に改めて開発要件についてまとめておきます。
■使用言語
Python
選択理由:AI実装において利用される機会が多く、今回は利用しませんがAIや機械学習用のライブラリなども充実しているため。
■機能
28x28の手書き数字が書かれた画像データを受け取り、その画像データが0~9のうちのどの数字かどうかを判定する機能
■ポイント
利用するライブラリはPythonが標準で具備するもののみとする(ただし、メイン機能以外の例えば学習データのダウンロードなどについては例外とする)。Pythonにはnumpyなどの行列計算に長けたライブラリが存在しますが、これらの便利なAPIを利用すると実際に行っている計算が見えにくくなるため、計算は全て純粋なPythonのコードで実装します。
次回
次回は具体的な実装に入りつつ、ニューラルネットワークが学習して精度をあげる仕組みについて書きたいと思います。