茨城エンジニアのPython開発日記

茨城のITベンチャー企業ではたらく2年目エンジニア。Pythonで色々なものを作成中。

論文読んでAIつくるぞ会(第5回) ~推論に挑戦~


ブログから記事を見つけたい場合はこちら

ブログ地図 - 茨城エンジニアのPython開発日記

こんにちは。

先日、仕事を収めてきました、開発メンバーのKです。
2020年を振り返ろうとすると、いろいろありすぎて振り返るのが大変なので、とりあえず振り返らずに前を向いて2021年も楽しく生きていく所存です。


さて、前回
https://tottorisnow33.hatenablog.com/entry/2020/12/19/210334
はSemantic Segmentationをするための学習を行ったので、今回は推論にチャレンジしました。

以下、目次です。

1. 書いたソースコード

今回書いたソースコードは以下の通り。

from PIL import Image
import numpy as np
import glob
import os
import cv2
import tensorflow as tf

###########################################
###任意の画像に対して推論→可視化のメイン関数###
###########################################
def demo_main():

    ###############
    ###推論可視化###
    ###############
    #選択した画像の入力((高さ, 幅, RGB)の三次元配列に格納)
    img_path="category/cat.jpg"
    input_img_gbr= cv2.imread(img_path)
    input_img_rgb = cv2.cvtColor(input_img_gbr, cv2.COLOR_BGR2RGB)

    input_height = input_img_rgb.shape[0]
    input_width = input_img_rgb.shape[1]
    print('input_height:', input_height)
    print('input_width:', input_width)

    #画像のフォーマットをセマセグの入力にあわせる(1枚, 128, 128, RGB)
    input_img_rgb = input_img_rgb/255.0
    input_img = cv2.resize(input_img_rgb, (128, 128), interpolation = cv2.INTER_LINEAR)

    #NNの情報入手
   # 同じモデルを読み込んで、重みやオプティマイザーを含むモデル全体を再作成
    model = tf.keras.models.load_model('my_model.h5')
    model.summary()

    gpus = tf.config.experimental.list_physical_devices('GPU')
    if gpus:
        try:
            for gpu in gpus:
                tf.config.experimental.set_memory_growth(gpu, True)
        except RuntimeError as e:
            print(e)


    # #推論実施
    input_img = np.expand_dims(input_img, axis = 0)
    predict_results = model.predict(input_img)
    print("[*] 成功!")

    #画像出力
    predict_result = predict_results[0,:,:,8] # catの確率はは8番目のインデックスに入っているので。
    predict_result = cv2.resize(predict_result, (input_width, input_height), interpolation = cv2.INTER_NEAREST)
    out_img = input_img_gbr
    out_img[:,:,0] = np.where(predict_result > 0.5, out_img[:,:,0], out_img[:,:,0]*0)
    out_img[:,:,1] = np.where(predict_result > 0.5, out_img[:,:,1], out_img[:,:,1]*0)
    out_img[:,:,2] = np.where(predict_result > 0.5, out_img[:,:,2], out_img[:,:,2]*0)

    cv2.imwrite('cat.png', out_img)


if __name__ == '__main__':
    demo_main()

今回はお試し版なので、前々回くらいに作ったload.pyをインポートしていません。
前回の学習モデルとパラメータは必要なので

model = tf.keras.models.load_model('my_model.h5')

で取得しています。

また、今回はcatの画像を入れて、うまくSemantic Segmentationできているかを見ようと思います。猫の確率は推論結果の配列のインデックス8番目に入っているので、

predict_result = predict_results[0,:,:,8]

で猫の結果だけ引っ張ってきています。

出力画像は、入力画像に対して猫の確率が0.5より小さいpixを真っ黒にした画像を出力しています。

2. エラーで動かないけどGPUのメモリ節約したら何とかなった

上記のソースを実行しようとすると、突然以下のエラーが出てきました。。。

Physical devices cannot be modified after being initialized
2020-12-26 16:02:48.500739: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library cudnn64_7.dll
2020-12-26 16:02:48.956309: E tensorflow/stream_executor/cuda/cuda_dnn.cc:329] Could not create cudnn handle: CUDNN_STATUS_ALLOC_FAILED
2020-12-26 16:02:48.956883: E tensorflow/stream_executor/cuda/cuda_dnn.cc:329] Could not create cudnn handle: CUDNN_STATUS_ALLOC_FAILED
2020-12-26 16:02:48.958289: W tensorflow/core/common_runtime/base_collective_executor.cc:217] BaseCollectiveExecutor::StartAbort Unknown: Failed to get convolution algorithm. This is probably because cuDNN failed to initialize, so try looking to see if a warning log message was printed above.
         [[{{node mnist_model/conv2d/Conv2D}}]]
