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

みなさんにコメント何件か頂いたので、再評価してみました。
環境については、[前回の記事](http://qiita.com/anafou/items/7c4d57a70efb42d105a5)を参照してください。


# .keras.jsonのimage_dim_orderingの設定
[PonDadさんからのコメント](http://qiita.com/anafou/items/7c4d57a70efb42d105a5#comment-e8d87d46941821a34162)

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

# data_formatの初期値
[Hirofumi Yashimaさんからのコメント](http://qiita.com/anafou/items/7c4d57a70efb42d105a5#comment-e5ecdad08fb137899ce9)

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

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

>```python: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' に なるのではないでしょうか？

>>```python: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がどうなっているのかを確認してみました。

# 確認方法



```python
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どちらになっているのか確認します。

```python
K.image_dim_ordering()
'tf'
```
tfですね。

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

```python
K.image_data_format()

'channels_last'
```

channels_lastですね。

- image_dim_orderをthに変えて、image_dim_orderingとimage_data_formatを確認します。

```python
K.set_image_dim_ordering('th')

K.image_dim_ordering()
    'th'

K.image_data_format()
'channels_first'
```

channels_firstになっています。



```python
DATA_SAMPLES = 20
CHANNELS = 1
DATA_LENGTH = 10
KERNEL_SIZE = 3
FILTERS = 50
```

- Modelクラスのget_configでdata_formatが拾えないか見てみたのですが、以下の通り、data_formatを削除しているようでした。

[convolutional.py#L336](https://github.com/fchollet/keras/blob/master/keras/layers/convolutional.py#L336)

```python
    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を削除しないようにしてみました。

```python
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
```


```python
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'」となっています。

```python
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系については確認しておりません。