Welcome to Mashykom WebSite



TensorFlow 2.0 を用いた機械学習のページ

 TensorFlow が大幅に改訂されて、version 1.x からversion 2.0に変更されました。Keras がTensorFLowのモジュールに統合されました。そして、それに対応しての関係でしょうが、TensorFlow 1.xで使用されていたいくつかの重要なモジュールが廃止されました。とりわけ、TensorFlow 2.0で、tf.contribが廃止された影響は大きいです。この結果、TensorFlow 1.xで作成された機械学習プログラムの多くが TensorFlow 2.0 ではエラーが出て、正常に作動しません。また、Keras がTensorFLowのモジュールに統合されましたので、従来のKeras単体でのコードが正常に動作しません。

 このページでは、TensorFlow 2.0のもとで正常に作動するDeep Learning(CNN)のPython実装の例を説明します。特に、画像識別や一般物体検出アルゴリズムをPythonでコード化したライブラリの代表的な事例を取り上げて、機械学習プログラムの実装と実行について説明します。

 python関連のパッケージなどの環境はセットアップされているとします。Jupyter Notebookなどが必須なので、anaconda3をインストールすることを推奨します。anaconda3に付属するpythonの最新バージョンは 3.7です(Python3自体の最新バージョンは3.8.0です)。Mac OSでもUbuntuのどちらでも正常に動作することは確認しています。TensorFlow 2.0がインストールされていれば、Windowsでも正常に作動すると思います。TensorFlow の公式ページにおけるPython開発環境の設定では、'virtualenv' を用いた 'Python virtual environments' を構築することが推奨されています。

 ここでは、GPUを搭載していないPCを前提にしているので、リアルタイムでの物体検出では、処理速度が遅く、画像の切り替わりがスムーズでないことはやむを得ません。また、動作確認は以下に明記されたTensorflowやKerasなどのバージョンで行っています。このページが書かれた時(2019年11月15日)のソフトウエ環境は

pythonのバージョンは3.7.4です
numpyのバージョンは1.17.2です
scipyのバージョンは1.3.1です
matplotlibのバージョンは3.1.1です
PIL(Pillow)のバージョンは6.2.0です
kerasのバージョンは2.2.4です
tensorflowのバージョンは2.0.0です。

Last updated: 2019.11.15


Tensorflow 2.0のインストール

 anaconda3をインストールすると、python3.7のモジュール環境(Python 3.7本体, NumPy, SciPy, Matplotlib, Scikit-Learnなど )は自動的にセットアップされます。このとき、python3.7のパッケージ環境(Python 3.7本体以外の, NumPy, SciPy, Matplotlib, Scikit-Learnなど )は ~/opt/anaconda3/lib/python3.7/site-packages/にインストールされます。

'virtualenv' を用いた 'Python virtual environments' を構築するときは、


$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
$ export PATH="/usr/local/bin:/usr/local/sbin:$PATH"
$ brew update
$ brew install python  # Python 3
$ sudo pip3 install -U virtualenv  # system-wide install

で、'Virtualenv'をインストールします。その後、Pythonをインストールします。


$ virtualenv --system-site-packages -p python3 ./venv
$ source ./venv/bin/activate  # sh, bash, ksh, or zsh

(venv) $ pip install --upgrade pip

(venv) $ pip list  # show packages installed within the virtual environment

(venv) $ deactivate  # don't exit until you're done using TensorFlow

$  #このシェルプロンプト状態ではインストールしたPythonは使用できません。

 シェルプロンプトの前に(venv)がついているときには、Pythonが作動します。deactivateした後は、Pythonがパスから消えますので、Tensorflowなどは使用できません。

 ここからは、anaconda3がインストールされている前提で説明を進めます。anaconda3がインストールされるときには、Pythonパスの設定は自動的に済んでいます。anaconda3 がインストールされているとき、シェルのプロンプトは


(base) $ 

となります。シェルプロンプトの prefix (base) はpython 3.7 に対応します。Python 3.7 を使用しないときは、$ conda deactivate と入力すれば、プロンプトは


$ #このシェルプロンプト状態ではインストールしたanaconda pythonは使用できません。

となります。通常のhomeディレクトリに戻ります。tensorflowを利用するときは必ず、$ conda activate を入力して、Pythonが使用可能な状態にします。

 以下のようなコマンドを入力してtensorflow 2.0 をインストールします。


(base) $ pip install tensorflow   # virtualenvでは、(venv)$ pip install --upgrade tensorflow 

 この入力で、TensorFlowのパッケージは ~/opt/anaconda3/lib/python3.7/site-packages/tensorflow/にインストールされます。

 kerasはtensorflowに統合されているので、kerasを単体でインストールする必要はないのですが、念のために、keras もインストールしておきましょう。


