前提・実現したいこと
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
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/12/09 12:49