質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.03%

kerasのCNNで「入力次元が間違っている」というエラーが出る

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 1,188

score 5

前提・実現したいこと

Kerasを用いてCNNを実装しようとしています。
RGBAのような4チャンネルの画像データを読み込ませて学習させることを検討しています。最終的にResNetのネットワーク構造で利用したいので、kerasのfunctional APIで実装しています。

手始めにダミーデータを作成し、作成したネットワークで読み込めるか試している最中に以下のエラーメッセージが発生しました。

発生している問題・エラーメッセージ

x_train.shape = (7, 8, 8, 4)
<class 'tensorflow.python.framework.ops.Tensor'>
input.shape = (None, 8, 8, 4)


---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-15-a964a900b16c> in <module>()
     47 model = ResNet(img_rows,img_cols,img_channels, x_train)
     48 #model = ResNet(32, 32, 3, x_train)
---> 49 history = model.fit(x_train, y_train, batch_size=2, epochs=20, validation_data = (x_test, y_test), verbose = 0)
     50 
     51 # モデルをプロット

~\AppData\Roaming\Python\Python37\site-packages\keras\engine\training.py in fit(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_freq, max_queue_size, workers, use_multiprocessing, **kwargs)
   1152             sample_weight=sample_weight,
   1153             class_weight=class_weight,
-> 1154             batch_size=batch_size)
   1155 
   1156         # Prepare validation data.

~\AppData\Roaming\Python\Python37\site-packages\keras\engine\training.py in _standardize_user_data(self, x, y, sample_weight, class_weight, check_array_lengths, batch_size)
    619                 feed_output_shapes,
    620                 check_batch_axis=False,  # Don't enforce the batch size.
--> 621                 exception_prefix='target')
    622 
    623             # Generate sample-wise weight values given the `sample_weight` and

~\AppData\Roaming\Python\Python37\site-packages\keras\engine\training_utils.py in standardize_input_data(data, names, shapes, check_batch_axis, exception_prefix)
    133                         ': expected ' + names[i] + ' to have ' +
    134                         str(len(shape)) + ' dimensions, but got array '
--> 135                         'with shape ' + str(data_shape))
    136                 if not check_batch_axis:
    137                     data_shape = data_shape[1:]

ValueError: Error when checking target: expected dense_10 to have 4 dimensions, but got array with shape (7, 8, 8)

エラーの内容は「dense層に与えられる入力の形状は4次元のはずなのに、君は(7,8,8)の3次元で渡してるからダメだよ!」とのことです。この(7,8,8)は(バッチサイズ,画像の行数,画像の列数)です。正常に動作させるには、(バッチサイズ,画像の行数,画像の列数,チャンネル数)の4次元が必要だと思われます。

該当のソースコード

ネットワーク構成部とダミーデータ作成部で構成しています。

ネットワーク構成部(エラー箇所確認のため、中間層をコメントアウトしています)

#~ResNetモデル構築~
from keras.layers import Dense, Dropout, Activation, Flatten, Input, add
from keras.layers import Conv2D
from keras.layers.normalization import BatchNormalization
from keras import Model
from keras import optimizers
import numpy as np

def rescell(data, filters, kernel_size):
    strides=(1,1)
    x=Conv2D(filters=filters,kernel_size=kernel_size,strides=strides,padding="same")(data)
    x=BatchNormalization()(x)
    x=Activation('relu')(x)

    data=Conv2D(filters=int(x.shape[3]), kernel_size=(1,1), strides=strides, padding="same")(data)
    x=Conv2D(filters=filters,kernel_size=kernel_size,strides=(1,1),padding="same")(x)
    x=BatchNormalization()(x)
    x=add([x,data])
    x=Activation('relu')(x)
    return x