(base) $ conda install keras

 kerasでモデルの保存を行うためにはHDF5が必要となるので、そのためのパッケージもインストールします。


(base) $ conda install h5py

 さらに、構成したモデルを可視化して、そのグラフを描画するためには、graphvizとpydotを利用する必要があります。それらのパッケージは


(base) $ conda install graphviz
(base) $ conda install pydot

とインストールします。


keras.Sequentialモデルを用いた手書き数値の識別


 Tensorflowの公式サイトにあるtutorialsに沿って説明します。TensorFlowのモデルを構築し訓練するためのハイレベルのAPIである tf.kerasを使用します。tf.keras.Sequential モデルを用いた最も単純な例は以下のように書けます。第1行目の、
from __future__ import absolute_import, division, print_function, unicode_literals
はこうするのが慣例だと思って下さい。

from __future__ import absolute_import, division, print_function, unicode_literals
from tensorflow.keras import datasets, layers, models

mnist = datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

model = models.Sequential()
model.add(layers.Flatten(input_shape=(28, 28)))
model.add(layers.Dense(128, activation='relu'))
model.add(layers.Dropout(0.2))
model.add(layers.Dense(10, activation='softmax'))


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

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

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

 ネットワークは4層のlayersから構成されます。model = Sequential()で、Sequentialモデルを用いた具体的なモデル名をmodelとします。簡単にネットワークのレイヤーを積み重ねて、モデルを構築します。Flatten(input_shape=(28, 28))は入力サイズが28✖️28の2次元データを1次元にフラットにします。Dense(128, activation='relu')は、128個のニューロンが隣接する層と全結合されたレイヤで、活性化関数がRelu関数であることを意味します。Dense(units=10, activation='softmax')は、追加される第4層が10個のニューロンからなる全結合層で、活性化関数がsoftmax関数であることを示します。Dropoutはディープラーニングの過学習を防ぐために行います。Dropoutは、隣接層のニューロンとのつながりをランダムに切断してあげることで、過学習を防ぎます。0.2という数字は、その切断するニューロンの割合を示しています。訓練時には、データが読み込まれるごとにニューロンはランダムに切断されます。

 compile()で、以上で指定された4層のレイヤをもつニューラルネットワークに損失関数と学習方法を指定して、モデルを完成させ、このモデルを用いた訓練(学習)プロセスを設定します。損失関数は交差エントロピー、最適化手法はadamを指定しています。loss='mean_squared_error'と指定すると二乗和誤差関数を使用されます。この例で指定されている'categorical_crossentropy'を使用するためには、データ(x_train,y_train)を'to_categorical'でone-hot形式にする前処理が必要です。損失関数の最小点を検索するための最適化手法にはいくつかの種類があります。SGD(stochastic Gradient Descent)は最も単純なアルゴリズムで、RMSprop、Adagrad, Adadelta、Adamなどのアルゴリズムが利用可能です。これらの詳細については、ディープラーニングの参考書などを参照ください。

 この後、fit()メソッドを用いて、epochs数とbatch_sizeの大きさを与えて、モデルのパラメータ値の訓練(学習)をします。訓練データは教師ラベル付きの(x_train,y_train)です。y_trainが教師ラベルです。mnistデータはmnist.load_data() で読み込んでいます。

 上記のコードを実行すると、以下のように、エポックごとに学習の計算結果が表示されます。


Train on 60000 samples
Epoch 1/5
60000/60000 [==============================] - 4s 73us/sample - loss: 0.2952 - accuracy: 0.9145
Epoch 2/5
60000/60000 [==============================] - 5s 82us/sample - loss: 0.1409 - accuracy: 0.9575
Epoch 3/5
60000/60000 [==============================] - 4s 66us/sample - loss: 0.1086 - accuracy: 0.9672
Epoch 4/5
60000/60000 [==============================] - 4s 72us/sample - loss: 0.0861 - accuracy: 0.9730
Epoch 5/5
60000/60000 [==============================] - 4s 72us/sample - loss: 0.0743 - accuracy: 0.9766
10000/1 - 0s - loss: 0.0415 - accuracy: 0.9761

[0.07995059116524644, 0.9761]

 次に、MNIST データを用いて、手書き数値の分類をするための、上記のネットワークよりは少し高度な畳み込みニューラルネットワーク (CNN: Convolutional Neural Network) を用いた学習について説明します。このネットワークは MNIST テストセットにおいて、99%以上の精度を達成します。tf.Keras.Sequential APIを使用するため、ほんの数行のコードでモデルの作成と学習を行うことができます。以下にコードを紹介します。モデルは8層のネットワーク層から構成されています。


