Raspberry Pi & Python 開発ブログ ☆彡

Raspberry PiとPythonの基本的な使い方をわかりやすく解説。初心者、入門者必見!!

Python TensorFlowの使い方

今回はTensorFlowの使い方を紹介したいと思います。TensorFlowの公式ページにトライアルとして記載されている、MNISTデータを使用した機械学習について解説したいと思います。今回はRaspberry Piではなく、WindowsにPythonとTensorFlowを入れて動作させます。

MNISTデータを使用した機械学習の概要

大まかに内容、流れを説明します。
① 0~9までの文字が手書きで書かれた画像データを大量に用意します(MNISTデータ)。
② TensorFlowで機械学習モデルを作成します。このモデルに①のデータを大量に与え、 学習をさせ、パラメータの最適値を探します。
③ この学習済みモデルに、何か数字が書かれたデータを与えると、自動的に0~9のどの文字が書かれているか判別します。例えば"3"と手書きで書かれた画像データをこの学習済みモデルに与えると、最適化されたパラメータとTensorFlowのアルゴリズムにより推測された、"3"という結果が出力されます(推測結果が正しい場合)。 100%正しい推測結果が出るわけではありませんが、訓練の度合いや仕様したアルゴリズムによって正解率の高くなっていきます。

それでは、WindowsにTensorFlowを入れて実際に動かしてみます。

WindowsにTensorFlowで使用するモジュールのインストール

pythonのインストール

下記のサイトからpythonのインストーラをダウンロードしてインストールを行います。
※Windows版のTensorflowはpython3.6用までしかリリースされていません。python3.7以上をインストールすると動作しない可能性があります。

http:// https://www.python.org/downloads/

pythonバージョン:3.6.8
Windows用インストーラ:Windows x86-64 executable installer

インストールウィザードの一番初めの画面で"Add Python to environment variables" にチェックを入れてインストールしてください。pythonの環境変数が設定されます。

set path when install python

また、pipのバージョンを最新版に更新しておきます。

> pip install --upgrade pip
> pip install setuptools --upgrade

tensorflowのインストール

下記コマンドでインストールを行います。NVIDIAのグラフィックカードを持っていないので、CPU版でインストールしています。CPU版だと、実行時にGPUで使うDLLがない等、エラーメッセージが表示されますが、結果は正しく出力されます。バージョンは1.15を指定してください

> pip install tensorflow==1.15

MNISTデータを使用した機械学習のコード解説

それでは実際のコードの説明をしていきます。機能単位で説明していきます。ページの最後に全コードを記載していますので、まずはそちらにざっと目を通して頂いてもいいかもしれません。

TensorFlowデータ型について

コードの解説の前に、Tensorflowのデータ型について説明します。今回、以下のデータ型を使用しています。
・プレースホルダ(tf.placeholder) :プレースホルダは中身は空で、領域だけを確保するイメージです。具体的な値は実行時に与えます。x = tf.placeholder(...)という形で、プレースホルダ:xを生成します。xに値を代入するときは、feed_dict={x:XXX}という構文を使用します(feed_dictは省略しても大丈夫そう)
・変数 : b = tf.Variable(...)という形で、変数;bを生成します。bに値を代入するときは、tf.assignメゾットを使用します。

プレースホルダと変数の違いが判りにくいですが、モデルの入力として一番初めに与えるデータ ⇒ プレースホルダ、その後の処理で使用する値 ⇒ 変数と理解しましょう。

モジュールのインポート

from tensorflow.examples.tutorials.mnist import input_data
import tensorflow.compat.v1 as tf

MNISTデータを読み込むモジュールとTensorFlowモジュールをインポートします。

MNISTデータの読み込み

mnist = input_data.read_data_sets("/tmp/data/", one_hot=True)

C:\tmp\dataフォルダにMNISTデータがダウンロードされます。MNISTデータには、"0~9までの文字が手書きで書かれた画像データ"と"それが0~9までのどの数字なのかが示されている正解値データ"が入っています。print文で確認すると以下のように表示されます。
・mnist.test.images ⇒ 縦28 x 横28 = 784の数値データ
・mnist.test.labels ⇒ 正解値が1になっている配列

print(mnist.test.images[0]) # 画像データ
[0.         0.         0.         0.         0.         0.
 0.         0.         0.         0.         0.         0.
 0.         0.         0.         0.         0.         0.
...
 0.47450984 0.9960785  0.8117648  0.07058824 0.         0.
 0.         0.         0.         0.         0.         0.
 0.         0.         0.         0.         0.         0.
 0.         0.         0.         0.         0.         0.
 0.         0.         0.         0.         0.         0.
 0.         0.         0.         0.         0.         0.
 0.         0.         0.         0.         0.         0.
 0.         0.         0.         0.        ]

print(mnist.test.labels[0]) # 正解値データ この場合は2が正解
[0. 0. 1. 0. 0. 0. 0. 0. 0. 0.]

セッションの作成

sess = tf.InteractiveSession()

Tensorflowでは主に"機械学習モデル作成"と"作成したモデルを実行"するフェーズのふたつに分かれます。モデルを実行する際にはセッションを生成する必要があります。
モデルはデータフローグラフという呼び方が正式のようです。データフローグラフは機械学習する際の処理のフローのようなイメージで、折れ線グラフのようなグラフではいので勘違いしないようにしましょう。