def ResNet(img_rows, img_cols, img_channels, x_train):
    #inputs=Input(batch_shape=(None,img_rows,img_cols,img_channels))
    inputs = Input(shape=x_train.shape[1:])
    '''
    x=Conv2D(filters=256, kernel_size(3,3), padding="same", input_shape=x_train.shape[1:],activation="relu")(input)
    x=MaxPooling2D(pool_size=(2,2))(x)
    '''
    #print(type(inputs))
    #aaaaaaaaaaaaaaaaaaaaaaaaaa
    #第1層
    #'''
    print("input.shape = " + str(inputs.shape))
    #'''
    #メモ:input_shapeはbatch_sizeを含まない
    #input= np.expand_dims(input, axis=0)
    #Conv2D は (BatchSize, Height, Width, Channels)の4次元入力を期待している????????????
    #メモ:層の引数input_shapeは1データの形状を記述するので、画像を入れるなら3次元(行、列、チャンネル)の表記にする。
    #    ただし、実際に渡すデータは4次元の(バッチサイズ、行、列、チャンネル)である必要がある。
    x=Conv2D(filters=256, kernel_size=(3,3), padding="same", input_shape=(img_rows,img_cols,img_channels))(inputs)
    '''
    x=BatchNormalization()(x)
    x=Activation('relu')(x)

    #第2~39層
    for i in range(19):
        x=rescell(x,256,(3,3))

    #次の1手予測部第1層
    x=Conv2D(filters=2, kernel_size=(1,1), padding="same")(x)
    x=BatchNormalization()(x)
    x=Activation('relu')(x)

    #次の1手予測部第2層
    x=Flatten()(x) #1次元に整形
    '''
    x=Dense(units=8*8, kernel_initializer="he_normal", activation="softmax")(x) #全結合層 

    model=Model(inputs=inputs,outputs=[x])
    #model.compile(loss="softmax_cross_entropy_with_logits", optimizer=SGD(lr=self.learning_rate, momentum = config.MOMENTUM))
    adam = optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False)
    model.compile(loss='categorical_crossentropy', optimizer=adam)
    return model

ダミーデータ作成部

import numpy as np
from sklearn.model_selection import train_test_split

#ダミーデータ作成
data_n = 10             #学習データの数
img_rows = 8            #画像の行数
img_cols = 8            #画像の列数
img_channels = 4        #画像のチャンネル数

data_x = []
data_y = []
for i in range(data_n):
    row_x = []
    row_y = []
    for j in range(img_rows):
        col_x = []
        col_y = []
        for k in range(img_cols):
            channel_x = []
            for l in range(img_channels):
                channel_x.append(1)
            col_x.append(channel_x)
            col_y.append(1)
        row_x.append(col_x)
        row_y.append(col_y)
    data_x.append(row_x)
    data_y.append(row_y)
#data_x = np.expand_dims(np.array(data_x), axis=-1)
#data_y = np.expand_dims(np.array(data_y), axis=-1)
x_train = np.array(data_x)
y_train = np.array(data_y)

x_train, x_test, y_train, y_test = train_test_split(x_train, y_train, test_size=0.30)

print("x_train.shape = "+str(x_train.shape))
model = ResNet(img_rows,img_cols,img_channels, x_train)
history = model.fit(x_train, y_train, batch_size=2, epochs=20, validation_data = (x_test, y_test), verbose = 0)

試したこと

・エラーの発生しているDense層をコメントアウトして実行しました。
結果:Conv2d層で同様のエラーが出た。
→エラーの原因はConv2dに入力されるinputsにある?

・kerasでCNNを実装するときの入力形状について調べました。Conv2D()の引数として指定するinput_shapeにはバッチサイズは含めないこと。例えば50000枚の32*32サイズのRGB画像を読み込ませたいなら、input_shape=(32,32,3)と記述する。ネットワーク構成部のConv2Dではinput_shape=(img_rows,img_cols,img_channels)を指定しているので、ここの形状指定ミスではないと思われます。

・inputs形状を出力してみました。比較用に訓練データの形状も出力しました。エラーメッセージの冒頭部分に出力されているように、inputsの形状は(None, 8, 8, 4)となりバッチサイズがNoneになっています。ここが原因でしょうか?

・訓練データを拡張しようとしました。ダミーデータ作成部のdata_x = np.expand_dims(np.array(data_x), axis=-1)のコメントアウトを外した状態にしました。これで実行した結果、以下のようなエラーが出ました。

x_train.shape = (7, 8, 8, 4, 1)
<class 'tensorflow.python.framework.ops.Tensor'>
input.shape = (None, 8, 8, 4, 1)