from __future__ import absolute_import, division, print_function, unicode_literals
from tensorflow.keras import datasets, layers, models

(train_images, train_labels), (test_images, test_labels) = datasets.mnist.load_data()

train_images = train_images.reshape((60000, 28, 28, 1))
test_images = test_images.reshape((10000, 28, 28, 1))

# ピクセルの値を 0~1 の間に正規化
train_images, test_images = train_images / 255.0, test_images / 255.0

model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))

 ネットワーク層のモデルを完成するために、Conv2D(64, (3, 3), activation='relu'))層の後に、ネットワーク層が3層追加されています。(shape (3, 3, 64) の) 畳み込みの基礎部分からの最後の出力テンソルを、1つ以上の Dense レイヤーに入れて分類を実行します。現在の出力は 3D テンソルですが、Dense レイヤーは入力としてベクトル (1D) を取ります。まず、3D 出力を 1D に平滑化 (または展開) してから、最上部に1つ以上の Dense レイヤーを追加します。MNIST は 10 個の出力クラスを持ちます。そのため、我々は最後の Dense レイヤーの出力を 10 にし、softmax関数を使用します。


model.summary()

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 26, 26, 32)        320       
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 13, 13, 32)        0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 11, 11, 64)        18496     
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 5, 5, 64)          0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 3, 3, 64)          36928     
_________________________________________________________________
flatten (Flatten)            (None, 576)               0         
_________________________________________________________________
dense (Dense)                (None, 64)                36928     
_________________________________________________________________
dense_1 (Dense)              (None, 10)                650       
=================================================================
Total params: 93,322
Trainable params: 93,322
Non-trainable params: 0
_________________________________________________________________

 モデルの構造がよく理解できます。以下の通りに、モデルをコンパイルして、学習する。


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

model.fit(train_images, train_labels, epochs=5)

 結果は次の通りです。

Train on 60000 samples
Epoch 1/5
60000/60000 [==============================] - 39s 643us/sample - loss: 0.1437 - accuracy: 0.9553
Epoch 2/5
60000/60000 [==============================] - 43s 718us/sample - loss: 0.0470 - accuracy: 0.9851
Epoch 3/5
60000/60000 [==============================] - 48s 800us/sample - loss: 0.0334 - accuracy: 0.9897
Epoch 4/5
60000/60000 [==============================] - 47s 776us/sample - loss: 0.0257 - accuracy: 0.9920
Epoch 5/5
60000/60000 [==============================] - 44s 734us/sample - loss: 0.0209 - accuracy: 0.9932


 シンプルなモデルですが、相当に正確な識別ができます。



keras.Sequentialモデルを用いた画像の識別


 ここでは、tf.keras.Sequential modelを用いてイメージ画像から動物を識別する方法について説明します。 Convolutional Neural Network (CNN) を使用して、CIFAR images の分類問題を取り上げます。 CIFAR10 dataset は 10クラスに分類、各クラス当たり60,000 color images 画像があります。データセットは、 訓練用として 50,000 training images 、検証用とし 10,000 testing imagesが用意されています。Kerasにはこのデータセットを読み込むコードが付録しています


from __future__ import absolute_import, division, print_function, unicode_literals

import tensorflow as tf

from tensorflow.keras import datasets, layers, models
import matplotlib.pyplot as plt

(train_images, train_labels), (test_images, test_labels) = datasets.cifar10.load_data()

# Normalize pixel values to be between 0 and 1
train_images, test_images = train_images / 255.0, test_images / 255.0

 と入力すると、cifar10のデータセットが読み込まれます。内容を見てみるために、以下のように入力します。


class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer',
               'dog', 'frog', 'horse', 'ship', 'truck']

plt.figure(figsize=(10,10))
for i in range(25):
    plt.subplot(5,5,i+1)
    plt.xticks([])
    plt.yticks([])
    plt.grid(False)
    plt.imshow(train_images[i], cmap=plt.cm.binary)
    # The CIFAR labels happen to be arrays, 
    # which is why you need the extra index
    plt.xlabel(class_names[train_labels[i][0]])
plt.show()

 25枚の画像が表示されます。画像はかなり不鮮明です。CNNモデルを作成し、学習するために、以下のコード作成します。cifarの画像のshapeは(32, 32, 3)です。


model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))

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

history = model.fit(train_images, train_labels, epochs=10, 
                    validation_data=(test_images, test_labels))

