hrsk
@hrsk

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

TensorFlowによる2タイプ画像分類についてのご質問

解決したいこと

tf版kerasで写真を sakura であるか、sakura以外であるか という画像認識アプリを作りたく考えております。
その際に下記のようなエラーが発生しました。
解決方法をご教授いただきたく思います。

ファイル構成は
├test.py (当該pythonファイル)
└Data┬sakura-jpg画像
   └others-jpg画像

となっております。

なお、tensorflow初学者で、理解ができていないことが多々あり申し訳ございません。

発生している問題・エラー

ValueError: Input 0 of layer sequential is incompatible with the layer: expected axis -1 of input shape to have value 784 but received input with shape (None, 224, 224, 3)

該当するソースコード

import tensorflow as tf
import glob
import numpy as np
import matplotlib.pyplot as plt

from tensorflow.keras.models import Sequential
from keras.preprocessing.image import ImageDataGenerator, img_to_array, load_img
from keras.layers import Input, Activation, Dropout, Flatten, Dense

X = []
Y = []

BATCH_SIZE=128
NUM_EPOCHS=20


for i in glob.glob('Data/sakura/*.jpg'):
  X.append(img_to_array(load_img(i, grayscale=False, color_mode='rgb', target_size=(224,224))))
  Y.append('sakura')

for i in glob.glob('Data/others/*.jpg'):
  X.append(img_to_array(load_img(i, grayscale=False, color_mode='rgb', target_size=(224,224))))
  Y.append('others')

X = np.array(X)
X = X.astype("float")/255
Y = np.array(Y)

model = Sequential([
    Dense(32, input_dim=784, activation='relu'),
    Dense(2, activation='softmax')
])

model.compile('adam', 'categorical_crossentropy', metrics=['accuracy'])
model.fit(X, Y, batch_size=BATCH_SIZE, epochs=NUM_EPOCHS, validation_split=0.2)

plt.plot(model.history['acc'])
plt.plot(model.history['val_acc'])
plt.title('Model accuracy')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(['Train', 'Test'], loc='upper left')
plt.show()

# Plot training & validation loss values
plt.plot(model.history['loss'])
plt.plot(model.history['val_loss'])
plt.title('Model loss')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(['Train', 'Test'], loc='upper left')
plt.show()
0

1Answer

上記で定義しているモデルの入力層のサイズは784になっています。つまり (28 x 28) ピクセルです。学習した時に入力しようとした画像が (224 x 224 x 3) だったのでエラーになりました。

少しコードを確認したんですが、いくつかの改善点を提案していいですか?

  1. Kerasではなくてtf.kerasを使うのがおすすめです。特にTF2を使っている場合だったら使った方がいいです。

  2. 上でimportしているけど使ってないImageDataGeneratorを使うのおすすめします。学習する時に全ての画像が同じサイズである必要があります。ImageDataGeneratorだと自動的にサイズを変更してくれます。後は、配列で画像を管理しようとするといつかメモリエラーになる可能性があります。今後は、精度を改善したいと思って拡張機能を導入しようと思う時にImageDataGeneratorの拡張機能を設定するだけですぐ使えます。

  3. Xに全ての画像をアペンドした後にそのままモデルに渡そうとしているんですが、本当は学習データをシャフルしないといけません。今の状態だと、最初は桜の画像ばかりをみて、その後はotherの画像を見るんですが、otherを見ている間は桜のことを忘れてしまう可能性があります。

  4. Yのデータはそのまま「sakura」と「other」になっていますが、深層学習モデルは数値の配列(numpyあるいはtensor)しか扱えないので、one-hot-encodingして sakura = [1.0 , 0.0] other = [0.0 , 1.0] のようにエンコーディングしないといけません。

すみません、少し長くなりましたが、学習成功できるといいですね。

2Like

Comments

  1. @hrsk

    Questioner

    ご回答いただき感謝申し上げます。
    明日確認させていただき、再度御礼差し上げられたらと思います。
  2. @hrsk

    Questioner

    @birosjhさま

    ご回答頂きありがとうございます。
    画像サイズと input_dimの数値が合ってないというのは、盲点でした。
    正直、input_dimの784という数値は何なのかと疑問には思っていたのですが、探し切ることができず、助かりました。
    input_dimを 224*224*3 に変更して試してみます。

    ImageDataGenerator については後学でなんとなくは理解できたつもりなのですが、シャッフルということに関しては全く頭になかったのですが、flowでバッチサイズとシャッフルを設定すれば、仰っていることが実装できるのかな、と思っています。(正しいでしょうか...。)

    ラベルデータについてはラベル取得の際に、リストに置き換えるようにして再度作成してみます。 助言いただきありがとうございます。
  3. @hrsk

    input_dimが784になっていたのは、おそらく事例に使われていた数値だと思っています。事例でよく使われているMNISTのディフォルト画像サイズが28x28の白黒イメージなので784で表すことが多いです。

    上記のコードを見れば、画像データがすでにクラスごとにダイレクトリー(/sakura, /others) に分けられているようなので、flow_from_directoryが使えると思っています。ちなみに、この方法にはもう一つのメリットがあって、ダイレクトリ名がラベルになるので、ラベルデータを扱う必要はありません。

Your answer might help someone💌