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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Keras

Kerasは、TheanoやTensorFlow/CNTK対応のラッパーライブラリです。DeepLearningの数学的部分を短いコードでネットワークとして表現することが可能。DeepLearningの最新手法を迅速に試すことができます。

深層学習

深層学習は、多数のレイヤのニューラルネットワークによる機械学習手法。人工知能研究の一つでディープラーニングとも呼ばれています。コンピューター自体がデータの潜在的な特徴を汲み取り、効率的で的確な判断を実現することができます。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

4521閲覧

ResNet50を用いた転移学習モデルで、training時とvalidation/predict時の推論結果が異なる

Hagasuke

総合スコア8

Keras

Kerasは、TheanoやTensorFlow/CNTK対応のラッパーライブラリです。DeepLearningの数学的部分を短いコードでネットワークとして表現することが可能。DeepLearningの最新手法を迅速に試すことができます。

深層学習

深層学習は、多数のレイヤのニューラルネットワークによる機械学習手法。人工知能研究の一つでディープラーニングとも呼ばれています。コンピューター自体がデータの潜在的な特徴を汲み取り、効率的で的確な判断を実現することができます。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/01/22 05:27

編集2020/01/23 02:26

質問内容

ResNet50の転移学習モデルを用いて画像分類を試みています。
ところが、下記のようにtrain時とval, predict時の挙動が異なっており困っております。

  train時:学習が正常に進み、epochごとにlossとaccuracyが改善される
val, predict時:すべての画像を特定の分類として判定する

ちなみに、学習後のモデルを用いて、trainに用いた画像を推論させたところ、
train時の判定精度は約89%だったにもかかわらず、
下記のConfusion Matrix同様に、すべての画像をある特定のラベルと判定していました。

原因についてお心当たりがありましたら、ご教授いただければ幸いです。

追記(修正点と結果)

下記の点、修正いたしました。

①resnet50とfc_modelを削除しない(回答参考) ⇒ 変化なし
②手動でダウンロードしていた重みを自分で作成したフォルダに保存して読み込んでいたが、
"~/.keras/models/"に移動して、'imagenet'で読み込み ⇒ 変化なし
③input_shape = (image_size, image_size, 3)として、input_tensorでなくinput_shapeで指定 ⇒ 変化なし
④別の重みをダウンロードして実行 ⇒ 最新版でないとのメッセージがでたため、元の重みに戻した
⑤転移学習を行わない場合の結果を追記いたしました(画像数とepoch数は異なる)。

問題のスクリプト

python

1# 画像とラベルをtrain, validation, testで分割 2X_train, X_test, y_train, y_test = train_test_split(x_all_data, y_GroundTruth, test_size=0.2, random_state=1) 3X_train, X_val , y_train, y_val = train_test_split(X_train, y_train, test_size=0.2, random_state=1) 4 5y_train = to_categorical(y_train) 6y_val = to_categorical(y_val) 7y_test = to_categorical(y_test) 8 9# ResNet50のロード。 10# FC層は不要なので include_top=False 11# 参照:https://www.pythonmania.work/entry/2019/04/17/154829 12# weightsがダウンロードできないためhttps://github.com/fchollet/deep-learning-models/releases/tag/v0.2 13# にて手動ダウンロード 参照:https://github.com/fchollet/deep-learning-models/issues/33 14input_shape = Input(shape=(image_size, image_size, 3)) 15resnet50 = ResNet50(include_top=False, 16 weights=r'./(ディレクトリ名)/resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5', 17 input_tensor=input_shape) 18 19# FC層の作成 20fc_model = Sequential() 21fc_model.add(Flatten(input_shape=resnet50.output_shape[1:])) 22fc_model.add(Dense(256, activation='relu')) 23fc_model.add(Dropout(0.5)) 24fc_model.add(Dense(8, activation='softmax')) 25 26# ResNet50とFC層を結合してモデルを作成 27resnet50_model = Model(input=resnet50.input, output=fc_model(resnet50.output)) 28 29del resnet50 30del fc_model 31 32gc.collect() 33 34# print(len(resnet50_model.layers)) => 176 35#ResNet50の一部の重みを固定(176階層中の170階層の重み固定) 36for layer in resnet50_model.layers[:170]: 37 layer.trainable = False 38 39 40# 多クラス分類を指定 41resnet50_model.compile(loss='categorical_crossentropy', 42 optimizer=optimizers.SGD(lr=1e-3, momentum=0.9), 43 metrics=['accuracy']) 44 45history = resnet50_model.fit(X_train, y_train, batch_size=8, verbose=1, epochs=10, 46 validation_data=(X_val, y_val)) 47 48 49 50 51# In[ ]: 52# 結果表示 53 54 55 56# accuracyが最小となるときのweightを読み込み 57# model.load_weights('weights.hdf5') 58 59y_pred = resnet50_model.predict(X_test, batch_size=8, verbose=0) 60 61 62y_test_arg = np.argmax(y_test, axis=1) 63y_pred_arg = np.argmax(y_pred, axis=1) 64 65print("Confusion Matrix") 66print(confusion_matrix(y_test_arg, y_pred_arg)) 67 68print('Accuracy: ', accuracy_score(y_test_arg, y_pred_arg)) 69print('F1 Score: ', f1_score(y_test_arg, y_pred_arg,average="macro"))

