私はケラを使用して画像セグメンテーション用の畳み込みニューラルネットワークを構築しており、「同じ」パディングの代わりに「反射パディング」を使用したいのですが、ケラでそれを行う方法が見つかりません。
inputs = Input((num_channels, img_rows, img_cols))
conv1=Conv2D(32,3,padding='same',kernel_initializer='he_uniform',data_format='channels_first')(inputs)
反射レイヤーを実装してkerasモデルに挿入する方法はありますか?
解決策を見つけました!レイヤーを入力として受け取る新しいクラスを作成し、tensorflowの事前定義された関数を使用するだけです。
import tensorflow as tf
from keras.engine.topology import Layer
from keras.engine import InputSpec
class ReflectionPadding2D(Layer):
def __init__(self, padding=(1, 1), **kwargs):
self.padding = Tuple(padding)
self.input_spec = [InputSpec(ndim=4)]
super(ReflectionPadding2D, self).__init__(**kwargs)
def get_output_shape_for(self, s):
""" If you are using "channels_last" configuration"""
return (s[0], s[1] + 2 * self.padding[0], s[2] + 2 * self.padding[1], s[3])
def call(self, x, mask=None):
w_pad,h_pad = self.padding
return tf.pad(x, [[0,0], [h_pad,h_pad], [w_pad,w_pad], [0,0] ], 'REFLECT')
# a little Demo
inputs = Input((img_rows, img_cols, num_channels))
padded_inputs= ReflectionPadding2D(padding=(1,1))(inputs)
conv1 = Conv2D(32, 3, padding='valid', kernel_initializer='he_uniform',
data_format='channels_last')(padded_inputs)
上記の受け入れられた答えは、現在のKerasバージョンでは機能しません。動作しているバージョンは次のとおりです。
class ReflectionPadding2D(Layer):
def __init__(self, padding=(1, 1), **kwargs):
self.padding = Tuple(padding)
self.input_spec = [InputSpec(ndim=4)]
super(ReflectionPadding2D, self).__init__(**kwargs)
def compute_output_shape(self, s):
""" If you are using "channels_last" configuration"""
return (s[0], s[1] + 2 * self.padding[0], s[2] + 2 * self.padding[1], s[3])
def call(self, x, mask=None):
w_pad,h_pad = self.padding
return tf.pad(x, [[0,0], [h_pad,h_pad], [w_pad,w_pad], [0,0] ], 'REFLECT')
import tensorflow as tf
from keras.layers import Lambda
inp_padded = Lambda(lambda x: tf.pad(x, [[0,0], [27,27], [27,27], [0,0]], 'REFLECT'))(inp)
Akihikoのソリューションは、新しいkerasバージョンでは機能しなかったため、独自のソリューションを思いつきました。スニペットは、202x202x3画像のバッチを256x256x3にパディングします
未定義の寸法がある場合、受け入れられた答えは機能しません! compute_output_shape関数を呼び出すと、エラーが発生します。これを回避する簡単な方法を次に示します。
class ReflectionPadding2D(Layer):
def __init__(self, padding=(1, 1), **kwargs):
self.padding = Tuple(padding)
self.input_spec = [InputSpec(ndim=4)]
super(ReflectionPadding2D, self).__init__(**kwargs)
def compute_output_shape(self, s):
if s[1] == None:
return (None, None, None, s[3])
return (s[0], s[1] + 2 * self.padding[0], s[2] + 2 * self.padding[1], s[3])
def call(self, x, mask=None):
w_pad, h_pad = self.padding
return tf.pad(x, [[0, 0], [h_pad, h_pad], [w_pad, w_pad], [0, 0]], 'REFLECT')
def get_config(self):
config = super(ReflectionPadding2D, self).get_config()
print(config)
return config
documentation で確認できるように、そのような「reflect」パディングはありません。 「same」と「valid」のみがkerasに実装されています。
自分で実装しようとするか、誰かがすでに実装しているかどうかを確認するかもしれません。 Conv2D
クラスに基づいて、self.padding
メンバー変数が使用されている場所を確認する必要があります。