話題の機械学習に挑戦したくて、機械学習フレームワークTensorFlow(テンソルフロー)に目を付けたものの、公式のチュートリアルで挫折しそうになっていませんか?
TensorFlowのインストールもハードルは高めですが、公式のチュートリアルもハードルが高いですよね。
そこで、今回はTensorFlow入門として、公式のチュートリアルで紹介されているプログラムを簡単に解説していきます。
本来であればTensorFlowの独特の考え方を理解しないといけなそうですが、今回はそこを棚上げし、TensorFlowでどのように実装していくのかを説明しています。
この記事を読み終われば、公式のチュートリアルをスラスラ読めるレベルにレベルアップしているでしょう。
では、がんばっていきましょう!
TensorFlowとは?
TensorFlowは、機械学習や深層学習のプログラムを実装する際に使用できるライブラリです。
同様のライブラリとして、Chainerやscikit-learnなども有名ですが、ここでは圧倒的に利用者が多いTensorFlowを紹介します。
TensorFlowとは何か?については、以下の記事で説明していますので、よく分からない方は確認してみてくださいね。
TensorFlowを始める前に
TensorFlowを始める前に、必要な知識とソフトウェアを確認しておきましょう。
と言っても、必要な知識がないと何もできないというわけではありませんので、TensorFlowを勉強しながら、必要な知識を身に付けていくと良いでしょう。
必要な知識は、
- 機械学習や深層学習の分野の知識
- Pythonの知識
- NumPyなどのライブラリの知識
です。
そうは言っても、それぞれの完璧な知識が必要なわけではなく、その辺りの知識が必要なのね、という程度の理解で構いません。
必要なソフトウェアは、
- Python
- TensorFlow
- その他のライブラリ
です。
その他のライブラリは、データを学習するための前処理であったり、学習結果をわかりやすく表現するための後処理でがんばるときに必要なものです。
この記事で紹介する範囲では、その他のライブラリは必要ありません。
本格的に機械学習に取り組むときには、PythonとTensorFlowだけで、すべてが完結するわけではないということを覚えておいてください。
TensorFlowのインストール
TensorFlowは、WindowsにもMac OSにもLinuxにもインストールできますので、お使いの環境にあわせてインストールしましょう。
なお、TensorFlow 1.5をWindows 10にインストールする手順は、以下の記事で説明していますので、ぜひ参考にしてください。
この記事では、上の記事に従ってGPU版TensorFlowをインストールした環境の操作を説明します。
MNIST For ML Beginnersをざっくり解説!
TensorFlowの公式サイトには、「MNIST For ML Beginners」という記事があります。
参考:https://www.tensorflow.org/versions/r1.1/get_started/mnist/beginners
実はちょっと古い情報になるのですが、TensorFlow 1.5でも動作しますし、すべてが無駄になるわけではありません。
また、理解しなければいけない範囲も狭いため、TensorFlow入門としてはピッタリです。
みなさんが読んでいるこの記事では、TensorFlowの雰囲気をつかむという目的で、「MNIST For ML Beginners」の内容を、もっと短い日本語で紹介してみようと思います!
手書き数字を認識させてみたい
「MNIST For ML Beginners」で解説しているプログラムの目的を、始めに紹介しておきましょう。
「MNIST For ML Beginners」では、機械学習もTensorFlowも初めて扱うという方向けに、手書き数字を認識するプログラムを解説しています。
手書き数字の認識は、機械学習で有名なタスクのひとつです。
ちなみに、手書き数字を認識する方法は1つではありません。
以下の記事でも、手書き数字の認識に挑戦していますので、手書き数字の認識って?と思う方はちょっと覗いてみてくださいね。
MNISTデータを読み込ませる
では、ここからプログラムの説明をしていきますね…と言いたいところですが、まずは機械学習に不可欠なデータの話からです。
手書き数字を認識するプログラムを作成する上で、必要なのは、画像データとその画像が表す数字データをペアにしたものです。
たとえば、以下のような4つのペアを用意することをイメージしてください。
画像データ | その画像が表す数字データ |
---|---|
(ニ.png) | 2 |
(サン.png) | 3 |
(ヨン.png) | 4 |
(ハチ.png) | 8 |
しかし、この4つのペアだけを見ても、プログラムは「5」とか「7」は学習できません。
また、「2」にしても、人によって「2」の形は違います。
もっと曲がった「2」もあれば、小さな「2」もあるでしょう。
それらをすべて読めるようにするには、4つのペアだけではとても足りず、もっと多くのペアが必要なのです。
そこで、TensorFlowだけでなく機械学習界隈では、Yann LeCun氏らが公開している、画像データとその画像が表す数字データのペア(MNISTデータ)を使用させてもらうことが多くなっています。
参考:http://yann.lecun.com/exdb/mnist/
今回解説していく「MNIST For Beginners」でも、紹介したMNISTデータを使っています。
といっても、あらかじめダウンロードしておく必要はありません。
プログラムの中でMNISTデータをダウンロードして、機械学習に都合の良いデータ形式に変換するという便利仕様になっています。
from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
2行目のコードで、MNISTデータをダウンロードして、機械学習をしやすいようにMNISTデータを変換したうえでmnistに格納します。
学習に使うペアデータは、mnistの中に3つの変数に分割して格納されています。
具体的には、mnist.trainに55000ペア、mnist.validationに5000ペア、mnist.testに10000ペアのデータが格納されます。
そして、mnist.train、mnist.validation、mnist.testには、それぞれ以下のようなデータが格納されています。
変数 | 説明 |
---|---|
num_examples | ペアデータの数 |
images | 画像データ(_num_examples個) 28×28ピクセルの画像データが、1×784の配列に格納されています。 |
labels | 画像が表す数字データ(_num_examples個) 「3」や「4」が登録されているのではなく、1×10の配列です。 以下のように、1つだけ「1」が、残りは「0」が格納されています。 [0. 0. 0. 0. 0. 0. 0. 1. 0. 0.] |
機械学習のプログラムでは、imagesとlabelsの対応を学習し、新しいimagesに対して新しいlabelsを推測するという動作を期待しています。
ニューラルネットワーク(モデル)を構築する
次に、ニューラルネットワーク(以降、モデルと表記します)を構築します。
TensorFlowでは、あらかじめ「画像データを受け入れたときにどのように計算するか」を定義します。
定義したときには計算は行われず、あとでまとめて計算するのが、TensorFlowの特徴ですが、初めのうちはあまり気にしなくても良いでしょう。
入門で大事なことは雰囲気です。
x = tf.placeholder(tf.float32, [None, 784]) W = tf.Variable(tf.zeros([784, 10])) b = tf.Variable(tf.zeros([10])) y = tf.matmul(x, W) + b
tf.placeholder()で、imagesを1つ受け取る場所(TensorFlowではプレースホルダーと呼ばれています)を生成します。
あとで出てくるsess.run()を実行するタイミングで、画像データがこのプレースホルダーに投入されるようなイメージでいてください。
その後の3行は(機械学習で言うところの)パラメーターを準備したり、あれこれ計算するところです。
少し書くと、画像データをxに格納し、パラメーターWとの内積を求めて、パラメーターbを加算した結果をyに格納している、となりますが、ザックリあれこれ計算するんだな、という理解で、読み飛ばしても良いでしょう。
この4行の計算を経ると、画像データから、以下のような謎の数値が格納された1×10の配列が計算されます。計算結果は、yに入ります。
[ 0.18440935 -8.5651245 1.7532194 … 10.496584 -0.19720328 2.1629303 ]
ここでは計算された「1×10の配列」が、先に説明してあったlabels[0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]に対応しているということを覚えておいてください。
誤差関数を準備する
次に、誤差関数(目的関数、コスト関数、損失関数、最適スコア関数とも呼ばれます)を準備します。
y_ = tf.placeholder(tf.float32, [None, 10]) cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y))
誤差関数は、画像データから計算した1×10の配列と、labels(画像が表す数字データ)に格納されている1×10の配列の誤差を判定するための関数です。
機械学習では、さまざまな誤差関数が提案されていますが、「MNIST For ML Beginners」では、tf.nn.softmax_cross_entropy_with_logits()、つまりクロスエントロピー関数(交差エントロピー関数とも)を利用しています。
tf.nn.softmax_cross_entropy_with_logits()に引数で渡しているyは画像データから計算した1×10の配列で、y_(アンダーバー付き)はlabels(画像が表す数字データ)に格納されている1×10の配列です。
この2つ配列の誤差をクロスエントロピー関数を使って判定し、その誤差の平均値をtf.reduce_mean()で求めているというイメージです。
勾配降下法を決定する
次は、勾配降下法(誤差を小さくするために使用するアルゴリズム)を決定します。
勾配降下法は、誤差関数で求めた誤差をどのように利用して、パラメーターを変更させるかを決定するアルゴリズムです。
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
「MNIST For ML Beginners」では、tf.train.GradientDescentOptimizer()、つまり最急降下法(バッチ勾配降下法とも)を使用しています。
以上で、機械学習のモデルが構築できました。
機械学習(訓練)を開始する
いよいよ機械学習を開始しましょう。
mnist.trainに格納されている55000点の画像データと、画像が表す数字データのペアを使って、先に構築したモデルの機械学習(訓練)を行います。
sess = tf.InteractiveSession() tf.global_variables_initializer().run() # Train for _ in range(1000): batch_xs, batch_ys = mnist.train.next_batch(100) sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})
ただし、55000点のデータをすべて利用するのではなく、mnist.trainから100個のペアデータをランダムに取得して機械学習(訓練)を行います。
100個のペアデータを使って、機械学習(訓練)を行い、まとめて1回だけパラメーターWとbを更新します。
これを1回と数えて、全部で1000回の機械学習(訓練)を行っています。
対象となるペアデータの数が100×1000=100000となり、55000点を優に超えていることに疑問を持った方は、なかなか鋭いです。
結果的に同じペアデータを何度も使っていることになりますが、毎回違う100個のペアデータを使うことで、学習精度が高くなることを期待して、このような方法をとっているのです。
ここでは簡単に「機械学習(訓練)を行う」と書きましたが、実際には画像データからあれこれ計算し、誤差逆伝播法を駆使してパラメーターWとbを更新する、というようなことを山ほど計算しています。
この山ほどの計算を、すべてTensorFlowが隠ぺいしているため、気軽に機械学習に取り組めるというわけですね。
訓練結果を評価する
機械学習の精度は、モデルの構築方法によるため、訓練結果が思わしくなかったらモデルを変更する必要があります。
そこで、機械学習(訓練)が終わったら、その結果を評価しましょう。
こちらもTensorFlowらしく、計算方法(評価方法)を構築してから、あとでまとめて計算します。
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1)) accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
ちょっと長くなってきましたので、yとy_について改めて説明しておきましょう。
yは、先に構築したモデルを使って、mnist.test.imagesの画像データから計算された1×10の配列で、以下のようにすべての要素が0~1の値を格納しています。
[ 0.18440935 -8.5651245 1.7532194 … 10.496584 -0.19720328 2.1629303 ]
y_は、mnist.test.labels、つまりmnist.test.imagesの画像が表す数字データで、1つだけ「1」が、残りは「0」が格納されています。
[0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]
tf.argmax()では、配列の中で最も大きな値をもつ要素の場所を取り出しています。
したがって、tf.equal()では、配列の中で最も大きい値をもつ要素が同じ場所にあるかを調べていることになりますね。
上の例では、どちらも後ろから3番目が最も大きくなっていますので、機械学習で正解を出せた!と考えます。
つまり、tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))では、先に構築したモデルでmnist.test.imagesを計算した結果(=機械学習で推測した数字)と、mnist.test.labels(=あらかじめ分かっている正解)が同じであることを確認しているのです。
2行目のtf.reduce_mean(tf.cast(correct_prediction, tf.float32))では、正解の平均(=全部正解していれば1、全部誤っていれば0で、正解率と見なせる)を計算します。
最後に表示する値は、accuracy(正解率)です。
print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))
以上で、「MNIST For ML Beginners」のプログラムの動作をざっくり解説できました。
TensorFlowで学ぶディープラーニング入門
もう少しTensorFlowを触りながら理解を進めたいという方のために、書籍も紹介しておきましょう。
どんな内容?
この本は、機械学習やTensorFlowについて興味がある一般の方向けに書かれた解説本です。
TensorFlowを利用して、何ができるのかを実際に動かしながら、機械学習(畳み込みニューラルネットワーク)の仕組みを根本から理解できます。
専門書ほど内容が深掘りされている訳ではなく、啓蒙書ではあまり触れられる事のない実際のアリゴリズムに触れることができます。
まさに、これから学習しようとする人にオススメです。
まとめ
この記事では、あえて誤差関数やクロスエントロピー関数、誤差、最急降下法など、機械学習でよく目にする単語をいくつか出しました。
この記事が、機械学習のアルゴリズムと、TensorFlowを使った場合の実装方法を、結びつける助けになることを願っています。
少し余談になってしまいますが、機械学習の用語はまだまだ一般化されておらず、同じものを指していても、著者によって誤差関数と呼んだり、目的関数と呼んだり、はたまた損失関数と呼んだりしています。
非常に残念なことに、これが学習コストを上げている状態です。
一方、今回紹介したTensorFlowのコードであれば、コードは日本語よりは揺れが少ないので、機械学習の学習コストがいくらか低くなるのではないでしょうか。
理屈っぽい本で機械学習に挫折しそうなあなたに、この記事が届きますように!
そして、TensorFlowのコードから、改めて機械学習の理屈に戻って、どんどん理解を進めていただければと思います!がんばってください!
なお、今まさに機械学習の学習をしている方は以下の記事もどうぞ。
はじめてPythonを使う方でもわかりやすいように、Pythonでできることやその学習法などを中心にまとめています。機械学習には欠かせない言語であるPythonの基礎知識がわかります。
復習にも使えると思いますので、ぜひ一度ご覧になってみてくださいね。
【Python 入門完全攻略ガイド】