問題のスクリプトの結果

python

1Train on 775 samples, validate on 194 samples 2Epoch 1/10 3775/775 [==============================] - 43s 56ms/step - loss: 2.8364 - accuracy: 0.6026 - val_loss: 2.1264 - val_accuracy: 0.3041 4Epoch 2/10 5775/775 [==============================] - 26s 34ms/step - loss: 0.9090 - accuracy: 0.7394 - val_loss: 2.0831 - val_accuracy: 0.0567 6Epoch 3/10 7775/775 [==============================] - 27s 34ms/step - loss: 0.7186 - accuracy: 0.7806 - val_loss: 2.0935 - val_accuracy: 0.0567 8Epoch 4/10 9775/775 [==============================] - 27s 34ms/step - loss: 0.6537 - accuracy: 0.8206 - val_loss: 2.3842 - val_accuracy: 0.3041 10Epoch 5/10 11775/775 [==============================] - 26s 34ms/step - loss: 0.7280 - accuracy: 0.8065 - val_loss: 2.1401 - val_accuracy: 0.3041 12Epoch 6/10 13775/775 [==============================] - 26s 34ms/step - loss: 0.5726 - accuracy: 0.8374 - val_loss: 2.0188 - val_accuracy: 0.3093 14Epoch 7/10 15775/775 [==============================] - 26s 34ms/step - loss: 0.5044 - accuracy: 0.8542 - val_loss: 2.1495 - val_accuracy: 0.0361 16Epoch 8/10 17775/775 [==============================] - 27s 35ms/step - loss: 0.5044 - accuracy: 0.8619 - val_loss: 2.1775 - val_accuracy: 0.2990 18Epoch 9/10 19775/775 [==============================] - 27s 34ms/step - loss: 0.5373 - accuracy: 0.8645 - val_loss: 2.1233 - val_accuracy: 0.3041 20Epoch 10/10 21775/775 [==============================] - 27s 34ms/step - loss: 0.4005 - accuracy: 0.8877 - val_loss: 2.0625 - val_accuracy: 0.3041 22 23Confusion Matrix 24[[ 0 0 0 0 2 0 0 0] 25 [ 0 0 0 0 10 0 0 0] 26 [ 0 0 0 0 39 0 0 0] 27 [ 0 0 0 0 65 0 0 0] 28 [ 0 0 0 0 77 0 0 0] 29 [ 0 0 0 0 32 0 0 0] 30 [ 0 0 0 0 7 0 0 0] 31 [ 0 0 0 0 11 0 0 0]] 32 33Accuracy: 0.3168724279835391 34F1 Score: 0.06015625 35 36

成功するスクリプト

python

1# 画像とラベルをtrain, validation, testで分割 2X_train, X_test, y_train, y_test = train_test_split(x_all_data, y_GroundTruth, test_size=0.2, random_state=1) 3X_train, X_val , y_train, y_val = train_test_split(X_train, y_train, test_size=0.2, random_state=1) 4 5y_train = to_categorical(y_train) 6y_val = to_categorical(y_val) 7y_test = to_categorical(y_test) 8 9model = Sequential() 10 11# 入力画像は224 X 224 X 3 12model.add(Conv2D(16, kernel_size=(5, 5),padding='same', activation='relu', 13 kernel_initializer='he_normal', input_shape=(224, 224, 3))) 14model.add(MaxPooling2D(pool_size=(2, 2))) 15model.add(Conv2D(64, kernel_size=(5, 5),padding='same', activation='relu', 16 kernel_initializer='he_normal')) 17model.add(MaxPooling2D(pool_size=(2, 2))) 18model.add(Conv2D(128, kernel_size=(5, 5),padding='same', activation='relu', 19 kernel_initializer='he_normal')) 20model.add(MaxPooling2D(pool_size=(2, 2))) 21 22model.add(Flatten()) 23model.add(Dense(units=512)) 24model.add(Activation('relu')) 25model.add(Dense(units=256)) 26model.add(Activation('relu')) 27model.add(Dense(units=256)) 28model.add(Activation('relu')) 29model.add(Dense(8, activation='softmax')) 30 31model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) 32 33history = model.fit(X_train, y_train, batch_size=8, verbose=1, epochs=15, validation_data=(X_val, y_val)) 34 35 36y_pred = model.predict(X_test, batch_size=8, verbose=0) 37 38y_test_arg = np.argmax(y_test, axis=1) 39y_pred_arg = np.argmax(y_pred, axis=1) 40 41print("Confusion Matrix") 42print(confusion_matrix(y_test_arg, y_pred_arg)) 43 44print('Accuracy: ', accuracy_score(y_test_arg, y_pred_arg)) 45print('F1 Score: ', f1_score(y_test_arg, y_pred_arg,average="macro")) 46