モデルの作成

x = tf.placeholder(tf.float32, [None, 784])
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
y = tf.nn.softmax(tf.matmul(x, W) + b)

基本的なモデルのフローは、データを入力する ⇒ 何か処理をする ⇒ 答えが出力される、です。

・データを入力する
⇒ 上記の "x" がデータになります。プレースホルダですので、まだ中身は空です。実行時に値を代入していきます。

・何か処理をする
⇒ まず、重みWとバイアスbという値を変数を作成します。重みWとバイアスbは学習により最適値を求めていきます。それらとソフトマックス関数を使用して、答えを導いていきます。

・答えが出力される
⇒ 答えが"y"になります。与えられた画像が0~9のどれなのか、確率を出力します。

学習モデルを作成(損失関数とオプティマイザーを定義)

y_ = tf.placeholder(tf.float32, [None, 10])
cross_entropy = -tf.reduce_sum(y_ * tf.log(y))
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

機械学習するためのモデルを作成します。y_は正解値データを格納するプレースポルダーで、この正解値に近づけることが目的です。いろいろ複雑で混乱しそうですが、何をしたいかというと、入力データ(0~9の数値画像)を読み込んだ時に、正しく判別してほしいわけです。学習していくうちに、実際の値と予測した値が同じになるようにしたい ⇒ 損失関数が最小になる ⇒ 正解率が上がるということです。ここでは損失関数が最小になるように、重みWとバイアスbの最適値を勾配降下アルゴリズムを使って求める処理(モデル)になります。

イニシャライズ

tf.global_variables_initializer().run()

実行前に初期化処理を行います。

学習

for i in range(1000):
    batch_xs, batch_ys = mnist.train.next_batch(100)
    train_step.run({x: batch_xs, y_: batch_ys})

ダウンロードしたMNISTデータの中にある学習用の訓練画像データ(batch_xs)とその正解値データ(batch_ys)を使用して学習をします。MNISTデータから100個ずつランダムで取り出し、それを1000回繰り返し、学習します。 train_step.run({データ})は上記の学習モデルにデータを与えて実行するということです。

学習済みモデルにテストデータを入れてテスト

result = sess.run(tf.argmax(y, 1), feed_dict={x: [mnist.test.images[0]]})
print("機械学習結果:{}".format(result))
print("正解値データ:{}".format(mnist.test.labels[0]))

〇sess.run関数の使い方
sess.run(実行したい関数のハンドル、feed_dict=入力データ)

sess.runメゾットに、実行したい関数と入力データを引数として与えます。feed_dictでxのプレースホルダにテスト用データを入れると、tf.argmax(y, 1)関数で処理した結果を表示してくれます。argmaxはy関数の結果、配列の中の数値が1(1=正解率100%)に1番近いものを取り出してくれるメゾット(1に1番近い配列の添え字を戻値りとして返す)です。

上記では、プレースホルダにmnist.test.images[0]のデータを与えています。配列[0]の正解値は7です。7と出力されれば、正しく学習できていると言えます。

学習済みモデルの正解率表示

correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
print(accuracy.eval({x: mnist.test.images, y_: mnist.test.labels}))

tf.argmax(y, 1)は今回作成したモデルでの結果、tf.argmax(y_, 1)は正解値データです。作成したモデルの結果と実際の正解値をを比較して、正解率を表示しています。tf.castでbool値(True/False)を1/0にキャストして、evalメゾットの引数に入力データを入れて、実行します。だいたい90%くらいの結果が表示されるはずです。

何となくですが、TensorFlowのイメージはつかめましたでしょうか?ソフトマックス関数や勾配降下アルゴリズム等はさっぱり私も理解していませんが、モジュールになっていますので、使うことができます。Pythonでは機械学習のコードは書きやすくなっていますので、実際にコードを書いてみて理解を深めていくといいと思います。

全コードの紹介

# モジュールのインポート
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow.compat.v1 as tf

# エラーメッセージの表示レベルを設定
old_v = tf.logging.get_verbosity()
tf.logging.set_verbosity(tf.logging.ERROR)
 
#MNISTデータの読み込み
mnist = input_data.read_data_sets("/tmp/data/", one_hot=True)

#セッションの作成
sess = tf.InteractiveSession()
 
# モデルの作成
x = tf.placeholder(tf.float32, [None, 784])
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
y = tf.nn.softmax(tf.matmul(x, W) + b)

# 学習モデルを作成(損失とオプティマイザーを定義)
y_ = tf.placeholder(tf.float32, [None, 10])
cross_entropy = -tf.reduce_sum(y_ * tf.log(y))
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

# イニシャライズ
tf.global_variables_initializer().run()
 
# 学習
for i in range(1000):
  batch_xs, batch_ys = mnist.train.next_batch(100)
  train_step.run({x: batch_xs, y_: batch_ys})

# 学習済みモデルにテストデータを入れてテスト
result = sess.run(tf.argmax(y, 1), feed_dict={x: [mnist.test.images[0]]})
print("機械学習結果:{}".format(result))
print("正解値データ:{}".format(mnist.test.labels[0]))

#学習済みモデルの正解率表示
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
print(accuracy.eval({x: mnist.test.images, y_: mnist.test.labels}))