教育

【ディープラーニング入門用】知っておきたいTensorFlowとKerasの使い方

【ディープラーニング入門用】知っておきたいTensorFlowとKerasの使い方

ディープラーニングでTensorFlowとKerasが役立つって聞くけど難しすぎてわからない!

AI(人工知能)やディープラーニングの実装について調べていると必ずといってもいいくらいこの用語2つが出てきますよね。

TensorFlowはフレームワーク、Kerasはライブラリの1つでPythonのscikit-learnなどと並びAI(人工知能)に関わっていく上でなくてはならないものとなっています。

とはいうもののAI(人工知能)の実装でよく使われるPythonとコードの書き方で勝手が違い初心者にはなかなかわかりづらいのが難点。
というわけで今回はTensorFlowとKerasそれぞれについてや共通点、違い、実装方法について触れた上で最後に活用することで何ができるようになるかお伝えしていきます。
中村
中村

それではまず、TensorFlowとは何かというところからお伝えしていきます。

TensorFlowとは

aiのイメージ

まずTensorFlowはGoogleが開発しているフレームワーク。

ディープラーニング向けとなっておりニューラルネットワークを使用した学習を行う機能をオープンソースで提供されているのが特徴です。

DistBeliefというYouTubeやGoogle翻訳、音声検索などに用いられていたものを土台に使い勝手の改善や用途の拡大を目的に開発が進められており社内の業務でも活用されています。

名前だけ見るとTensor(テンソル)って何?となりますよね。

これは線形的な量を表す概念を一般化したもの。

多次元の配列として表現できるので「多次元配列」であると認識して差し支えありません。

Flowという言葉と併せると多次元のデータを流れるように処理できるということでありそれを通してディープラーニングができるということになります。

Kerasとは

ライブラリのイメージ

TensorFlowとは何か触れたのでKerasについても解説していきます。

これはTensorFlowやCNTKなどディープラーニングのライブラリの上で実行できるニューラルネットワークのライブラリのこと。

実験を迅速に行えるようにすることに主眼を置かれており、それらよりも簡単にモデルの作成ができるよう設計されているのが強みです。

そのためアイデアがあった時結果を出すまでの時間を小さくすることが期待できます。

TensorFlowとKerasの共通点・違い

二項対立のイメージ

TensorFlowとKerasについてそれぞれ触れたので今度は両者の共通点と違いを見ていきましょう。

ディープラーニングを扱うという目的ではTensorFlowとKerasのどちらにも共通している点。
大きな違いとしてそれぞれの位置づけや難易度の差が挙げられます。

まず位置づけについて。

最初にも上げたようにTensorFlowはGoogleが開発しているフレームワーク。

それに対しKerasはTensorFlowなどの上位ライブラリにあたりテンソル計算を高速に行うものとなります。

なのでTensorFlowはAI(人工知能)に使われるフレームワークでKerasはその上で動作するライブラリという認識でほぼ説明ができます。
細かく見るとKerasはTheanoというフレームワークでも動くものの既に開発が終了しているので上記のように考えるのが妥当です。

次に難易度。

TensorFlowは「Define and Run」という形をとっており、計算処理をグラフとして一度構築しその上でまとめて計算処理をするということになります。

つまり、単純な処理であっても計算グラフで考えるというステップを踏むのは避けられず初心者にとって難しく感じてしまうところです。

そんなTensorFlowに対しKerasの特徴はその計算グラフをかなり簡単に記述できること。

層をひたすら積み重ねるだけですぐ実装ができるので不慣れな人でも簡単に実装ができます。
そのためTensorFlowより簡単にニューラルネットワークの構築ができる一方、中の計算はTensorFlowに任せてしまうので処理内容の理解がわからないので本格的な学習には向かないという点に注意が必要です。

TensorFlowとKerasのダウンロード・インストール方法

ダウンロードしているイメージ

TensorFlowとKerasの共通点と違いを見てきたのでそれぞれのダウンロード・インストール方法をお伝えします。

