スポンサーリンク

Scratchで拡張機能などを一切使わずにニューラルネットワークを作ってみた【Scratch】【ニューラルネットワーク】

AI

今回は、Twitterで投稿した作品が思ったより反響があったのでちょっと詳しく紹介できたらなと思います。

Twitterで反響をいただいた作品↓

 

 

「Scratchで楽しく学ぶアート&サイエンス」の著者さんからもとても嬉しいメッセージをいただきました!

 

さまざまな方からメッセージをいただけました。ありがとうございます!

本も出してみたいのですが、自分自身がまだ本の作り方などを知らないので、まだ先になりそうです。(電子書籍から紙の書籍にしたほうがいいかなと考えています)

動画は、動画編集に時間がかかりそうだったので、まず最初に簡単に記事にまとめてから動画、本などでもっと詳しく紹介できたらなと思います。

実際の作品はこちらから↓

https://scratch.mit.edu/projects/564599222/

ProtoPediaに登録し、ヒーローズリーグに応募してみました!

Scratchでニューラルネットワークを作ってみた!(ライブラリなどを一切使わず!) | ProtoPedia
Scratchで、独自拡張機能や、ライブラリなどを一切使わずにニューラルネットワークを一から作ってみました。MNISTデータを用いて、高精度(約90%以上)で文字認識ができます!

この作品について

まず、この作品についてわからない方もいると思うので、一番最初に紹介します。この作品は、MNISTデータセットに対して推論処理を行うニューラルネットワークです。

そう言われてもわからないことがたくさんあると思うので、用語について解説していきます。

用語解説

・ニューラルネットワーク→脳機能に見られるいくつかの特性に類似した数理的モデル
・MNISTデータセット→機械学習分野でもっとも有名なデータセットのひとつ

つまり、人間などの脳の処理をプログラムで再現したものがニューラルネットワーク、有名なデータセットがMNISTデータセットと思ってもらえれば大丈夫です。

それでは、このニューラルネットワークの何ができるかを少し紹介したいと思います。ニューラルネットワークを使うと、画像認識や音声処理、自然言語処理など、さまざまなことができます。

そして、今回はできることの一部である、「画像認識」ができる作品をScratchで作ってみました。※この記事はあまり深いところなどは解説せずに、表面を簡単に説明します。

つまり、自分で書いた文字や、あらかじめ用意されているテストデータの画像を認識して、0~9の数字をニューラルネットワーク(AI)が高確率で認識してくれる作品です!

自分の書いた文字やテストデータから数字を認識する!

猫のよこにある文字がニューラルネットワークが導き出した答えです。

この作品のどこがすごいのか

それでは、この作品の一体どこがすごいのかなどを解説していきたいと思います。

かなり良い精度で文字認識ができる

テストデータが100個あり、それらを分類する精度(認識精度)は96%となりました。かなり精度が高いほうなのではないでしょうか。今後はもっとプログラムに工夫を施して96%以上にしたいと思っています。

AIの拡張機能や、自作ブロック、ライブラリを一切使っていない

ScratchにはAIの拡張機能や、自作ブロックがあるのですが、それらを一切使わず(ベーシックなScratch)ニューラルネットワークを作りました。

そして、ライブラリは、Scratchにその概念があるのかわかりませんが、一切使っておりません。PythonでいうNumPy(行列などの計算でよく使われる)などのことをライブラリと言います。

NumPyというライブラリを使うと、行列などの演算がかなり簡単に実装できるのでとても便利です。NumPyはインストールしてimportして使い方さえわかれば行列などの複雑な計算はNumPyがやってくれます。

しかし、Scratchにはそのようなものが標準で搭載されていないので、すべて自作でNumPyと同じような処理をするプログラムを全てScratchで実装しました。

NumPyというライブラリに似たプログラムをScratchで実装してみたことについてはまた別の記事で紹介させていただこうと思います。

つまりは、PythonなどではNumPyなどのライブラリなどで簡単にプログラムを作ることができますが、Scratchにはそういう機能は搭載されていないので、一から全部作ったということです!

汎用性のあるプログラム

この作品は、少しですが汎用性があります。作品の中に一部使われていないプログラムがあると思います。そのプログラムは、先ほど紹介したNumPyとの通訳者みたいなものです。

NumPyで行列をあつかうプログラムを書いた時に、Scratch側でもNumPyの記述で行列などを操作することができるようになっています。(少し書き方が違いますが)

MNISTのデータを読み込む際には使わなかったのですが、最初の演算の実験段階などでは、Pythonとの挙動を確認するためにかなり役に立ちました。

プログラムの解説

現在(2021/8/30)時点でもかなりプログラムの量が多いので、(ブロック数721個)全部をしっかりと解説することはまだできませんが、大切な部分などをまとめて解説していこうと思います。

プログラム解説①:多次元配列の演算(積と和)

多次元配列の演算(積)

多次元配列の演算のプログラムです。多次元配列である二次元配列を行列と呼びます。

ニューラルネットワークでは、簡略化すると、入力層のデータを重みで加工し、加工されたデータを隠れ層(中間層)に伝え、中間層のデータを重みで加工し、出力するという感じの計算をしています。

今回のニューラルネットワークは、

・入力層の数:784個
・中間層一つ目の数:50個
・中間層二つ目の数:100個
・出力層の数:10個

こんな感じです。入力層が784個あるのは、画像データの大きさが28*28ピクセルなので、それに合わせています。今回は0~9の数字を判定するので、出力層の数は単純に10個になります。