# 成功するスクリプトの結果

python

1Train on 670 samples, validate on 168 samples 2Epoch 1/15 3670/670 [==============================] - 22s 33ms/step - loss: 11.9808 - accuracy: 0.3149 - val_loss: 1.4312 - val_accuracy: 0.3810 4Epoch 2/15 5670/670 [==============================] - 6s 9ms/step - loss: 1.2536 - accuracy: 0.5746 - val_loss: 1.0848 - val_accuracy: 0.6726 6Epoch 3/15 7670/670 [==============================] - 6s 9ms/step - loss: 1.1292 - accuracy: 0.6149 - val_loss: 1.1626 - val_accuracy: 0.6369 8Epoch 4/15 9670/670 [==============================] - 6s 9ms/step - loss: 0.9577 - accuracy: 0.6343 - val_loss: 0.9260 - val_accuracy: 0.6786 10Epoch 5/15 11670/670 [==============================] - 6s 9ms/step - loss: 0.7463 - accuracy: 0.7313 - val_loss: 0.8360 - val_accuracy: 0.6845 12Epoch 6/15 13670/670 [==============================] - 6s 9ms/step - loss: 0.6855 - accuracy: 0.7507 - val_loss: 0.9705 - val_accuracy: 0.7262 14Epoch 7/15 15670/670 [==============================] - 6s 9ms/step - loss: 0.6168 - accuracy: 0.7731 - val_loss: 1.0714 - val_accuracy: 0.7619 16Epoch 8/15 17670/670 [==============================] - 6s 9ms/step - loss: 0.4977 - accuracy: 0.8164 - val_loss: 0.9056 - val_accuracy: 0.6964 18Epoch 9/15 19670/670 [==============================] - 6s 9ms/step - loss: 0.3705 - accuracy: 0.8716 - val_loss: 0.7673 - val_accuracy: 0.7321 20Epoch 10/15 21670/670 [==============================] - 6s 9ms/step - loss: 0.2310 - accuracy: 0.9075 - val_loss: 0.7087 - val_accuracy: 0.7798 22Epoch 11/15 23670/670 [==============================] - 6s 9ms/step - loss: 0.1560 - accuracy: 0.9418 - val_loss: 1.0097 - val_accuracy: 0.7262 24Epoch 12/15 25670/670 [==============================] - 6s 9ms/step - loss: 0.1333 - accuracy: 0.9507 - val_loss: 0.8617 - val_accuracy: 0.8452 26Epoch 13/15 27670/670 [==============================] - 6s 9ms/step - loss: 0.1456 - accuracy: 0.9478 - val_loss: 0.8585 - val_accuracy: 0.7440 28Epoch 14/15 29670/670 [==============================] - 6s 9ms/step - loss: 0.0938 - accuracy: 0.9716 - val_loss: 0.7732 - val_accuracy: 0.7857 30Epoch 15/15 31670/670 [==============================] - 6s 9ms/step - loss: 0.0609 - accuracy: 0.9836 - val_loss: 0.7505 - val_accuracy: 0.8214 32 33Confusion Matrix 34[[ 3 0 0 0 0 0 0] 35 [ 0 1 1 2 0 0 3] 36 [ 0 1 21 7 3 0 1] 37 [ 0 1 11 38 1 8 1] 38 [ 0 0 0 0 83 0 0] 39 [ 0 0 0 1 0 14 0] 40 [ 0 0 3 0 0 0 6]] 41Accuracy: 0.7904761904761904 42F1 Score: 0.6922323858385239

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

train時の判定精度は約89%だったにもかかわらず、

fit() 関数で学習を実行したときのログを見ると、確かに学習データに対する精度が10エポック目で 89% となっていますが、検証データに対する精度は 30% と1エポック目からほとんど変化していません。

loss: 0.4005 - accuracy: 0.8877 - val_loss: 2.0625 - val_accuracy: 0.3041

