- 投稿日:2021-02-13T20:39:33+09:00
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()凝った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")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これで実際に動かしてみると、下記画像が得られました。
右上の画像と前項での画像が同じになっているのでうまく動いていそうです。まとめ
tensorflowの前処理で、自身がよく知っているnumpyのFFTを使いたいとか、画像処理の定番のopenCVを使いたいとか、そういうことのTipsでした。py_functionはもっと奥深い機能だと思いますが、こんなふうにも使えるんですね。
- 投稿日:2021-02-13T18:36:37+09:00
tensorflow-gpuをRTX3070で動かすのは大変だった
概略
TensorFlow公式ページ(https://www.tensorflow.org/install/gpu) に従ってGPU版を導入するもうまく動作しなかった。
↓
ファイル名の書き換えで動作することを確認。RTX30シリーズで頻発している様子。
今回の対応はかなり応急処置的なので改善待ちですね・・・。環境
OS
Windows 10 Home(64bit)
バージョン : 20H2CPU
Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz 2.90 GHzGPU
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/gpucuda - 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-3070nvidia cudaセットアップ - Qiita
https://qiita.com/mailstop/items/a84ac6b4eac8d12ba488tensorflow-nightly-gpu looking for cusolver64_10.dll on a cuDNN 11.1 installation · Issue #44291 · tensorflow/tensorflow
https://github.com/tensorflow/tensorflow/issues/44291RTX 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/
- 投稿日:2021-02-13T14:01:55+09:00
とりあえず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)を選択。
- 基本的にインストーラーに従うだけで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
今回はtensorflow-2.4.xをインストールします。
念のため一度tensorflow周りのアンインストールを実行してから再度インストールを行います。pip uninstall -y tensorflow tensorflow-cpu tensorflow-gpu tensorflow_datasets tensorflow-hub keraspip 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-notesVisual Studio Installerでは「C++ Build Tools」にチェックを入れておきます。
これだけで6GBくらい容量食います……。
CUDAのインストール
前述の通り、指定のバージョンをインストールしましょう。
https://developer.nvidia.com/cuda-toolkit-archiveCUDA Toolkit 11.0 Update1 (Aug 2020)を選択します。
プラットフォームの入力が求められるので、Windows→x86_64→10と選択します。
Installer Typeはどちらでも構いません。
インストール時の設定は基本的に規定値のままでOKです。
ドライバのコンポーネントを指定する場面がありますが、ここは「CUDA」のみチェックすれば大丈夫。バージョンの確認方法
コマンドプロンプトを起動し、以下のコマンドを実行。
nvcc -V nvcc念のためパスが通っているかも見ておくとよいでしょう。
cuDNNのインストール
同じく指定のバージョンをインストールしましょう。
とか言っておきながら、自分がインストールしたのはcuDNN 8.1でした。が、しっかり動いています。
CUDAがtensorflowのバージョンに依存し、cuDNNは対応するCUDAのバージョンが重要とかなのでしょうか?
https://developer.nvidia.com/cudnn-download-surveycuDNNのダウンロードにはNVIDIAのDeveloper Program Membershipに参加する必要があります。
アカウントを持っていない方は作成してください。必要なcuDNNのバージョンを選択し、.zipファイルのダウンロードを行います。
解凍後は以下のディレクトリが構成されています。
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())"これで一山超えました。
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からライブラリをインストールしましょう。
- 投稿日:2021-02-13T01:08:40+09:00
モルカーをCycleGANで現実の車っぽくしてみた
PUI PUI モルカー
毎週火曜に数分のショートアニメが放送されている”PUI PUI モルカー”.
パペットキャラ・アニメとして,愛らしいモルモットの姿をした車『モルカー』の愛嬌
と,その裏に存在する人間の愚かさを見事に表現した作品です.2月14日は #バレンタインデー ?
— PUI PUI モルカー【公式】 (@molcar_anime) February 12, 2021
チョコ?ポテト?シロモ?のバレンタインカードをプレゼント!
チョコレートに沿えるもよし、メッセージを書き込むもよし。ぜひ、週末のバレンタインにご活用ください?
#モルカー pic.twitter.com/qXMjUs90Oa今回,このモルカーと現実の車の画風を入れ替えるとおもしろそうなのでは?と思ったのと,またちょうど試してみたいGANもあったので実験してみました.
CycleGAN
今回使用したのはCycleGANです.
このGANは,ある入力領域(ソースドメイン)$X$から別の領域(ターゲットドメイン)$Y$に画像の変換を行います.
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)と呼ばれるニューラルネットワークの一種です.
詳しい説明は省かせていただきます.ググったらわんさか記事が出てくるのでお許しください.
上図のように,入力された画像を別の領域に変換する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自体は作用するよ~と書いてる記事を多く散見するんですが,これがあるとないとでは生成される画像の質が全然違います.これがないとリンゴとミカン変換するモデルで葉っぱが赤,オレンジ色に変わったりします.これらの損失関数をもとに,画像の領域変換を行っています.数式で説明してくれ~って方はこちらの記事を参考にしてみてください.
準備
データセットを集めます.今回は車とモルカーの変換ですので,車の画像とモルカーの画像を集めます.
車画像
スタンフォードAI研究所から提供されている自動運転AI学習用の車の外面画像を使わせていただきました.今から君たちにはモルカーになってもらいます.
モルカー画像
アニメ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に設定.これで同一性も保たれるはずです.結果
2000iteration.図は左:元画像 真ん中:CycleGANが領域を変換した画像 右:もう一度変換し元の領域に戻したもの となっています.
Real Carのほうはすでにかなりモルカーの世界観に近づいています.
10000iteration.色味も大きく変換されています.ただReal Carの背景色も大きく変換されており,車本体以外のところからも特徴を抽出していることがわかります.現に,MarCar画像の背景は現実に即した灰色に変化しています.まとめ
学習画像が極端に少なかったですがモルカーと現実の変換がうまくできているように感じました.
もう少しアニメの話数が追加されたらその分データセットも追加できるので今後に期待です.
みんなもモルカーを見よう!!(宣伝)