Traceback (most recent call last):
  File "demo_forBLOG.py", line 63, in <module>
    demo_main()
  File "demo_forBLOG.py", line 47, in demo_main
    predict_results = model.predict(input_img)
  File "C:\Users\seigo\miniconda3\envs\tf_ct\lib\site-packages\tensorflow_core\python\keras\engine\training.py", line 1013, in predict
    use_multiprocessing=use_multiprocessing)
  File "C:\Users\seigo\miniconda3\envs\tf_ct\lib\site-packages\tensorflow_core\python\keras\engine\training_v2.py", line 498, in predict
    workers=workers, use_multiprocessing=use_multiprocessing, **kwargs)
  File "C:\Users\seigo\miniconda3\envs\tf_ct\lib\site-packages\tensorflow_core\python\keras\engine\training_v2.py", line 475, in _model_iteration
    total_epochs=1)
  File "C:\Users\seigo\miniconda3\envs\tf_ct\lib\site-packages\tensorflow_core\python\keras\engine\training_v2.py", line 128, in run_one_epoch
    batch_outs = execution_function(iterator)
  File "C:\Users\seigo\miniconda3\envs\tf_ct\lib\site-packages\tensorflow_core\python\keras\engine\training_v2_utils.py", line 98, in execution_function
    distributed_function(input_fn))
  File "C:\Users\seigo\miniconda3\envs\tf_ct\lib\site-packages\tensorflow_core\python\eager\def_function.py", line 568, in __call__
    result = self._call(*args, **kwds)
  File "C:\Users\seigo\miniconda3\envs\tf_ct\lib\site-packages\tensorflow_core\python\eager\def_function.py", line 638, in _call
    return self._concrete_stateful_fn._filtered_call(canon_args, canon_kwds)  # pylint: disable=protected-access
  File "C:\Users\seigo\miniconda3\envs\tf_ct\lib\site-packages\tensorflow_core\python\eager\function.py", line 1611, in _filtered_call
    self.captured_inputs)
  File "C:\Users\seigo\miniconda3\envs\tf_ct\lib\site-packages\tensorflow_core\python\eager\function.py", line 1692, in _call_flat
    ctx, args, cancellation_manager=cancellation_manager))
  File "C:\Users\seigo\miniconda3\envs\tf_ct\lib\site-packages\tensorflow_core\python\eager\function.py", line 545, in call
    ctx=ctx)
  File "C:\Users\seigo\miniconda3\envs\tf_ct\lib\site-packages\tensorflow_core\python\eager\execute.py", line 67, in quick_execute
    six.raise_from(core._status_to_exception(e.code, message), None)
  File "<string>", line 3, in raise_from
tensorflow.python.framework.errors_impl.UnknownError:  Failed to get convolution algorithm. This is probably because cuDNN failed to initialize, so try looking to see if a warning log message was printed above.
         [[node mnist_model/conv2d/Conv2D (defined at demo_forBLOG.py:47) ]] [Op:__inference_distributed_function_1157]

Function call stack:
distributed_function


このエラーが取れずに数時間悩みました。
最初の予想では、cudaのバージョンやtensorflowのバージョンが悪くて正常に動くバージョンを探さないといけないのかなと思っていましたが、どうやら違ったようで今回はGPUのメモリのリソースに余裕を持たせて実行することで解決しました。
具体的には、モニターを2画面表示しているのを1画面にしました。
おそらく、メモリが足りてなかったのでしょうか。。新しいグラボを買うか、モデル構造を見直す必要がありそうです。。

ちなみに、メモリ不足対策としてソースコードのほうで以下のように書いておきましたが、モニターを2画面出力しているときはやっぱりエラーで止まっていました。

    gpus = tf.config.experimental.list_physical_devices('GPU')
    if gpus:
        try:
            for gpu in gpus:
                tf.config.experimental.set_memory_growth(gpu, True)
        except RuntimeError as e:
            print(e)

3. 推論結果

以下を入力画像として推論させました。

f:id:tottorisnow33:20201226164820j:plain
うちのかわいい猫

推論の結果は、猫の部分だけ残っていて他が真っ黒になっていればよいのですが、実際には以下のようになりました。

f:id:tottorisnow33:20201226165004p:plain
うちのかわいい猫の推論結果

。。。。どうやら僕らが作ったモデルはかわいい猫を識別しないようです。あぁ、かわいい猫はどこへ行ってしまったのか。
すべて真っ黒ということは、各ピクセルにおいて猫である確率が0.5以下であるということです。

前回、テキトーな学習で64%の正答率だとか言ってましたが、おそらくそのすべてが背景の正答率だったのでしょう。
たしかに、もし僕が怠惰な識別器だったら、画像をすべてを「背景だよ!ヨシ!」という結果にするでしょう。大体の画像の大半を占めるのが背景であることを考えると、画像全体を背景と言っておけばそれなりの結果になりますから。

4. 次回

次回は、今回作った評価用のコードをもっと煮詰めて、各クラスごとに出力結果に色を付けたいなと思います。
また、各クラスの識別結果を数値でも見られるようにしたいです。
定性的かつ定量的に評価できるようになったら、モデルをいじったときに良くなったのか悪くなったのかを知ることができるので。