見出し画像

ボブと学ぶTensorFlow 2.0

Hey bro. What's up?

よお、兄弟。元気か?俺は相変わらずだぜ。

この前ブラザーからJetsonを教えてもらって、Nvideaが用意したご機嫌なサンプルプログラムを実行したな。でもな、俺にはAIって野郎が何やっていたかさっぱりだ。きっと俺には思いつかねえことしてんだろうよ。

それでブラザーにまた聞いたんだ。俺は流行りのAIの野郎をF〇ckしてえんだよ。この前のやつはUNIXコマンド叩いただけで、何にも分からなかったぜ。俺のようなおつむの小せえバカにでも分かるように教えてくれよ。

そんなピーマンみたいな俺にブラザーは Google ColaboratoryでTensorFlow 2.0を使ってみろと言ってきた。なんでもGoogleがタダで出している超イカす道具なんだとよ。相変わらず、ブラザーは脳みそいっぱい詰まってんな。

というわけでTensorFlow 2.0がどんなハッピーな道具なのか頭に叩き込もうと思う。

TensorFlow 2.0ってのはAIを色々使いやすくしてくれる野郎だ。フレームワークって言うんだとよ。こいつがいなければ俺はHello Worldから初めて、自分でAIの計算式をコードで実装しなければならねえ。そんなのクソめんどくせえ。勉強のためにはやるが、車輪をもう一度発明するのは好きじゃねえ。そんでせっかちな俺とかにGoogleが与えたもうた福音がTensorFlowで、旧約聖書がTensorFlow 1.X 、新約聖書がTensorFlow 2.0だ。

まずはチュートリアルからだ。野郎のホームページにアクセスして童貞向けのクイックスタートを選ぶ。

Run in Google Colabってのがあって、Google ColabがGoogleがタダで出しているブラウザから Python を記述、実行できるサービスなんだとよ。こいつはGPUとかも使えて、Google Colabで仮に試したコードをJetsonで本格的に動かすみてえなことができるんだ。なんでこれがタダで使えてんのかよく分んねえな。いつもYoutubeに出てくる脱毛の広告とか怪しいやせ薬みてえな広告とかねえし、使用時間に時間制限はあるが、時限爆弾みたいにコード吹っ飛ばすことはしねえしな。

まあいいや、とにかくF〇ckしよう。まずはパッケージのインポートだ。ところで、こいつモジュールじゃなくて、パッケージって言うんだな。このパッケージはCtrl+Enterで実行できる。tensorflowといちいち入れんのは面倒だからtfって省略するぜ。

import tensorflow as tf

次にMNISTデータセットをロードする。MNISTはちょっとした有名なデータだ。中身を見ると0から9の数字の画像の集まりで大体みんな機械学習のために使うんだが、データはアメリカの国勢調査局の従業員から取得したらしい。どう見ても3にしか見えない2とか、6のような0とか、くそ汚い字も多く含まれている。きっと国勢調査局の奴らは俺たち家の玄関まで行って、国勢調査をお願いしますとか言うだけで、普段字を書かないのだろう。そうに違いない。

mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()

少し余談が過ぎたな、この文字列がどんなハッピーなことしているかと言うと、tf(tensorflow)のkerasというフレームワークがいて、kerasが持っているdatasetsモジュールの中のmnistというモジュールを読み込むんだ。kerasはフレームワークだ。元々、kerasは別個のフレームワークだったんだがTensorflow2.0が完全に飲み込んじまった。旧約聖書がTensorFlow 1.X 、新約聖書がTensorFlow 2.0ならkerasは黙示録ってとこか。

そんでもって、mnistモジュールのロードデータ関数でネットから国勢調査局の奴らの汚い字を読み込む。ちなみにtrainと名前のついたやつは国勢調査局の字の画像で学習データセットとして使って、testと名前のついたやつは高校生の字の画像らしくて、こいつを評価のために使う。

画像は白黒の画像なんだが完全に白黒の二色でなく、白と黒の間に255段階の中間の灰色のドット(画素)がある。それでドットが0から255の値を持っているが、255で割って、0~1の値になるように正規化する。0から1の値にしとくと何かと都合がいいんだぜ。

x_train, x_test = x_train / 255.0, x_test / 255.0

次はモデルを構築する。モデルが何なのかって?モデルってのは数式の集まりだが、脳みそいっぱい詰まっているやつでも数式見ただけではよく分からないから数式を図にしたりして簡単にしたやつだ。

model = tf.keras.models.Sequential([
 tf.keras.layers.Flatten(input_shape=(28, 28)),
 tf.keras.layers.Dense(128, activation='relu'),
 tf.keras.layers.Dropout(0.2),
 tf.keras.layers.Dense(10)
])

このモデルについて、もっと詳細について見ていこうと思う。なあに、どうせこいつも数式だ。いかつい美人でも丁寧に口説けば服を脱いでくれるように、こいつも丁寧に分解すれば足し算引き算の簡単な要素になるさ。

まずSequentialってなんだ?それはな、層を積み重ねたものだ。層は数式のセットだが、色んな層がある。まずはflattenってやつだ。こいつは28x28の二元の入力を784の一次元のデータにするから、平べったくするということだ。まあ要するにいくつかの入力をぶち込んだらひとまとめにして、ひとまとめにしたのをReLUにさらにぶち込んで結果が出てくるって感じか。ふいりーんぐってやつだけど、人生も色々ぶち込んで凝縮すると何が大事なのか分かってくるな。