中村
中村

今回はAnacondaという環境に2つを入れるという想定で進めていきます。

Anacondaをまだインストールしていない方はAIZINEの中でやり方の説明をした記事があるので是非ご覧ください。

まず、AnacondaからmacOSであればターミナル、Windowsであればコマンドプロンプトを起動、まずは

$ conda install tensorflow

と入力し実行。

完了したら続けて

$ conda install keras

と入力し実行が完了できれば成功です。

TensorFlowとKerasを用いた実装方法

キーボードで打ち実装しているイメージ

TensorFlowとKerasのダウンロード・インストール方法について触れたので実装方法についても見ていきましょう。

今回は乗り物や動物など6万枚のカラー写真のデータセット「CIFAR-10」を使い画像に対しそれぞれ何の画像であるかを当てるプログラムを実装していきます。

中村
中村

AnacondaからJupyter NotebookやJupyterLabでの使用を想定していますがGoogleColabでの使用も可能です。

[1]:

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Conv2D, Flatten, Dropout, MaxPooling2D 
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import os
import numpy as np
import matplotlib.pyplot as plt
#https://www.tensorflow.org/tutorials/images/classification?hl=ja
print(tf.__version__)

2.4.0

データの読み込み

[2]:

from keras.datasets import cifar10
(train_images, train_labels), (test_images, test_labels) = cifar10.load_data()
Downloading data from https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz (https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz) 170500096/170498071 [==============================] - 2s 0us/step
データセットには上記のクラス名が含まれていないため、後ほど画像を出力するときのために、クラス名を 保存しておきます。
[3]:

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

データセットのフォーマット

[4]:

train_images.shape
(50000, 32, 32, 3)
[5]:

len(train_labels)
50000
[6]:

train_labels.shape
(50000, 1)
[7]:

test_images.shape
(10000, 32, 32, 3)
[8]:

len(test_labels)
10000
[9]:

test_labels.shape
(10000, 1)

幅32×高さ32ピクセル: 1つ分のデータが基本的に(3, 32, 32)もしくは(32, 32, 3)(=計3072要素)という多 次元配列の形状となっており、最初もしくは最後の次元にある3要素がRGB値。

訓練用データでは50,000 枚、テスト用では10,000枚ということになります。
[10]:

#5x5枚の画像を表示する
plt.figure(figsize=(10,10))
for i in range(25):
    cifar_img=plt.subplot(5,5,i+1)
    plt.imshow(train_images[i]) #x軸の目盛りを消す
    plt.tick_params(labelbottom='off') #y軸の目盛りを消す
    plt.tick_params(labelleft='off') #正解ラベルを表示
    plt.title(train_labels[i])
plt.show()
/usr/local/lib/python3.6/dist-packages/matplotlib/text.py:1165: FutureWarning: elementwise comparison failed; returning scalar instead, but in the future will pe rform elementwise comparison
if s != self._text:

スクリーンショット1枚目

クラスラベルは次の10クラス [0] airplane (飛行機) [1] automobile (自動車) [2] bird (鳥) [3] cat (猫) [4] deer (鹿) [5] dog (犬) [6] frog (カエル) [7] horse (馬) [8] ship (船) [9] truck (トラック)となります。

前処理

ネットワークを訓練する前に、データを前処理する必要があります。

最初の画像を見ると画素の値が0から 255の間であることがわかります。
[11]:

plt.figure()
plt.imshow(train_images[0])
plt.colorbar()
plt.grid(False)
plt.show()

スクリーンショット2枚目

ニューラルネットワークにデータを投入する前に画素の値を255で割り0から1までの範囲にスケールします。

訓練用もテスト用も同じです。
[12]:

train_images = train_images / 255.0
test_images = test_images / 255.0

訓練用データセットの最初の25枚の画像を、クラス名付きで表示します。