そして、計算の話にななるのですが、入力層から中間層に値が伝達される時、1つの中間層に全ての入力層の値が重みで加工されたあと入力されます。なので、784*50で39200もの重みで加工された39200の値を計算しなければなりません。

しかもそのあとに、50(中間層1)*100(中間層2)=5000もの重みで加工されたデータを出力層に…となります。なので、かなり計算がめんどくなりますし、管理が大変です。

しかし、行列を使うと簡単に計算できるので、行列(多次元配列)のプログラムを作ってそのプログラムに重みやバイアスなどの計算をさせています。

計算式はこんな感じです。

A(1)=XW(1)+B(1)

A(1)が中間層一層目、Xが入力、W(1)が一層目の重み、B(1)が一層目のバイアスを表しています。 今回は、全部で四つの層まであるので(入力、中間*2、出力)これが(4)まであります。

英アルファベットだけだとわかりにくいと思うので、各アルファベットの要素を軽く解説しておきます。

X(1)=100行784列のテストデータ、もしくは1行784列の入力データ
W(1)=784行50列
B(1)=1行784
A(1)=1行50列

このような感じです。この値を行列、多次元配列にして計算することによって、簡単にA(1)を求めることができます。

多次元配列の演算(和)

先ほど、入力層から中間層に値が伝達される時、1つの中間層に全ての入力層の値が重みで加工されたあと入力されるとかきましたが、今度はバイアスの概念を付け加えます。

重みは掛け算(積)で値を加工しましたが、それとは違い、バイアスは足し算で値を加工します。バイアスも重みと同じ数あります。

なので、単純に重みで加工された値に各バイアスの重みを「〜回繰り返す」で足していくだけです。プログラムが少し多く見えるのは、NumPyに対応するため、汎用性を持たせたためです。NumPyに対応させなければ半分以下のサイズになります。

多次元配列の演算の単体の作品を公開しているので興味のある方はどうぞ!

https://scratch.mit.edu/projects/564182862/

プログラム解説②:シグモイド関数

シグモイド関数、ニューラルネットワーク関係のことを知っている方はわかると思いますが、全くわからない方の方が多いと思いますので、説明します。

シグモイド関数は、活性化関数のことです。活性化関数は入力信号の総和がどのように活性化するかということを決定します。その中の一つがシグモイド関数です。

このシグモイド関数は、1より大きい数字であろうと小さい数字であろうと0~1の間に収めてくれます。

このシグモイド関数を使って、値をさらに加工し、次のニューロンに値を渡します。

式はこんな感じです。

プログラム解説③:ソフトマックス関数

ソフトマックス関数は、分類問題の際(今回のような場合)に使われます。出力層からの複数の出力値の合計が1.0(100%)になるように変換して出力する関数です。

なので、この関数を使うと、「0」の確率は40%、「1」の確率は10%…のように、わかりやすい出力となります。

式はこんな感じです。

ソフトマックス関数単体での作品があるので、気になる方はそちらもどうぞ!

https://scratch.mit.edu/projects/564579311/

プログラム解説④:画像の描画

ニューラルネットワークが文字を認識しているんだな、ということが少しでもわかりやすいように、画像を描画するプログラムも追加してみました。

やっていることはと今までのことに比べるととても簡単で、28*28ピクセルの画像データを二重ループを使ってスタンプで描画しているだけです。

なぜ手書き入力の認識精度は低いのか

このような投稿が。なぜ手書きの文字だと認識精度が低いのかというと、このニューラルネットワークはそもそもMNIST学習データを使っている、そしてScratchの手書き入力のデータはMNISTのデータとほぼ違うデータになっているからです。

解決策としては、手書き文字を学習する、Scratchの手書き入力のデータをMNISTのデータに近づける、のふたつがあります。

Scratchの手書き入力のデータはMNISTのデータとほぼ違うデータになっていることについて詳しく説明すると、MNISTの文字データの中央がほぼ1(白)とすると、Scratchで実装した方は0.5~0.8ぐらいなので、認識精度が下がっています。

なので、文字の中央はほぼ1にする処理を追加すればそれだけでもかなり精度は上がる気がします。

そもそも手書き文字入力は急遽1時間ほどで実装したものなので、そこまで精度は高くありません。現段階ではオプションのようなものです。

今後この作品をどのようにしていくか

今後この作品は、推論処理だけでなく、学習ができるように開発していこうと思っています。ここでいうニューラルネットワークの学習は、訓練データから最適な重みパラメーターの値を自動で獲得することです。

勾配法や遺伝的アルゴリズムを使って学習を進められるようにしていこうと思っています。
しかし、正直なところ、勾配法や微分、偏微分などがまだあまり理解できてないのが事実です。

「まだ高一だから…」「まだ習ってないから…」なんて理由を言ってしまったら終わりだと自分では思っているので、ゆっくりだと思いますが、しっかり勉強しながらニューラルネットワーク、いずれはディープラーニングをScratchで完全に再現、実装したいなと思います。

その時はぜひ、また興味を持っていただけると嬉しいです。

終わりに

まだわからないことがたくさんありますが、Scratchでニューラルネットワーク、ディープラーニングを再現、実装するという目標は変わることはありませんので、頑張っていこうと思います。

ここまで読んでいただき本当にありがとうございました!少しでも参考になれば嬉しいです。

SNSシェア、コメントなどぜひよろしくお願いします!

もしScratchに興味がわいた方はぜひScratchを始めてみてください。無料で簡単に登録できて作品が作れるのでおすすめです!

コメント

タイトルとURLをコピーしました