LoginSignup
3
3

More than 5 years have passed since last update.

【再評価】Keras Conv1DのInput Shapeの順番はChannel firstかChannel lastのどちらが正解か?

Last updated at Posted at 2017-04-03

みなさんにコメント何件か頂いたので、再評価してみました。
環境については、前回の記事を参照してください。

.keras.jsonのimage_dim_orderingの設定

PonDadさんからのコメント

image_dim_ordering: 文字列, "tf" か "th" によって、channel_firstかchannel_lastのいずれかになるのではないかとのご指摘です。

data_formatの初期値

Hirofumi Yashimaさんからのコメント

また、Hirofumi Yashimaさんからは、初期化メソッドにて、data_formatはNoneになるのではないかとのご指摘です。

こちらの記事の冒頭 で、以下、
class Conv1D(_Conv) 中、親クラスの初期化メソッド を 呼び出しているところ
に 注目されています が 、

convolutional.py#L233
class Conv1D(_Conv):
.
.
       super(Conv1D, self).__init__(
           rank=1,
           filters=filters,
           kernel_size=kernel_size,
           strides=strides,
           padding=padding,
           data_format='channels_last',

conv1dメソッド を data_format引数に何も渡さず に 呼び出すと、
data_format は デフォルト設定 の data_format=None に 切り替わり、
tf_data_format = 'NCW' に なるのではないでしょうか?

convolutional.py#L233
conv1d(x, kernel, strides=1, padding='valid',
          data_format=None, dilation_rate=1):
   if data_format == 'channels_last':
       tf_data_format = 'NWC'
   else:
       tf_data_format = 'NCW'

評価方法

ソースコードを読んでるより、実際書いてみてdata_formatがどうなっているのかを確認してみました。

確認方法

from keras.models import Model, Sequential
from keras import backend as K
from keras.layers import Input, Conv1D, Flatten, Dense

Using TensorFlow backend.
  • image_dim_orderがthかtfどちらになっているのか確認します。
K.image_dim_ordering()
'tf'

tfですね。

  • 次は、image_data_formatがchannels_firstかchannels_lastどちらになっているのかを確認します。
K.image_data_format()

'channels_last'

channels_lastですね。

  • image_dim_orderをthに変えて、image_dim_orderingとimage_data_formatを確認します。
K.set_image_dim_ordering('th')

K.image_dim_ordering()
    'th'

K.image_data_format()
'channels_first'

channels_firstになっています。

DATA_SAMPLES = 20
CHANNELS = 1
DATA_LENGTH = 10
KERNEL_SIZE = 3
FILTERS = 50
  • Modelクラスのget_configでdata_formatが拾えないか見てみたのですが、以下の通り、data_formatを削除しているようでした。

convolutional.py#L336

    def get_config(self):
        config = super(Conv1D, self).get_config()
        config.pop('rank')
        config.pop('data_format')
        return config
  • そこで、Conv1Dを基底クラスとして、ラッパークラス作って、そのラッパークラスを呼び出すとき、data_formatを表示してやり、さらに、get_configを返す際、data_formatを削除しないようにしてみました。
class Conv1D_test(Conv1D):
    def get_config(self):
            config = super(Conv1D, self).get_config()
            #config.pop('rank')
            #config.pop('data_format')
            return config

    def call(self, inputs):
        print(self.data_format)
        outputs = Conv1D.call(self, inputs)
        print(self.data_format)
        return outputs
shape=(None, DATA_LENGTH, CHANNELS)

input_layer = Input(batch_shape=shape)
conv_1d_output_layer = Conv1D_test(FILTERS, KERNEL_SIZE, padding='same')(input_layer)
flatten_output_layer = Flatten()(conv_1d_output_layer)
prediction_result = Dense(1)(flatten_output_layer)
model = Model(inputs=input_layer, outputs=prediction_result)

    channels_last
    channels_last

となり、data_formatはK.set_image_dim_orderingに関わらず、channels_lastとなっています。
また、get_configの結果についても、「'data_format': 'channels_last'」となっています。

model.get_config()
{'input_layers': [['input_1', 0, 0]],
 'layers': [{'class_name': 'InputLayer',
   'config': {'batch_input_shape': (None, 10, 1),
    'dtype': 'float32',
    'name': 'input_1',
    'sparse': False},
   'inbound_nodes': [],
   'name': 'input_1'},
  {'class_name': 'Conv1D_test',
   'config': {'activation': 'linear',
    'activity_regularizer': None,
    'bias_constraint': None,
    'bias_initializer': {'class_name': 'Zeros', 'config': {}},
    'bias_regularizer': None,
    'data_format': 'channels_last',
    'dilation_rate': (1,),
    'filters': 50,
    'kernel_constraint': None,
    'kernel_initializer': {'class_name': 'VarianceScaling',
     'config': {'distribution': 'uniform',
      'mode': 'fan_avg',
      'scale': 1.0,
      'seed': None}},
    'kernel_regularizer': None,
    'kernel_size': (3,),
    'name': 'conv1d_test_1',
    'padding': 'same',
    'rank': 1,
    'strides': (1,),
    'trainable': True,
    'use_bias': True},
   'inbound_nodes': [[['input_1', 0, 0, {}]]],
   'name': 'conv1d_test_1'},
  {'class_name': 'Flatten',
   'config': {'name': 'flatten_1', 'trainable': True},
   'inbound_nodes': [[['conv1d_test_1', 0, 0, {}]]],
   'name': 'flatten_1'},
  {'class_name': 'Dense',
   'config': {'activation': 'linear',
    'activity_regularizer': None,
    'bias_constraint': None,
    'bias_initializer': {'class_name': 'Zeros', 'config': {}},
    'bias_regularizer': None,
    'kernel_constraint': None,
    'kernel_initializer': {'class_name': 'VarianceScaling',
     'config': {'distribution': 'uniform',
      'mode': 'fan_avg',
      'scale': 1.0,
      'seed': None}},
    'kernel_regularizer': None,
    'name': 'dense_1',
    'trainable': True,
    'units': 1,
    'use_bias': True},
   'inbound_nodes': [[['flatten_1', 0, 0, {}]]],
   'name': 'dense_1'}],
 'name': 'model_1',
 'output_layers': [['dense_1', 0, 0]]}

結論

ということで、Conv1Dの場合、image_dim_orderに関わらず、input shapeはchannel lastで設定するということになるのではないかと思います。
ただし、これはKeras 2.0の場合でKeras 1系については確認しておりません。

3
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3