Train on 50000 samples, validate on 10000 samples
Epoch 1/10
50000/50000 [==============================] - 11s 222us/sample - loss: 1.5684 - accuracy: 0.4266 - val_loss: 1.2367 - val_accuracy: 0.5543
Epoch 2/10
50000/50000 [==============================] - 7s 130us/sample - loss: 1.1648 - accuracy: 0.5879 - val_loss: 1.1616 - val_accuracy: 0.5853
Epoch 3/10
50000/50000 [==============================] - 6s 130us/sample - loss: 1.0314 - accuracy: 0.6379 - val_loss: 1.0190 - val_accuracy: 0.6374
Epoch 4/10
50000/50000 [==============================] - 6s 129us/sample - loss: 0.9382 - accuracy: 0.6711 - val_loss: 0.9656 - val_accuracy: 0.6617
Epoch 5/10
50000/50000 [==============================] - 6s 129us/sample - loss: 0.8650 - accuracy: 0.6970 - val_loss: 0.9005 - val_accuracy: 0.6870
Epoch 6/10
50000/50000 [==============================] - 6s 129us/sample - loss: 0.8054 - accuracy: 0.7183 - val_loss: 0.9217 - val_accuracy: 0.6748
Epoch 7/10
50000/50000 [==============================] - 7s 131us/sample - loss: 0.7557 - accuracy: 0.7356 - val_loss: 0.9336 - val_accuracy: 0.6858
Epoch 8/10
50000/50000 [==============================] - 7s 132us/sample - loss: 0.7145 - accuracy: 0.7514 - val_loss: 0.9107 - val_accuracy: 0.6906
Epoch 9/10
50000/50000 [==============================] - 7s 134us/sample - loss: 0.6758 - accuracy: 0.7647 - val_loss: 0.8696 - val_accuracy: 0.7077
Epoch 10/10
50000/50000 [==============================] - 6s 130us/sample - loss: 0.6410 - accuracy: 0.7757 - val_loss: 0.8684 - val_accuracy: 0.7076

 MNIST分類で採用した前項のモデルと同一ですが、学習の結果はそれほど高精度のモデルにはなっていません。MNISTのデータは白黒でしたので、このような結果となりました。

*** under construction ***

学習済みモデルを用いた画像からの物体の識別


 通常のCPUを搭載したPCでは、正答率が90%を超えるまでニューラルネットワークの学習を行うためには、数時間から数日も必要とされます。Kerasには、学習済みモデルが用意されています。ImageNetで学習した重みをもつ画像分類のモデルとして、以下のものが用意されています。


Xception
VGG16
VGG19
ResNet50
InceptionV3
InceptionResNetV2
MobileNet
DenseNet
NASNet


  ここでは、ディープラーニングでよく使用されるニューラルネットワークであるVGG、ResNet及びInceptionV3を使用します。VGGは、畳み込み層とプーリング層から構成される基本的なCNNです。畳み込み層と全結合層を全部で16もしくは19層にしてディープにしています。前者をVGG16、後者をVGG19と呼びます。VGGは、2014年に開催された大規模画像認識のコンペILSVRC(ImageNet Large Scale Visual Recognition Challenge)で2位の成績に終わりましたが、シンプルな構成なので応用面ではよく使用されます。(ちなみに、優勝者はGoogLeNetでした)VGGは3x3のフィルターによる畳み込み層を2回から4回連続して、プーリング層でサイズを半分にするという処理を繰り返します。
  ResNetは2015年Microsoftのチームによって開発されたニューラルネットワークです。その特徴は、層を深くしすぎると過学習などの問題が起きるのを回避するために、スキップ構造(ショートカット)と呼ばる概念を導入した点です。ResNetは、VGGのネットワークをベースにして、スキップ構造を取り入れて、層を深くしています。具体的には、畳み込み層を2層おきにスキップしてつなぎ、層を150層以上まで深くしています。ILSVRCのコンペでは、誤認識率が3.5%という驚異的な成果を出しています。
  最初に、この中で最も単純なVGG16モデルを取り上げます。上で触れたとおり、VGG16は2014年のILSVRCで提案された畳み込み13層とフル結合3層の計16層から成る畳み込みニューラルネットワークです。層の数が多いだけで一般的な畳み込みニューラルネットと大きな違いはなく、同時期に提案されたGoogLeNetに比べるとシンプルでわかりやすい。ImageNetと呼ばれる大規模な画像データセットを使って訓練したモデルが公開されています。VGG16の出力層は1000ユニットあり、ImageNetの1000クラスを分類するニューラルネットです。
*** under constyruction ***

Object Detection APIを用いた物体検出


TensorFlow Object Detection API can be used to detect, with bounding boxes, objects in images and/or video using either some of the pre-trained models made available or through models you can train on your own (which the API also makes easier).

*** under construction ***

PyTorchでObject Detectionのページに移る

このページの先頭に戻る