論文読んでAIつくるぞ会(第2回) ~Tensorflow KerasのSequential APIとFunctional APIに挑戦~
ブログから記事を見つけたい場合はこちら
ブログ地図(大) - 茨城エンジニアのPython開発日記
ブログから記事を見つけたい場合はこちら
こんにちは、開発メンバーのKです。
今回は朝7:20からみんなで勉強会でした。休日の早起きは気分が良い。
前回から方針が変わり、
Tensorflow 2.xでAI関連の論文を実装するぞ!
というモチベーションでお勉強することになりました。
それにあたり、進める手順として以下のようにしようと、決まりました。
[1] TensorFlow でひながたNNを作る
[2] いろいろ変えられるようになる
[3] Semantic Segmentation のひながたを作る
[4] 論文を読む
[5] 論文をTensorFlowで再現
さて、今回は上記の [1]、[2]をやりました。
以下、目次です。
- 0. CondaでTensorflow-gpu 2.xを導入
- 1. MNISTを学習するためのソースをSequential APIで実装
- 2. MNISTを学習するためのソースをFunctional APIで実装
- 3. 次回は何をやるか
0. CondaでTensorflow-gpu 2.xを導入
以下の手順でTensorflow-gpuを入れました。
なお、OSはWindows 10です。
0-1. Conda で仮想環境を作る
コマンドプロンプト上で以下のコマンドを入力
> conda create -n myenv python=3.7 > conda activate myenv
# 最初、python 3.8.x を入れていたのですが、tensorflow-gpuを入れるときに低いバージョンにしてと怒られたので、python 3.7.x を入れました。
0-2. tensorflow-gpuのインストール
仮想環境が立ち上がった状態でコマンドプロンプト上で以下のコマンドを入力
> conda install -c anaconda tensorflow-gpu
0-3. tensorflowのバージョン確認
コマンドプロンプト上で以下を入力
> python >>> import tensorflow as tf >>> print(tf.__version__)
これで入っているバージョンが確認できます。おそらくtensorflowの 2.x が入っていることでしょう。
1. MNISTを学習するためのソースをSequential APIで実装
Tensorflowの公式のチュートリアル*2を参考に、Sequential APIでMNISTデータセットを学習させてみました。
チュートリアルを丸パクリではつまらないので、全結合だけでなくConvolutionも入れてみました。
Sequential APIで自分のモデルを作る場合、model.add でどんどんlayerを追加していくようです。それだけで簡単にモデルを構築できちゃいます。
しかし、Sequential APIはlayerを積み重ねることしができず、branchを分けるようなことはできません。そのため、ResNetやU-NetのようにSkip Connectionがあるモデルは実装できないと思います。
また、入力と出力は1つのテンソルのみです。Lossを複数定義することは出来ないでしょう。
以下、実際に作ったソースコードです。
import tensorflow as tf # グラボのメモリが不足してる時ばこれをいれる physical_devices = tf.config.list_physical_devices('GPU') try: tf.config.experimental.set_memory_growth(physical_devices[0], True) except: # Invalid device or cannot modify virtual devices once initialized. pass # エポック、バッチサイズの設定 epochs = 20 batch_size = 128 # mnistデータセットのロード mnist = tf.keras.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 # 画像のpixelの値は0~255なので0.0~1.0に正規化 # 入力画像をreshape # 入力は(batch数, 幅, 高さ, チャネル)を想定しているが、x_trainは(batch数, 幅, 高さ)となっているのでReshape x_train = x_train.reshape(x_train.shape[0], x_train.shape[1], x_train.shape[2], 1) x_test = x_test.reshape(x_test.shape[0], x_test.shape[1], x_test.shape[2], 1) input_shape = (x_train.shape[1], x_train.shape[2], 1) # モデル構築 model = tf.keras.models.Sequential() model.add(tf.keras.layers.Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=input_shape)) model.add(tf.keras.layers.Conv2D(64, kernel_size=(3, 3), activation='relu')) model.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2))) model.add(tf.keras.layers.Dropout(0.25)) model.add(tf.keras.layers.Flatten()) model.add(tf.keras.layers.Dense(128, activation='relu')) model.add(tf.keras.layers.Dropout(0.5)) model.add(tf.keras.layers.Dense(10, activation='softmax')) model.summary() # 損失関数 loss_fn = tf.keras.losses.sparse_categorical_crossentropy model.compile(optimizer='adam', # 最適化アルゴリズム loss=loss_fn, # 損失関数 metrics=['accuracy']) # 学習 model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=1, validation_data=(x_test, y_test)) # 評価 score = model.evaluate(x_test, y_test, verbose=0) print('Test loss:', score[0]) print('Test accuracy:', score[1]) # save model model.save("model_mnist_cnn.h5")
2. MNISTを学習するためのソースをFunctional APIで実装
こちらもTensorflowの公式サイト*3を参考にソースコードを作りました。1 で作ったSequential APIのモデル構造はそのままに、Functional APIの書き方で書きました。
Functional APIで自分のモデルを作る場合、まるで関数の数式を書くようにlayerを追加できます。
例えば、y=f(x)という数式で考えると、
x: 入力のテンソル
f: 自分で設定したレイヤ (<-- tf.keras.layers.Conv2D() とか tf.keras.layers.Dense() とか)
y: 出力のテンソル
という意味になります。だからこれをつなげて、
y1=f1(x)
y2=f2(y1)
y3=f3(y2)
...
と書けばOKです。
Functional APIでは、Sequential APIでは出来ない"layerのbranchを分けること"や"入力と出力を複数用意すること"ができます。これを使えるようになれば、論文に書かれているモデルを実装するときに障害がかなりなくなります。
以下、実際に作ったソースコードです。
import tensorflow as tf # グラボのメモリが不足してる時ばこれをいれる physical_devices = tf.config.list_physical_devices('GPU') try: tf.config.experimental.set_memory_growth(physical_devices[0], True) except: # Invalid device or cannot modify virtual devices once initialized. pass # エポック、バッチサイズの設定 epochs = 20 batch_size = 128 # mnistデータセットのロード mnist = tf.keras.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 # 画像のpixelの値は0~255なので0.0~1.0に正規化 # 入力画像をreshape # 入力は(batch数, 幅, 高さ, チャネル)を想定しているが、x_trainは(batch数, 幅, 高さ)となっているのでReshape x_train = x_train.reshape(x_train.shape[0], x_train.shape[1], x_train.shape[2], 1) x_test = x_test.reshape(x_test.shape[0], x_test.shape[1], x_test.shape[2], 1) input_shape = (x_train.shape[1], x_train.shape[2], 1) # モデル構築 mnist_inputs = tf.keras.Input(shape=input_shape, name='mnist_input') conv_1 = tf.keras.layers.Conv2D(32, kernel_size=(3, 3), activation='relu')(mnist_inputs) conv_2 = tf.keras.layers.Conv2D(64, kernel_size=(3, 3), activation='relu')(conv_1) conv_2 = tf.keras.layers.Dropout(0.25)(conv_2) pool_3 = tf.keras.layers.MaxPooling2D(pool_size=(2, 2))(conv_2) flat_4 = tf.keras.layers.Flatten()(pool_3) dense_5 = tf.keras.layers.Dense(128, activation='relu')(flat_4) dense_5 = tf.keras.layers.Dropout(0.5)(dense_5) mnist_outputs = tf.keras.layers.Dense(10, activation='softmax')(dense_5) model = tf.keras.Model(inputs=mnist_inputs, outputs=mnist_outputs, name="mnist_model") model.summary() # 損失関数 loss_fn = tf.keras.losses.sparse_categorical_crossentropy model.compile(optimizer='adam', # 最適化アルゴリズム loss=loss_fn, # 損失関数 metrics=['accuracy']) # 学習 model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=1, validation_data=(x_test, y_test)) # 評価 score = model.evaluate(x_test, y_test, verbose=0) print('Test loss:', score[0]) print('Test accuracy:', score[1]) # save model model.save("model_mnist_func_cnn.h5")
3. 次回は何をやるか
今回の勉強会で
[1] TensorFlow でひながたNNを作る
[2] いろいろ変えられるようになる
が終わったので、次回は
[3] Semantic Segmentation のひながたを作る
をやる予定です。
(次回もみんなで早起きする予定)
それではまた次回!