なので、過学習しており、学習がうまくいっていないと思います。
学習データに対する loss の値及び精度はその値が変化しなくなったことで収束したかどうかの判断には使えますが、汎化性能のあるモデルが学習できたかどうかは val_loss、val_accuracy の値で判断するべきだと思います。

追記

学習済みモデルを使用する際は、学習済みモデルを学習した際と同じ前処理を行う必要があります。keras.applications.resnet50.preprocess_input に (N, H, W, C) のテンソルを渡してください。

python

1from keras.applications.resnet50 import ResNet50, preprocess_input 2 3X_train = preprocess_input(X_train) 4X_test = preprocess_input(X_test)

投稿2020/01/22 05:51

編集2020/01/23 03:00
tiitoi

総合スコア21956

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Hagasuke

2020/01/22 06:38

ご回答いただきありがとうございます。 私も過学習をしているのかと思いましたが、 念のため、下記のように学習したモデルを用いて、 学習に使用したデータ(X_train)の推論を行ってみました。 y_pred = resnet50_model.predict(X_train, batch_size=8, verbose=0) この場合は、accuracy: 0.8877が再現されるはずですが、 推論結果のaccuracyを確認すると0.3程度となっていました。 Confusion Matrixも上記と同様の結果となりました。 なので、過学習ではなく、学習後のモデルが何らかの理由で 正しく推論(val, testともに)できなくなっているのだと思います。
tiitoi

2020/01/22 06:43 編集

X_train に対しても同じ値が出ないということでしょうか。 関係あるかどうかはわからないですが、以下の三行はいらないと思いますので、消してみてはでうでしょうか。 既存のモデルから新しいモデルを作った場合に全く別のオブジェクトとして作成されるわけではないので、resnet50, fc_model を消してしまって問題ないのかわかりません。 del resnet50 del fc_model gc.collect()
Hagasuke

2020/01/22 08:33

> X_train に対しても同じ値が出ないということでしょうか。 はい、X_trainに対してpredictしても再現しません。 > 関係あるかどうかはわからないですが、以下の三行はいらないと思いますので、消してみてはでうでし > ょうか。 > 既存のモデルから新しいモデルを作った場合に全く別のオブジェクトとして作成されるわけではないの > で、resnet50, fc_model を消してしまって問題ないのかわかりません。 > del resnet50 > del fc_model > gc.collect() なるほど、別のオブジェクトとして作成されるわけではないのであれば、 上記が悪さをしている可能性がありますね。 修正して確認してみます。結果が出ましたら、また報告させていただきます。
Hagasuke

2020/01/23 00:06

上記の件、修正して確認してみましたが改善しませんでした。
tiitoi

2020/01/23 02:11 編集

念の為確認しますが、X_train に対しても再現しなかったというときは、fit() のあとの行にある y_test も y_train に、適宜変更しましたか? y_pred = resnet50_model.predict(X_train, batch_size=8, verbose=0) y_train_arg = np.argmax(y_train, axis=1) y_pred_arg = np.argmax(y_pred, axis=1) print("Confusion Matrix") print(confusion_matrix(y_train_arg, y_pred_arg)) print('Accuracy: ', accuracy_score(y_train_arg, y_pred_arg)) print('F1 Score: ', f1_score(y_train_arg, y_pred_arg,average="macro"))
tiitoi

2020/01/23 02:13

こちらにはデータがないため、動かしてデバッグすることはこちらではできないのですが、目視でコードを見た範囲では問題はないように思いました。
Hagasuke

2020/01/23 02:35

ご回答いただきありがとうございます。 手持ちの画像枚数が増えているので同じ条件で再確認することは難しいのですが、 上記のようにy_testもy_trainに変更しておりましたが再現いたしませんでした。 また、転移学習ではなく、手書きのCNNモデルを用いた場合について追記いたしました。 画像数やepoch数は異なりますが、モデルの構造以外は同じものです。 同様の条件でも転移学習を行わなければ問題なく学習ができますので、 入力画像や、分類対象の難しさが原因ではないと考えております。
tiitoi

2020/01/23 03:01

学習データに対しても精度がでないのは謎ですが、コードをよく見たら前処理をやっていませんね。 学習済みモデルを使用する際はその重みが作成された際と同じ前処理を行う必要があり、具体的には keras.applications.resnet50.preprocess_input を使って、学習前に予め全部のデータを変換しておいてください。
Hagasuke

2020/01/23 04:27

スクリプト外でスケーリングは行っておりましたが、 確かに、学習済みモデルを使う場合には、 入力の前処理をそろえていないとまずいですね。 勉強不足でした。修正いたします。
Hagasuke

2020/01/24 04:52

前処理としてpreprocess_inputを用いたところ、 上記の問題は解決いたしました! 数日にわたりご助言いただきありがとうございました。 本当に助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問