ネットワークを構築・訓練する前に、データが正しいフォーマットになっていることを確認します。
[13]:

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)
    plt.xlabel(class_names[int(train_labels[i])])
plt.show()

スクリーンショット3枚目

モデルの構築

ニューラルネットワークを構築する第一歩としてモデルの階層を定義、その後モデルをコンパイルします。

層の設定

ニューラルネットワークを作る上で層(layer)が基本的な構成要素。

層の役割として入力されたデータから取り組もうとする問題に対し意味のある「表現」を抽出できることが求められます。

ディープラーニングのモデルは単純な層の積み重ねといっても過言ではなくtf.keras.layers.Dense のような層のほとんどに訓練中に学習されるパラメータがあります。
[14]:

model = keras.Sequential([
keras.layers.Flatten(input_shape=(32, 32, 3)),
keras.layers.Dense(256, activation='relu'),
keras.layers.Dense(10, activation='softmax')
])

最初の層は、tf.keras.layers.Flatten です。

この層は、画像を(32×32ピクセルの)2次元配列から、1024ピクセルの、1次元配列に変換します。

この層が、画像の中に積まれているピクセルの行を取り崩し、横に並べると考えてください。

また、RGBに当たる3はそのままにします。ここまでの流れはデータのフォーマット変換を行うだけです。

ピクセルを1次元化しました。

以後、ネットワークは2つの tf.keras.layers.Dense 層となります。

これらは密結合あるいは全結合されたニューロンの層です。

最初の Dense 層には、256個のノード(あるはニューロン)があります。

最後の層でもある2番めの層は、10ノードのsoftmax層です。

この層は、合計が1になる10個の確率の配列を返します。

それぞれのノードは、今見ている画像が10個のクラスのひとつひとつに属する確率を出力します。

モデルのコンパイル

モデルが訓練できるように設定の追加が必要です。コンパイル時に追加されます。

  • 損失関数(loss function) —訓練中にモデルがどれくらい正確かを測定します。損失関数を最小化することにより、訓練中のモデルを正しい方向に向かわせることとなります。
  • オプティマイザ(optimizer)—モデルが見ているデータと損失関数の値をもとにモデルの更新をどう進めていくか決定します。
  • メトリクス(metrics) —訓練とテストのステップを監視する際に使われます。今回はaccuracy(正解率)といい画像が正しく分類された比率を使用しています。
[15]:

model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
model.summary()
Model: "sequential" 
_________________________________________________________________ 
Layer (type) Output Shape Param # 
================================================================= 
flatten (Flatten) (None, 3072) 0 
_________________________________________________________________ 
dense (Dense) (None, 256) 786688 
_________________________________________________________________ 
dense_1 (Dense) (None, 10) 2570 
================================================================= 
Total params: 789,258 Trainable params: 789,258 Non-trainable params: 0
_________________________________________________________________

モデルの訓練

ニューラルネットワークの訓練ではまずモデルに訓練用データ(ここではtrain_imagesとtrain_labels)を入れて画像とラベルの対応関係を学習します。

そして、モデルにテスト用データセットtest_imagesの予測(ここでは分類)を行わせて予測結果とtest_labelsで照合し正答率を確認します。

model.fit メソッドを呼び出し訓練をします。
[16]:

model.fit(train_images, train_labels, epochs=20, batch_size=256)
Epoch 1/20 196/196 [==============================] - 5s 21ms/step - loss: 2.1896 - accuracy: 0.2562 
Epoch 2/20 196/196 [==============================] - 4s 21ms/step - loss: 1.7803 - accuracy: 0.3682 
Epoch 3/20 196/196 [==============================] - 4s 21ms/step - loss: 1.7133 - accuracy: 0.3948 
Epoch 4/20 196/196 [==============================] - 4s 21ms/step - loss: 1.6524 - accuracy: 0.4200 
Epoch 5/20 196/196 [==============================] - 4s 21ms/step - loss: 1.6102 - accuracy: 0.4329 
Epoch 6/20 196/196 [==============================] - 4s 21ms/step - loss: 1.5818 - accuracy: 0.4411 
Epoch 7/20 196/196 [==============================] - 4s 21ms/step - loss: 1.5466 - accuracy: 0.4564 
Epoch 8/20 196/196 [==============================] - 4s 21ms/step - loss: 1.5151 - accuracy: 0.4631 
Epoch 9/20 196/196 [==============================] - 4s 21ms/step - loss: 1.5142 - accuracy: 0.4722 
Epoch 10/20 196/196 [==============================] - 4s 22ms/step - loss: 1.4885 - accuracy: 0.4761 
Epoch 11/20 196/196 [==============================] - 4s 21ms/step - loss: 1.4553 - accuracy: 0.4906 
Epoch 12/20 196/196 [==============================] - 4s 22ms/step - loss: 1.4643 - accuracy: 0.4859 
Epoch 13/20 196/196 [==============================] - 4s 21ms/step - loss: 1.4289 - accuracy: 0.4962 
Epoch 14/20 196/196 [==============================] - 4s 22ms/step - loss: 1.4222 - accuracy: 0.4997 
Epoch 15/20 196/196 [==============================] - 4s 22ms/step - loss: 1.4115 - accuracy: 0.5024 
Epoch 16/20 196/196 [==============================] - 4s 21ms/step - loss: 1.3930 - accuracy: 0.5095 
Epoch 17/20 196/196 [==============================] - 4s 22ms/step - loss: 1.4005 - accuracy: 0.5036 
Epoch 18/20 196/196 [==============================] - 4s 21ms/step - loss: 1.3888 - accuracy: 0.5088 
Epoch 19/20 196/196 [==============================] - 4s 21ms/step - loss: 1.3876 - accuracy: 0.5127 
Epoch 20/20 196/196 [==============================] - 4s 21ms/step - loss: 1.3692 - accuracy: 0.5160

正解率の評価

モデルの訓練ができたのでテスト用データセットに対するモデルの性能も確かめましょう。
[17]:

test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)
print('\nTest accuracy:', test_acc)
Test accuracy: 0.49059998989105225

テスト用データセットでの正解率は、訓練用データセットでの正解率よりも少し低くなりました。

新しいデータに対する機械学習モデルの性能が、訓練時と比較して低下する現象過学習(over fitting)の一例です。

モデルの訓練が終わったら、そのモデルを使って画像の分類予測を行うことが出来ます。
[18]:

predictions = model.predict(test_images)

これは、モデルがテスト用データセットの画像のひとつひとつを分類予測した結果です。最初の予測を見てみましょう。
[19]:

predictions[0]
array([0.01279367, 0.01005951, 0.10952231, 0.2464253 , 0.11879683,
0.19029582, 0.21369596, 0.00096528, 0.09624713, 0.00119826],
dtype=float32)

予測結果として10個の数字の配列になっています。画像が10の項目それぞれに該当するかの「確信度」を表しています。どのラベルが一番確信度が高いかを見てみましょう。
[20]:

np.argmax(predictions[0])
3

モデルによると最初の画像は[3] cat (猫)である可能性が最も高いと判断したことになります。

これが正しいかどうか、テスト用ラベルを見てみましょう。
[21]:

test_labels[0]
array([3], dtype=uint8)

見事正解です。

10チャンネルすべてをグラフ化すると以下のように。
[22]:

def plot_image(i, predictions_array, true_label, img):
    predictions_array, true_label, img = predictions_array[i], true_label[i], img[i]
    plt.grid(False)
    plt.xticks([])
    plt.yticks([])
    plt.imshow(img, cmap=plt.cm.binary)
    predicted_label = np.argmax(predictions_array)
    if predicted_label == true_label:
        color = 'blue'
    else:
        color = 'red'
    plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label],
                                    100*np.max(predictions_array),
                                    class_names[true_label[0]]),
                                    color=color)