---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-16-ad9f21bd03c9> in <module>()
     45 print("x_train.shape = "+str(x_train.shape))
     46 #print(x_train[1])
---> 47 model = ResNet(img_rows,img_cols,img_channels, x_train)
     48 #model = ResNet(32, 32, 3, x_train)
     49 history = model.fit(x_train, y_train, batch_size=2, epochs=20, validation_data = (x_test, y_test), verbose = 0)

<ipython-input-14-05129b474cf2> in ResNet(img_rows, img_cols, img_channels, x_train)
     38     #メモ:層の引数input_shapeは1データの形状を記述するので、画像を入れるなら3次元(行、列、チャンネル)の表記にする。
     39     #    ただし、実際に渡すデータは4次元の(バッチサイズ、行、列、チャンネル)である必要がある。
---> 40     x=Conv2D(filters=256, kernel_size=(3,3), padding="same", input_shape=(img_rows,img_cols,img_channels))(inputs)
     41     '''
     42     x=BatchNormalization()(x)

~\AppData\Roaming\Python\Python37\site-packages\keras\backend\tensorflow_backend.py in symbolic_fn_wrapper(*args, **kwargs)
     73         if _SYMBOLIC_SCOPE.value:
     74             with get_graph().as_default():
---> 75                 return func(*args, **kwargs)
     76         else:
     77             return func(*args, **kwargs)

~\AppData\Roaming\Python\Python37\site-packages\keras\engine\base_layer.py in __call__(self, inputs, **kwargs)
    444                 # Raise exceptions in case the input is not compatible
    445                 # with the input_spec specified in the layer constructor.
--> 446                 self.assert_input_compatibility(inputs)
    447 
    448                 # Collect input shapes to build layer.

~\AppData\Roaming\Python\Python37\site-packages\keras\engine\base_layer.py in assert_input_compatibility(self, inputs)
    340                                      self.name + ': expected ndim=' +
    341                                      str(spec.ndim) + ', found ndim=' +
--> 342                                      str(K.ndim(x)))
    343             if spec.max_ndim is not None:
    344                 ndim = K.ndim(x)

ValueError: Input 0 is incompatible with layer conv2d_11: expected ndim=4, found ndim=5


今度は「Input層は4次元データが欲しいのに5次元データが入力されているよ」と言われました。

以上をまとめますと、データを5次元にするとInput層から大きすぎと文句を言われ、4次元にするとConv2d層から小さすぎると文句を言われて困っている状況です。

よろしくお願いいたします。

補足情報(FW/ツールのバージョンなど)

開発環境:jupyter notebook
使用言語:python 3.7
使用ライブラリ:keras 2.3.1

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

y_trainの次元が3になってました。ダミーデータを作るのでしたらnumpy.randomが便利です。

data_n = 10
img_rows = 8
img_cols = 8
img_channels = 4
img_channels_out = 64  # 今、ネットワークを途中で切っているので出力のチャネルが4でないのに注意

# 形状を指定してランダムなデータを生成
x_train = np.random.rand(data_n, img_rows, img_cols, img_channels)
y_train = np.random.rand(data_n, img_rows, img_cols, img_channels_out)

# ここから下は同じ
x_train, x_test, y_train, y_test = train_test_split(x_train, y_train, test_size=0.30)
model = ResNet(img_rows, img_cols, img_channels, x_train)
model.summary()
history = model.fit(
    x_train,
    y_train,
    batch_size=2,
    epochs=20,
    validation_data=(x_test, y_test),
    verbose=0,
)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/12/09 21:49

    回答ありがとうございます。そして返信が遅くなって申し訳ありません。
    Yhayaさんのコードを参考に修正した結果、「ValueError: Error when checking target: expected dense_10 to have 4 dimensions, but got array with shape (7, 8, 8)」のようなエラーはなくなりました。ありがとうございます。

    しかし、新たに「ValueError: None values not supported.」というエラーが出てしまい、こちらもいろいろ調べたのですが解決できず、また文章も長くなってしまったので、新たに質問させていただきました。以下にURLを置いておきます。
    https://teratail.com/questions/228395?modal=q-comp

    今回の質問についてはYhayaさんをベストアンサーとし、示させていただこうと思います。ありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.03%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る