あとはdropoutか、こいつは文字通りドロップアウトしてんだ。定期的に結果を落とす(無視する)。そうすると過学習ってのが防げるんだ。その辺にいるだろ、頭の固いやつ、歳だけは重ねて頭凝り固まっている頑固ジジイみたいなやつ。そういうやつはぶん殴って記憶喪失になってもらった方がいい人になるみたいな話聞くだろ、それと大体一緒だ。忘れた方がいいこともあるんだぜ。そんで最後の層は10の結果に凝縮する。判断してほしい結果が0から9の数字だから10個だ。

じゃあこいつで国勢調査局の従業員のくそ汚い字を判定してみようぜ。使うデータはデータセットの最初の文字の画像だ。まず最初のコードでロジットと呼ばれるスコア出す。ロジットと言うから統計学のロジット関数を思い浮かぶかもしれねえが全然違う(そのあたり勘違い野郎が多そうだ)。こいつは要するにDense(10)から出てきた生の予想値なだけだ。そんでこいつをソフトマックス関数で確率にする(まあいい加減な確率なんだがな、気にすんな)。ソフトマックス関数が何なのかは下の脳みそいっぱい詰まったやつが書いた記事を見てくれ。要するに最悪と最高を切り捨てるマザーファッカーみたいなやつだ。

predictions = model(x_train[:1]).numpy()
tf.nn.softmax(predictions).numpy()

そんでこいつを実行すると以下のような確率が出てくる。

array([[0.11866686, 0.15054315, 0.09077021, 0.05999506, 0.1362176 ,
       0.05860646, 0.10100915, 0.1352904 , 0.06510126, 0.08379982]],
     dtype=float32)

ちなみにprint(y_train[:1])で確認すると5と出てきたからまあでたらめだ。こいつにはとことん教え込まねえといけねえ。それで損失関数と最適化関数というのを使いつつ学習させんだ。損失関数はどれだけ本当の値と違うのか教え込むための関数だ。2乗和誤差と交差エントロピー誤差のどちらかが使われることが多い(俺調べ)。今回のやつは交差エントロピー誤差を使っている。詳しい数式が分かるクレバーな野郎は下記の脳みそいっぱい詰まったやつが書いた記事でも読んでくれ。どっちも間違いを足し合わせて評価されるんだが、減点方式みたいな評価の仕方で個人的には嫌いだな。

ちなみに学習対象はReLUが出てきたtf.keras.layers.Dense(128, activation='relu')とtf.keras.layers.Dense(10)の野郎だ。迷ったらmodel.summary()で確認できる。

loss_fn = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)

あとはモデルの最適化関数を設定してコンパイル(機械の野郎が分かりやすい言葉に翻訳すること)だな。最適化関数はさっき出てきた損失関数の結果を0にするためにいるやつだ。具体的には損失関数の結果をパラメータの調整のために足したり引いたりする。今回はAdam:Adaptive moment estimationを使用する。Adamがどんなハッピーな野郎かは下記の脳みそいっぱい詰まったやつが書いた記事でも読んでくれ。最初に聞いたときはアダムというインテリ系の黒人が発明したからAdamなんだと思ったぜ。評価対象(メトリクス)は確率なのでaccuracyを設定だ。

model.compile(optimizer='adam',
             loss=loss_fn,
             metrics=['accuracy'])

あとはモデルの学習だ。5回繰り返し同じデータセットを学習してほしいからepochs=5に設定する。それにしても誤差逆伝播法とか難しいこと考えずに勝手にやってくれるのは楽だな。数式知らなくてもお手軽だ。

model.fit(x_train, y_train, epochs=5)

さて、最後に学習してしたやつを試してみる。高校生の字でテストしてみる。verboseで表示手法が変えられるけど、それは表示だけだからまあなんでもいいさ、構いやしねえだろ。

model.evaluate(x_test,  y_test, verbose=2)

これで98%ぐらいの正答率になるだろう。(俺の結果は97.7%だった)

さて、他でも試してみるか、関数の形にF〇ckして、確率を吐き出すようにする。

probability_model = tf.keras.Sequential([
 model,
 tf.keras.layers.Softmax()
])

さて、さっきはでたらめ返してきたやつはどうなっているか見てみるか。

probability_model(x_train[:1])

下記が結果だが、5のとこが9.9925059e-01で一番高くなっている。99.9%とは中々だな。


probability_model(x_train[:1])
# print(y_train[:1])
<tf.Tensor: shape=(1, 10), dtype=float32, numpy=
array([[1.7775844e-13, 4.3426176e-11, 1.4174215e-10, 7.4937718e-04,
       4.6354116e-20, 9.9925059e-01, 3.1038109e-16, 1.5909277e-11,
       3.1770114e-11, 4.3963180e-09]], dtype=float32)>

もちろん、こいつも使って学習したわけだから、きっちり学習していないテストデータでも試しておこう。

print(probability_model(x_test[:1]))
print(y_test[:1])
tf.Tensor(
[[5.9271269e-08 7.6131483e-09 4.8906175e-05 1.9060256e-04 1.6581370e-14
 1.3024704e-06 1.1541011e-13 9.9975854e-01 3.4613798e-08 5.9317273e-07]], shape=(1, 10), dtype=float32)
[7]

問題なさそうだ。

とりあえずチュートリアルはできるようになったな。さて次は...ブラザーに聞いて、指示をもらって、勉強をするかな。

じゃあな。

この記事が気に入ったらサポートをしてみませんか?