こしあん
2019-02-13

転移学習でネットワーク内でアップサンプリングする方法(Keras)


転移学習でインプットのサイズを揃えなければいけないことがありますが、これをRAM(CPU)上でやるとメモリが不足することがあります。転移学習の重みをそのまま使い、事前にアップサンプリングレイヤーを差し込む方法を紹介します。

関連記事とバックグラウンド

まず前提知識としてCPU側でアップサンプリングするとメモリーサイズが2乗のオーダーで増えます。解像度が128は解像度が64の4倍メモリーサイズを使います。これをメモリーに余裕があるネットワーク側でやりたいのです。

以前書いたこの記事とも重なるのですが、基本的にUpsampling2Dレイヤーを使います。以下の方法で独自にUpsamplingを定義してもOKです。

TPUでアップサンプリングする際にエラーを出さない方法
https://blog.shikoan.com/tpu-upsampling/

ただし、新規にモデルを定義する場合はそれでよかったのですが、Functional APIの要領でUpsampling済みのテンソルを差し込むというのが難しくなります。

また私が書いたこの記事の要領で、モデルを再定義し、Upsamplingのレイヤーを差し込むというのもできますが面倒です。

keras.applicationsで指定できた

実はkeras.applicationsの入力にはinput_shapeで(128,128,3)のようにshapeを指定する方法のほかに、input_tensorでKerasのテンソルを指定する方法があります。ここにアップサンプリング済みのテンソルを入れればよいわけです。イメージ的には、

vgg = VGG16(include_top=False, weights="imagenet", input_tensor=x)

このxというのが、アップサンプリング済みのテンソルです。

コード

from keras.layers import UpSampling2D, Input
from keras.applications import VGG16
from keras.applications.imagenet_utils import preprocess_input
from keras.datasets import cifar10
from keras.models import Model

(X_train, y_train), (X_test, y_test) = cifar10.load_data()
input = Input((32,32,3))
x = UpSampling2D(4)(input)
vgg = VGG16(include_top=False, weights="imagenet", input_tensor=x)
model = Model(input, vgg.output)

model.summary()

y_pred = model.predict(preprocess_input(X_test[:16]))
print(y_pred.shape)

summaryを見ると、このようにVGG16に入る前にアップサンプリングされているのが確認できます。

_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
input_1 (InputLayer)         (None, 32, 32, 3)         0
_________________________________________________________________
up_sampling2d_1 (UpSampling2 (None, 128, 128, 3)       0
_________________________________________________________________
block1_conv1 (Conv2D)        (None, 128, 128, 64)      1792
_________________________________________________________________
block1_conv2 (Conv2D)        (None, 128, 128, 64)      36928
_________________________________________________________________
block1_pool (MaxPooling2D)   (None, 64, 64, 64)        0
_________________________________________________________________
~中略~
_________________________________________________________________
block5_pool (MaxPooling2D)   (None, 4, 4, 512)         0
=================================================================
Total params: 14,714,688
Trainable params: 14,714,688
Non-trainable params: 0
_________________________________________________________________

出力のshapeも問題ありません。

(16, 4, 4, 512)

これで堂々とネットワーク内でアップサンプリングできるというわけです。簡単でしたね。

Related Posts

BrestCancerデータセットをCNNで分類する 構造化データを畳み込みニューラルネットワーク(CNN)で分析することを考えます。BrestCancerデータセットはScikit-learnに用意されている、乳がんが良性か悪性かの2種類を分類する典型的な構造化データです。サンプル数569、データの次元30の典型的な構造化データです。 なぜ畳み込...
TPUでも大きなバッチサイズに対して精度を出す... TPUでは大きなバッチサイズを適用することが訓練の高速化につながりますが、これは精度と引き換えになることがあります。大きなバッチサイズでも精度を出す方法を論文をもとに調べてみました。 背景 Qiitaに書いたGoogle Brainの論文「学習率を落とすな、バッチサイズを増やせ」を読むの続き。...
OpenCVで画像を歪ませる方法 PythonでOpenCVを使い画像を歪ませる方法を考えます。アフィン変換というちょっと直感的に理解しにくいことをしますが、慣れればそこまで難しくはありません。ディープラーニングのData Augmentationにも使えます。 OpenCVでのアフィン変換のイメージ アフィン変換というと、ま...
Python(Numpy)で画像を水平反転する方法:Data Augmentation向け... OpenCVを使わずに単純に画像を左右反転(水平反転)する方法を考えます。ディープラーニングでデータのジェネレーターを自分で実装した場合、Data Augmentationを組み込む際にも必要になります。それを見ていきましょう。 左右反転自体は実は簡単 例えばNumpyの行列を左右反転させてみ...
Kerasでメモリ使用量を減らしたかったらmax_queue_sizeを調整しよう... Kerasで大きめの画像を使ったモデルを訓練していると、メモリが足りなくなるということがよくあります。途中処理の変数のデータ型(np.uint8)を変えるのだけではなく、max_queue_sizeの調整をする必要があることがあります。それを見ていきます。 メモリサイズの目安 ニューラルネット...

Add a Comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です