20210213のTensorFlowに関する記事は4件です。

TensorflowのPreProcessでTensorflow以外の関数を使う

はじめに

tensorflow.data.Datasetを使っていて、preprocess内でnumpyのFFTやopenCVを使ったらエラーが出て困った人向けです。いや自分自身が困ったので、そのTipです。

時間がない人向け

tf.py_functionを使用すると出来る。

細かい説明

tf.data.Datasetの簡単な動き

こちらはtensorflowの公式のドキュメントで書いてある通りに、datasetのloaderを作ります。pytorchでいえばdataloaderですね。

def preprocess_image(image):
    image = tf.image.decode_jpeg(image, channels=3)
    image = tf.image.resize(image, [192, 192])
    return image


def load_and_preprocess_image(path):
    image = tf.io.read_file(path)
    return preprocess_image(image)

path_ds = tf.data.Dataset.from_tensor_slices(path_list)
image_ds = path_ds.map(load_and_preprocess_image, num_parallel_calls=tf.data.experimental.AUTOTUNE)

label_ds = tf.data.Dataset.from_tensor_slices(label)
image_label_ds = tf.data.Dataset.zip((image_ds, label_ds))

やっていることは簡単で、pathを渡すと、preprocessを終えたデータが読み込まれるというよくあるdataloaderを作っています。事前に画像のPathのリストと、紐づくラベルのリストを作っておけば簡単です。
これを実行してみると、下記のようなサンプルとなります。ちなみに画像はCifar10です。

fig = plt.figure(figsize=(10, 10))
for i, (im, l) in enumerate(image_label_ds.take(9)):
    fig.add_subplot(3, 3, i + 1)
    plt.imshow(im.numpy().astype(np.uint8))
    plt.title(annot[l.numpy()])  # annotはラベル名のdictionary
plt.tight_layout()

sample1.png

凝ったPreProcessをしたい

このpreprocess内で少し凝った処理を走らせましょう。今回は例として、openCVを使って、色空間を変換(RGB->YCrCb)しています。別にNumpyのFFT関数でもいいし、まぁtensorflow純正以外の関数を使うなら何でも良いです。これで実行してみます。

def preprocess_image(image):
    image = tf.image.decode_jpeg(image, channels=3)
    image = tf.image.resize(image, [192, 192])
    image = cv2.cvtColor(image.numpy(), cv2.COLOR_RGB2YCrCb)
    image = tf.convert_to_tensor(image)
    return image

なんかものすごいエラーが出ます。エラー内容が見たい人は左の三角をクリック。
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
~/workspace/project/cifar10/load_cifar10.py in 
      58 AUTOTUNE = tf.data.experimental.AUTOTUNE
      59 path_ds = tf.data.Dataset.from_tensor_slices(path_list)
----> 60 image_ds = path_ds.map(load_and_preprocess_image, num_parallel_calls=AUTOTUNE)
      61 
      62 label_ds = tf.data.Dataset.from_tensor_slices(label)

~/.pyenv/versions/py37_emopy/lib/python3.7/site-packages/tensorflow/python/data/ops/dataset_ops.py in map(self, map_func, num_parallel_calls, deterministic)
   1700           num_parallel_calls,
   1701           deterministic,
-> 1702           preserve_cardinality=True)
   1703 
   1704   def flat_map(self, map_func):

~/.pyenv/versions/py37_emopy/lib/python3.7/site-packages/tensorflow/python/data/ops/dataset_ops.py in __init__(self, input_dataset, map_func, num_parallel_calls, deterministic, use_inter_op_parallelism, preserve_cardinality, use_legacy_function)
   4082         self._transformation_name(),
   4083         dataset=input_dataset,
-> 4084         use_legacy_function=use_legacy_function)
   4085     if deterministic is None:
   4086       self._deterministic = "default"

~/.pyenv/versions/py37_emopy/lib/python3.7/site-packages/tensorflow/python/data/ops/dataset_ops.py in __init__(self, func, transformation_name, dataset, input_classes, input_shapes, input_types, input_structure, add_to_graph, use_legacy_function, defun_kwargs)
   3369       with tracking.resource_tracker_scope(resource_tracker):
   3370         # TODO(b/141462134): Switch to using garbage collection.