def plot_value_array(i, predictions_array, true_label):
    predictions_array, true_label = predictions_array[i], true_label[i]
    plt.grid(False)
    plt.xticks([])
    plt.yticks([])
    thisplot = plt.bar(range(10), predictions_array, color="#777777")
    plt.ylim([0, 1])
    predicted_label = np.argmax(predictions_array)
    thisplot[predicted_label].set_color('red')
    thisplot[true_label[0]].set_color('blue')

先程の画像で試してみましょう。
[23]:

i = 0
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions, test_labels, test_images)
plt.subplot(1,2,2)
plot_value_array(i, predictions, test_labels)
plt.show()

スクリーンショット4枚目

予測の中のいくつかの画像を、予測値とともに表示してみましょう。

予測が合っている場合は青で、誤っている場合は赤で表示されます。数字は予測したラベルのパーセント(100分率)を示します。
[24]:

i = 1
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions, test_labels, test_images)
plt.subplot(1,2,2)
plot_value_array(i, predictions, test_labels)
plt.show()

スクリーンショット5枚目

他の画像も予測してみて予測値とともに表示してみましょう。

正しい予測は青で、誤っている予測は赤でラベルを表示します。数字は予測したラベルのパーセント(100分率)を示します。
[25]:

# X個のテスト画像、予測されたラベル、正解ラベルを表示します。
# 正しい予測は青で、間違った予測は赤で表示しています。
num_rows = 5
num_cols = 3
num_images = num_rows*num_cols
plt.figure(figsize=(2*2*num_cols, 2*num_rows))
for i in range(num_images):
    plt.subplot(num_rows, 2*num_cols, 2*i+1)
    plot_image(i, predictions, test_labels, test_images)
    plt.subplot(num_rows, 2*num_cols, 2*i+2)
    plot_value_array(i, predictions, test_labels)
    plt.show()

スクリーンショット6枚目

こうやって見てみるとモデル側が自信を持って予測していても間違いは起こりうるということがわかります。

TensorFlow・Kerasを活用すれば、こんなこともできる

活用のイメージ

最後にTensorFlowとKerasを使うことでどのようなことができるか見ていきましょう。

まず、TensorFlowは現在も活躍するジャンルや分野のさらなる広がりが予想されています。

有名なものの1つとして挙げられるのがGoogleのMagentaというプロジェクト。

これはニューラルネットワークを用いて作曲や美術の生成をさせておりアート生成におけるAI(人工知能)の活用という点から無視できない活動となっています。

Kerasの方でよく挙げられるのは文章の自動生成や画像認識、botの作成など。

NetflixやUberのような企業はもちろん、スタートアップ企業が自社製品でディープラーニングを重用している際にも使われています。

研究者の間でもKerasは必要不可欠。

CERNやNASAのような機関にも採用されていますしプレプリントサーバであるarXivで公開されている科学技術系の論文でも言及されている回数はトップレベルとなっています。

このようにTensorFlowとKerasは多くの企業や機関の間での共通言語となっているので使いこなすことで個人開発だけでなく就職活動でスキルのアピールに繋げることも可能です。

 

エンジニアのイメージ

今回はディープラーニングに欠かせないTensorFlowとKerasについて両者の違いや相違点にも触れつつ実装方法や活用することでどういったことができるかについてご紹介してきました。

TensorFlowはGoogleが開発しているディープラーニング向けのフレームワークでKerasはTensorFlowの上などで動くライブラリとなります。

ディープラーニングを扱うという目的で一致しているものの大きな違いは難易度。

どちらも「計算グラフ」ありきで実装していくこととなりますがTensorFlowはKerasよりも複雑となります。

今回はAnacondaからインストール方法について言及し実装方法についても触れていきました。

必ずしも簡単とは言えないですが多くの企業や機関が使っているので少しずつマスターし自分の将来を考えていく上で武器になるといいですよね。
トップへ戻る
タイトルとURLをコピーしました