LoginSignup
3
4

More than 3 years have passed since last update.

Kerasでとりあえず動かしてみるTPUでのディープラーニング

Last updated at Posted at 2019-05-07

はじめに

GPUが載ってないPCでディープラーニングをやってみたい、という人向けです。
今回は前回作成した数字の判定をTPUを使ってやってみます。
https://qiita.com/norikawamura/items/a5c3844e7555202c35a4#_reference-64514a0a96dfd9b1648e

事前準備

ColaboratoryでハードウェアアクセラレータにTPUを選択します。

ColaboratoryでTPUを使用するには

結論としては以下の変更が必要なようです。(2019/5/7時点)
①「keras.~」でimportしていたパッケージを「tensorflow.keras.~」とtensorflowの物に変更する。(optimizerの指定等も含む)
②CPU/GPU向けで作成したモデルをTPU向けのモデルに変換する。
 ・環境情報を取得後、keras_to_tpu_model()で変換する。
③TPUモデルではpredict_classes()が使えないので、分類を行う場合は代わりにpredict()の結果の最大値をとる。
④TPUモデルではpredict()に渡すデータの件数が、TPUコア数(8)の倍数である必要がある。

データの準備

前回と同様です。

import sklearn as skl
from sklearn import datasets
import pandas as pd

dgt = skl.datasets.load_digits()
digits_df = pd.DataFrame(dgt.data)
target_df = pd.DataFrame(dgt.target)

# 特徴量のセットを変数Xに、ターゲットを変数yに格納
X = digits_df.values
y = target_df.values

学習データと検証用データに分けます。

kerasの代わりにtensorflow.kerasに変更しています。
また、検証用データの数を8の倍数にしておきます。
※学習用データの数は8の倍数になっている必要はないようです。

import numpy as np
import tensorflow.keras as keras
# データの順番を入れ替えるためのランダムなNumPy配列
np.random.seed(42)
indices = np.random.permutation(len(X))
val_len = int(len(X) * -0.1) // 8 * 8    #TPUを使った場合のために8の倍数にする

# 学習用のデータ。全体から100データを省いたもの
X_train = X[indices[:val_len]]
y_train = y[indices[:val_len]]

# テスト用のデータ。全体から100データ取り出したもの
X_test  = X[indices[val_len:]]
y_test  = y[indices[val_len:]]

# サンプル数、特徴量の次元、クラス数の取り出し
(n_samples, n_features) = X_train.shape
n_classes = len(np.unique(y))

# ターゲットyをkeras用の形式に変換
y_keras = keras.utils.to_categorical(y_train, n_classes)

損失関数のグラフ表示

前回のものと同じです。

import matplotlib.pyplot as plt
#損失関数グラフ
def plotHistory(history):
    # 損失関数のグラフの軸ラベルを設定
    plt.xlabel('time step')
    plt.ylabel('loss')
    # グラフ縦軸の範囲を0以上と定める
    plt.ylim(0, max(np.r_[history.history['val_loss'], history.history['loss']]))
    # 損失関数の時間変化を描画
    val_loss, = plt.plot(history.history['val_loss'], c='#56B4E9')
    loss, = plt.plot(history.history['loss'], c='#E69F00')
    # グラフの凡例(はんれい)を追加
    plt.legend([loss, val_loss], ['loss', 'val_loss'])
    # 描画したグラフを表示
    plt.show()

モデルの定義・学習

「#TPU」のコメントの下のkeras_to_tpu_model()を呼ぶまでの部分が、今回追加したTPU用にモデルを変換する部分です。

import os
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import BatchNormalization
from tensorflow.keras.layers import Conv2D, MaxPooling2D
from tensorflow.keras.layers import Flatten
from tensorflow.keras.layers import Dense, Dropout
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.callbacks import EarlyStopping

X_train = X_train.reshape(-1, 8, 8, 1)
X_test  = X_test.reshape(-1, 8, 8, 1)

savefile = 'keras_clf_skldigit_tpu.h5'
useSavedModel = False
if useSavedModel == False:
    # ニューラルネットワークを定義
    model = Sequential()

    # ニューラルネットワークを定義
    model = Sequential()
    # 中間層と入力層を定義
    model.add(Conv2D(32, kernel_size=(3, 3),
                     activation='relu',
                     input_shape=(8,8,1,)))
    model.add(Conv2D(64, (3, 3), activation='relu'))
    #model.add(MaxPooling2D(pool_size=(2, 2)))
    #model.add(BatchNormalization())
    model.add(Conv2D(128, (3, 3), activation='relu'))
    model.add(Flatten())
    model.add(Dense(128, activation='relu'))
    model.add(BatchNormalization())

    # 出力層を定義
    model.add(Dense(units=n_classes, activation='softmax'))

    # モデルのコンパイル
    model.compile(loss='categorical_crossentropy', optimizer=Adam(lr=0.0002), metrics=['accuracy'])

    # TPU
    tpu_grpc_url = "grpc://"+os.environ["COLAB_TPU_ADDR"]
    tpu_cluster_resolver = tf.contrib.cluster_resolver.TPUClusterResolver(tpu_grpc_url)
    #strategy = keras_support.TPUDistributionStrategy(tpu_cluster_resolver)
    strategy = tf.contrib.tpu.TPUDistributionStrategy(tpu_cluster_resolver)
    model = tf.contrib.tpu.keras_to_tpu_model(model, strategy=strategy)

    # モデルの学習
    early_stopping = EarlyStopping(monitor='val_loss', mode='min', patience=1000)
    plotHistory(
        model.fit(
             X_train
            ,y_keras
            ,epochs=10000
            ,validation_split=0.1
            ,batch_size=n_samples
            ,verbose=2
            ,callbacks=[early_stopping]
        )
    )    

    # 学習結果を保存    
    model.save(savefile)
else:    
    # 学習済ファイルを読み込んでmodelを作成
    model = keras.models.load_model(savefile)

image.png

判定処理

TPUだとmodel.predict_classes()が使えないので、predict()の結果の最大値をnumpy.argmax()で取得して代用します。

y_test2 = y_test.reshape(-1)

# 結果の表示
#result = model.predict_classes(X_test, verbose=0)
y_result = model.predict(X_test, verbose=0)
import numpy as np
result = np.zeros(y_test2.shape, int)
for idx, data in enumerate(y_result):
  result[idx] = int(np.argmax(data))

print('ターゲット')
print(y_test2)
print('ディープラーニングによる予測')
print(result)

# データ数をtotalに格納
total = len(result)
# ターゲット(正解)と予測が一致した数をsuccessに格納
success = sum(result==y_test2)

# 正解率をパーセント表示
print('正解率')
print(100.0*success/total)

image.png

次回

 「CAEを使ったノイズ除去」をやってみます。
 https://qiita.com/norikawamura/items/044f7fda43f609f8f1d8

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4