-> 3371         self._function = wrapper_fn.get_concrete_function()
   3372         if add_to_graph:
   3373           self._function.add_to_graph(ops.get_default_graph())

~/.pyenv/versions/py37_emopy/lib/python3.7/site-packages/tensorflow/python/eager/function.py in get_concrete_function(self, *args, **kwargs)
   2937     """
   2938     graph_function = self._get_concrete_function_garbage_collected(
-> 2939         *args, **kwargs)
   2940     graph_function._garbage_collector.release()  # pylint: disable=protected-access
   2941     return graph_function

~/.pyenv/versions/py37_emopy/lib/python3.7/site-packages/tensorflow/python/eager/function.py in _get_concrete_function_garbage_collected(self, *args, **kwargs)
   2904       args, kwargs = None, None
   2905     with self._lock:
-> 2906       graph_function, args, kwargs = self._maybe_define_function(args, kwargs)
   2907       seen_names = set()
   2908       captured = object_identity.ObjectIdentitySet(

~/.pyenv/versions/py37_emopy/lib/python3.7/site-packages/tensorflow/python/eager/function.py in _maybe_define_function(self, args, kwargs)
   3211 
   3212       self._function_cache.missed.add(call_context_key)
-> 3213       graph_function = self._create_graph_function(args, kwargs)
   3214       self._function_cache.primary[cache_key] = graph_function
   3215       return graph_function, args, kwargs

~/.pyenv/versions/py37_emopy/lib/python3.7/site-packages/tensorflow/python/eager/function.py in _create_graph_function(self, args, kwargs, override_flat_arg_shapes)
   3073             arg_names=arg_names,
   3074             override_flat_arg_shapes=override_flat_arg_shapes,
-> 3075             capture_by_value=self._capture_by_value),
   3076         self._function_attributes,
   3077         function_spec=self.function_spec,

~/.pyenv/versions/py37_emopy/lib/python3.7/site-packages/tensorflow/python/framework/func_graph.py in func_graph_from_py_func(name, python_func, args, kwargs, signature, func_graph, autograph, autograph_options, add_control_dependencies, arg_names, op_return_value, collections, capture_by_value, override_flat_arg_shapes)
    984         _, original_func = tf_decorator.unwrap(python_func)
    985 
--> 986       func_outputs = python_func(*func_args, **func_kwargs)
    987 
    988       # invariant: `func_outputs` contains only Tensors, CompositeTensors,

~/.pyenv/versions/py37_emopy/lib/python3.7/site-packages/tensorflow/python/data/ops/dataset_ops.py in wrapper_fn(*args)
   3362           attributes=defun_kwargs)
   3363       def wrapper_fn(*args):  # pylint: disable=missing-docstring
-> 3364         ret = _wrapper_helper(*args)
   3365         ret = structure.to_tensor_list(self._output_structure, ret)
   3366         return [ops.convert_to_tensor(t) for t in ret]

~/.pyenv/versions/py37_emopy/lib/python3.7/site-packages/tensorflow/python/data/ops/dataset_ops.py in _wrapper_helper(*args)
   3297         nested_args = (nested_args,)
   3298 
-> 3299       ret = autograph.tf_convert(func, ag_ctx)(*nested_args)
   3300       # If `func` returns a list of tensors, `nest.flatten()` and
   3301       # `ops.convert_to_tensor()` would conspire to attempt to stack

~/.pyenv/versions/py37_emopy/lib/python3.7/site-packages/tensorflow/python/autograph/impl/api.py in wrapper(*args, **kwargs)
    256       except Exception as e:  # pylint:disable=broad-except
    257         if hasattr(e, 'ag_error_metadata'):
--> 258           raise e.ag_error_metadata.to_exception(e)
    259         else:
    260           raise

AttributeError: in user code:

    <ipython-input-87-550493cbb714>:12 load_and_preprocess_image  *
        return preprocess_image(image)
    <ipython-input-93-6034e2f0f0fd>:4 preprocess_image  *
        image = cv2.cvtColor(image.numpy(), cv2.COLOR_RGB2YCrCb)

    AttributeError: 'Tensor' object has no attribute 'numpy'

ちなみにこの色変換の関数そのものには異常はありません。TensorflowのDatasetのようなパイプラインを介さずに利用すると、ちゃんと画像が表示できます。

image = tf.io.read_file(image_path)
image = preprocess_image(image)

fig = plt.figure(figsize=(8, 4))

fig.add_subplot(1, 2, 1)
plt.imshow(image.numpy().astype(np.uint8))
plt.title("YCC")

fig.add_subplot(1, 2, 2)
# 表示用にもう一度YCC→RGBに戻している
image = cv2.cvtColor(image.numpy(), cv2.COLOR_YCrCb2RGB)
plt.imshow(image.astype(np.uint8))
plt.title("RGB")

sample2.png

tf.py-function降臨

こういう事態を避ける方法があって、tf.py_functionを使用します。下記の例のように、tensorflow純正の関数ではない変換を別の関数にしてやり、それをラッピングする形で使用します。簡単ですね。

def trans_color(image):
    image = cv2.cvtColor(image.numpy(), cv2.COLOR_RGB2YCrCb)
    return tf.convert_to_tensor(image)

def preprocess_image(image):
    image = tf.image.decode_jpeg(image, channels=3)
    image = tf.image.resize(image, [192, 192])
    image = tf.py_function(trans_color, [image], tf.float32)
    return image

これで実際に動かしてみると、下記画像が得られました。
右上の画像と前項での画像が同じになっているのでうまく動いていそうです。

sample3.png

まとめ

tensorflowの前処理で、自身がよく知っているnumpyのFFTを使いたいとか、画像処理の定番のopenCVを使いたいとか、そういうことのTipsでした。py_functionはもっと奥深い機能だと思いますが、こんなふうにも使えるんですね。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

tensorflow-gpuをRTX3070で動かすのは大変だった

概略

TensorFlow公式ページ(https://www.tensorflow.org/install/gpu) に従ってGPU版を導入するもうまく動作しなかった。

ファイル名の書き換えで動作することを確認。

RTX30シリーズで頻発している様子。
今回の対応はかなり応急処置的なので改善待ちですね・・・。

環境

OS
Windows 10 Home(64bit)
バージョン : 20H2

CPU
Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz 2.90 GHz

GPU
GeForce RTX 3070
Driver version : 461.40
CUDA Version : 11.2

言語とライブラリ
conda : 4.9.2
Python : 3.8.5
tensorflow-gpu : 2.4.1

解決までの経緯

指定の要件で動かない

公式のソフトウェア要件(https://www.tensorflow.org/install/gpu#software_requirements) の通りにセットアップして学習を始めると以下のメッセージが

2021-02-13 17:10:23.436049: I tensorflow/stream_executor/platform/default/dso_loader.cc:49] Successfully opened dynamic library cudart64_110.dll
2021-02-13 17:10:24.817916: I tensorflow/compiler/jit/xla_cpu_device.cc:41] Not creating XLA devices, tf_xla_enable_xla_devices not set
2021-02-13 17:10:24.818847: I tensorflow/stream_executor/platform/default/dso_loader.cc:49] Successfully opened dynamic library nvcuda.dll
2021-02-13 17:10:24.850803: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1720] Found device 0 with properties:
pciBusID: 0000:01:00.0 name: GeForce RTX 3070 computeCapability: 8.6
coreClock: 1.725GHz coreCount: 46 deviceMemorySize: 8.00GiB deviceMemoryBandwidth: 417.29GiB/s

~~ 中略 ~~

2021-02-13 17:10:24.892311: W tensorflow/stream_executor/platform/default/dso_loader.cc:60] Could not load dynamic library 'cusolver64_10.dll'; dlerror: cusolver64_10.dll not found
2021-02-13 17:10:24.895383: I tensorflow/stream_executor/platform/default/dso_loader.cc:49] Successfully opened dynamic library cusparse64_11.dll
2021-02-13 17:10:24.895962: I tensorflow/stream_executor/platform/default/dso_loader.cc:49] Successfully opened dynamic library cudnn64_8.dll
2021-02-13 17:10:24.908415: W tensorflow/core/common_runtime/gpu/gpu_device.cc:1757] Cannot dlopen some GPU libraries. Please make sure the missing libraries mentioned above are installed properly if you would like to use GPU. Follow the guide at https://www.tensorflow.org/install/gpu for how to download and setup the required libraries for your platform.
Skipping registering GPU devices...
2021-02-13 17:10:24.909790: I tensorflow/core/platform/cpu_feature_guard.cc:142] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX2
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
2021-02-13 17:10:24.910559: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1261] Device interconnect StreamExecutor with strength 1 edge matrix:
2021-02-13 17:10:24.910934: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1267]    

2021-02-13 17:10:24.911055: I tensorflow/compiler/jit/xla_gpu_device.cc:99] Not creating XLA devices, tf_xla_enable_xla_devices not set
2021-02-13 17:10:25.019189: I tensorflow/compiler/mlir/mlir_graph_optimization_pass.cc:116] None of the MLIR optimization passes are enabled (registered 2)
Epoch 1/100
15/15 [==============================] - 2s 80ms/step - loss: 1.1186 - accuracy: 0.3416
Epoch 2/100
15/15 [==============================] - 1s 80ms/step - loss: 1.0781 - accuracy: 0.3804

~~ 以下略 ~~

最終的に学習は始まってるし一見できている風なんですが、

ここ

Skipping registering GPU devices...

「GPUでやるの飛ばすね。。。」とおっしゃっています。
なので、CPUで動いています。なぜ?

'cusolver64_10.dll'が読み込めない

さっきのメッセージをよく読むと

Could not load dynamic library 'cusolver64_10.dll'; dlerror: cusolver64_10.dll not found

「'cusolver64_10.dll'がないよ」とのこと。
実際CUDAの入っているフォルダを確認してもそんなものはない。

調べてみると公式のGitHubリポジトリでもissueが上がっていました。
(https://github.com/tensorflow/tensorflow/issues/44291)
そこで見つけた解決策がこちら

訳「'cusolver64_11.dll'を'cusolver64_10.dll'に名前変更したら解決しましたよ」

それありなの?(笑)

ありでした

2021-02-13 18:02:35.671492: I tensorflow/stream_executor/platform/default/dso_loader.cc:49] Successfully opened dynamic library cusolver64_10.dll

はい、読み込めてますね。
(かなり胡散臭い対応ですが)これでとりあえずは動くみたいです。

ちなみにGPUだとさっきのCPUで動かした場合の約10倍の速度で学習しています。早い!

# GPU
Epoch 1/100
15/15 [==============================] - 0s 10ms/step - loss: 1.1017 - accuracy: 0.3842
Epoch 2/100
15/15 [==============================] - 0s 8ms/step - loss: 1.0474 - accuracy: 0.4595  

#CPU
Epoch 1/100
15/15 [==============================] - 2s 80ms/step - loss: 1.1186 - accuracy: 0.3416
Epoch 2/100
15/15 [==============================] - 1s 80ms/step - loss: 1.0781 - accuracy: 0.3804

参考

GPU サポート  |  TensorFlow
https://www.tensorflow.org/install/gpu

cuda - tensorflow-gpu の導入がうまくいきません [RTX 3070] - スタック・オーバーフロー
https://ja.stackoverflow.com/questions/72013/tensorflow-gpu-%E3%81%AE%E5%B0%8E%E5%85%A5%E3%81%8C%E3%81%86%E3%81%BE%E3%81%8F%E3%81%84%E3%81%8D%E3%81%BE%E3%81%9B%E3%82%93-rtx-3070

nvidia cudaセットアップ - Qiita
https://qiita.com/mailstop/items/a84ac6b4eac8d12ba488

tensorflow-nightly-gpu looking for cusolver64_10.dll on a cuDNN 11.1 installation · Issue #44291 · tensorflow/tensorflow
https://github.com/tensorflow/tensorflow/issues/44291

RTX 3090 and Tensorflow for Windows 10 - step by step : tensorflow
https://www.reddit.com/r/tensorflow/comments/jsalkw/rtx_3090_and_tensorflow_for_windows_10_step_by/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

とりあえずWindowsで機械学習環境を構築する(GPUあり)

タイトルのまんま。
9割自分用のメモです。
最終的にはtensorflowでGPUを使えるようにし、開発環境としてはJupyter Labをインストールします。

  • Windows 10 Home(バージョン2004/OSビルド21301.1010*評価版を使用)
  • Python 3.8.7
  • tensorflow-gpu 2.4.1
  • CUDA 11.0
  • cuDNN 8.1
  • GeForce 1660 GTX Super

以下の情報はすべて2021/2/13時点のものとなります。

Pythonのインストール

Anacondaは使わないです。

公式サイトからどうぞ。
https://www.python.org/

Downloadのタブから、Stable Releases(安定版)のインストーラーを選択します。
自分の場合はWindows installer(64-bit)を選択。

スクリーンショット 2021-02-12 202539.png

  • 基本的にインストーラーに従うだけでOK。ただし最小構成にしたい場合は「Customize Installation」をチェック。インストーラーの起動も「管理者として実行」から。
  • 「Add Python 3.8 to PATH」をチェックしPATHをチェック。
  • 「Disable path length limit」が表示された場合にはパス最大長の制限を解除する。
  • インストール完了後は、おなじみユーザー環境変数を確認。コントロールパネル→システム→システムの詳細設定→詳細設定タブ→環境変数 から。

作業が完了したらバージョンを確認しましょう。

バージョンの確認方法

コマンドプロンプトを起動→「python -V」を実行。

tensorflowのインストール

gpu対応版のtensorflowはバージョンごとに必要なCUDAとcuDNNのバージョンが指定されています。
https://www.tensorflow.org/install/source?hl=ja#gpu_support_2
スクリーンショット 2021-02-12 204041.png

今回はtensorflow-2.4.xをインストールします。
念のため一度tensorflow周りのアンインストールを実行してから再度インストールを行います。

pip uninstall -y tensorflow tensorflow-cpu tensorflow-gpu tensorflow_datasets tensorflow-hub keras
pip install -U tensorflow-gpu tensorflow_datasets

バージョンの確認方法

コマンドプロンプトを起動し、以下のコマンドを実行。

pip list  | find "tensor"

Visual Studioのインストール

機械学習関係なくね? って感じですがCUDA、cuDNNのインストールにはVisual Studio(正確にはVisual C++ ビルドツール)が必要です。
Visual Studio Communityを入れてもいいし、ビルドツールだけでも問題ありません。
https://docs.microsoft.com/ja-jp/visualstudio/releases/2019/release-notes

Visual Studio Installerでは「C++ Build Tools」にチェックを入れておきます。
これだけで6GBくらい容量食います……。
スクリーンショット 2021-02-13 135115.png

CUDAのインストール

前述の通り、指定のバージョンをインストールしましょう。
https://developer.nvidia.com/cuda-toolkit-archive

CUDA Toolkit 11.0 Update1 (Aug 2020)を選択します。
スクリーンショット 2021-02-13 132554.png

プラットフォームの入力が求められるので、Windows→x86_64→10と選択します。
Installer Typeはどちらでも構いません。
スクリーンショット 2021-02-13 132916.png

インストール時の設定は基本的に規定値のままでOKです。
ドライバのコンポーネントを指定する場面がありますが、ここは「CUDA」のみチェックすれば大丈夫。

バージョンの確認方法

コマンドプロンプトを起動し、以下のコマンドを実行。

nvcc -V nvcc

念のためパスが通っているかも見ておくとよいでしょう。

cuDNNのインストール

同じく指定のバージョンをインストールしましょう。
とか言っておきながら、自分がインストールしたのはcuDNN 8.1でした。が、しっかり動いています。
CUDAがtensorflowのバージョンに依存し、cuDNNは対応するCUDAのバージョンが重要とかなのでしょうか?
https://developer.nvidia.com/cudnn-download-survey

cuDNNのダウンロードにはNVIDIAのDeveloper Program Membershipに参加する必要があります。
アカウントを持っていない方は作成してください。

必要なcuDNNのバージョンを選択し、.zipファイルのダウンロードを行います。
解凍後は以下のディレクトリが構成されています。
スクリーンショット 2021-02-13 133955.png

cuda以下のフォルダすべてをcudaのインストールディレクトリにコピーします。
前章の作業でおそらく「C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.0」というディレクトリが作成されているはずなので、そちらにどうぞ。

バージョンの確認方法

ちょっと調べたんだけど、自分の環境ではコマンドから確認がうまくできませんでした。
「C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.0\include」の中に「cudnn.h」というフォルダがあるのでテキストエディタで開きます。
その中に「# define CUDNN_MAJOR」だとか「# define CUDNN_MINOR」だとかがあるので、それを調べます。

GPU認識の確認

tensorflowがきちんとgpuを認識してくれているかを確認します。

コマンドプロンプトから以下のコマンドを実行。

python -c "from tensorflow.python.client import device_lib; print(device_lib.list_local_devices())"

以下の表示がでればOKです。
スクリーンショット 2021-02-13 135612.png

これで一山超えました。

Jupyter Labのインストール

Annacondaを使っていないのでデフォルトのIDLEしか入っていません。
開発環境はお好みで良いと思いますが、自分はJupyter Labを使用しています。

コマンドプロンプトを起動し、以下のコマンドを実行します。

pip install -U pip setuptools
pip install -U jupyterlab jupyter jupyter-console jupytext nteract_on_jupyter spyder

以下のコマンドを実行し、ブラウザ上でJupyter Labが起動すればOKです。

jupyter lab

作業ディレクトリの変更

Jupyter Labのデフォルトのディレクトリは「C:\Users\(ユーザー名)」になっているのでちょっと使いにくい。
ので、以下の手順で作業ディレクトリを編集します。

まずコマンドプロンプトから以下のコマンドを実行。

jupyter lab --generate-config

すると「C:\Users\(ユーザー名).jupyter」というフォルダの直下に「jupyter_lab_config.py」というファイルが生成されているはずです。
これをテキストエディタで開き、以下の通りディレクトリを指定してあげます。

c.NotebookApp.notebook_dir = '(指定したいディレクトリのパス)'

ちなみに昔の~config.pyファイルには「# c.NotebookApp.notebook_dir = ''」という行があり、コメントアウトを解除してからパスを設定していたようですが、自分の環境では検索かけてもでてきませんでした。
~config.pyファイルはデフォルトではすべてコメントアウトされた状態の設定ファイルで、たとえオリジナルのファイルに行がなくても新たに入力することでjupyterはしっかり判別してくれます。

設定が完了したらJupyter Labを再起動し、設定が反映されていることを確認します。

あとはExtensioの追加ですが、こちらはお好みで。
自分は以下のページを参考にしています。
https://qiita.com/canonrock16/items/d166c93087a4aafd2db4


以上。

トラブル等なく進んでだいたい30分~1時間くらいでしょうか?
(入れるバージョンやディレクトリさえ間違わなければ)
あとは必要に応じ、pipからライブラリをインストールしましょう。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

モルカーをCycleGANで現実の車っぽくしてみた

PUI PUI モルカー

image.png

毎週火曜に数分のショートアニメが放送されている”PUI PUI モルカー”.

パペットキャラ・アニメとして,愛らしいモルモットの姿をした車『モルカー』の愛嬌と,その裏に存在する人間の愚かさを見事に表現した作品です.

今回,このモルカーと現実の車の画風を入れ替えるとおもしろそうなのでは?と思ったのと,またちょうど試してみたいGANもあったので実験してみました.

CycleGAN

今回使用したのはCycleGANです.
このGANは,ある入力領域(ソースドメイン)$X$から別の領域(ターゲットドメイン)$Y$に画像の変換を行います.
teaser.jpg

ICCV 2017
"Unpaired Image-to-Image Translation using Cycle-Consistent Adversarial Networks"
Jun-Yan Zhu, Taesung Park, Phillip Isola, Alexei A. Efros
Berkeley AI Research (BAIR) laboratory, UC Berkeley

図のように,シマウマの画像をウマに変換したり,モネの絵を実写風に変換したり,その逆変換だったり...と,『画像特有の特徴』を学習し,自動的に変換を行います.

そもそもGANとは?ですが,簡潔に述べると2つの学習モデルがお互いに競い合いながら学習を進めあう,敵対的生成ネットワーク(Generative Adversarial Networks)と呼ばれるニューラルネットワークの一種です.
詳しい説明は省かせていただきます.ググったらわんさか記事が出てくるのでお許しください.

無題.png
上図のように,入力された画像を別の領域に変換するGenerater(図ではG)と,入力された画像がGeneraterが生成した画像か,本当の学習用データかを分類するDiscriminator(図ではD)とが,お互いの出力,評価を基準に学習を進めていく構造となっています.

では,どのように画像の特徴だけをとらえきれるのか?には通常のGANには存在しない三つの評価基準が存在するためです.初学者向けに数式をあまり使わずにシンプルに説明しますが,詳しくは本論文や他の記事を参照してみてください.

評価関数

CycleGANは,3つの損失関数をもち,この損失関数を減らす方向に学習を進めていきます.

1つが妥当性損失(validity).これは通常のGANにもあるように,Generatorが生成した画像がどれくらいDiscriminatorを欺いたか?によって定義されます.

次に復元性損失(reconstruction).これは領域Aから領域Bに変換するGenerator($G_{AB}$)と,それとは逆方向に変換するGenerator($G_{BA}$)を順に適用したとき,どれくらい元の画像に近づくか,によって定義されます.$A$➡$B$➡$A$となるため元の画像の特徴に戻るのは当たり前ですよね.

最後に同一性損失(identity).これは領域Aの画像をGenerator $G_{BA}$に適用したとき,画像がどれだけ変化しないか?によって定義されます.
余談ですが,同一性損失これがなくてもCycleGAN自体は作用するよ~と書いてる記事を多く散見するんですが,これがあるとないとでは生成される画像の質が全然違います.これがないとリンゴとミカン変換するモデルで葉っぱが赤,オレンジ色に変わったりします.

これらの損失関数をもとに,画像の領域変換を行っています.数式で説明してくれ~って方はこちらの記事を参考にしてみてください.

準備

データセットを集めます.今回は車とモルカーの変換ですので,車の画像とモルカーの画像を集めます.

車画像

image.png
Cars Dataset

スタンフォードAI研究所から提供されている自動運転AI学習用の車の外面画像を使わせていただきました.今から君たちにはモルカーになってもらいます.

モルカー画像

37.png

アニメ1~3話までのyoutube見逃し配信から,モルカーが大きく映っている画面をトリミングしてデータセットとし,画像をおよそ100枚ほど集めました.1~3話を50回以上繰り返して視聴して集めたのでその日の夜シロモが夢に出てきました.
また,データオーグメンテーションとして画像の反転処理を施しています.

学習

今回のデータセットの内訳は次のようになっています.

Real Car MarCar
Training Images 140枚 138枚
Test Images 27枚 36枚

全て256*256にリサイズ処理を施しています.

CycleGANの元コードはGithubからクローンし,モルカー変換用に少し変更します.
CycleGAN-tensorflow-2

パラメータは以下の通り.
バッチサイズ...1
epoch数...150
epoch_decay...100
Adamオプティマイザ学習係数…0.0002
$β$...0.5
cycle_loss_weight=10.0
identity_loss_weight=5.0

ほぼデフォルトと変わりませんが,時間の関係上すこしepoch数を減らしての学習となっています.画像枚数が極端に少ないためこの程度でも十分学習は進むとの考えでした.
あとデフォルトでidentity_loss_weightが0に設定されているので,これを5.0に設定.これで同一性も保たれるはずです.

結果

image.png
2000iteration.図は左:元画像 真ん中:CycleGANが領域を変換した画像 右:もう一度変換し元の領域に戻したもの となっています.
Real Carのほうはすでにかなりモルカーの世界観に近づいています.

image.png
10000iteration.色味も大きく変換されています.ただReal Carの背景色も大きく変換されており,車本体以外のところからも特徴を抽出していることがわかります.現に,MarCar画像の背景は現実に即した灰色に変化しています.

まとめ

学習画像が極端に少なかったですがモルカーと現実の変換がうまくできているように感じました.
もう少しアニメの話数が追加されたらその分データセットも追加できるので今後に期待です.
みんなもモルカーを見よう!!(宣伝)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む