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

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

新規登録して質問してみよう
ただいま回答率
85.46%
CNN (Convolutional Neural Network)

CNN (Convolutional Neural Network)は、全結合層のみではなく畳み込み層とプーリング層で構成されるニューラルネットワークです。画像認識において優れた性能を持ち、畳み込みニューラルネットワークとも呼ばれています。

Python

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

学習法

プログラミングやITエンジニアの学習法に関する質問を投稿する際にご使用ください。

Q&A

解決済

1回答

262閲覧

CNN学習 モバイルネットV3をもとにファインチューニングを行い二値分類で正解画像と不正解画像を分類するモデルを作りたいが、学習がうまくいかない。検証データが一定になる

kains

総合スコア1

CNN (Convolutional Neural Network)

CNN (Convolutional Neural Network)は、全結合層のみではなく畳み込み層とプーリング層で構成されるニューラルネットワークです。画像認識において優れた性能を持ち、畳み込みニューラルネットワークとも呼ばれています。

Python

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

学習法

プログラミングやITエンジニアの学習法に関する質問を投稿する際にご使用ください。

0グッド

0クリップ

投稿2024/01/15 11:02

編集2024/01/15 11:10

モバイルネットV3で二値分類を使った学習についてです。
ファインチューニングもしているのですが、以下のコードです。

python

1import os 2import pandas as pd 3from sklearn.model_selection import train_test_split 4from tensorflow.keras.preprocessing.image import ImageDataGenerator 5from tensorflow.keras.applications import MobileNetV3Small 6from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint 7import matplotlib.pyplot as plt 8import tensorflow as tf 9 10# ハイパーパラメータ 11image_size = (224, 224) 12batch_size = 32 13learning_rate = 0.0001 14epochs = 100 15fine_tune_at = -5 16 17# データセットを格納するディレクトリへのパス 18base_dir = 'C:/Users/admin/Documents/CNN_224/' 19 20# 訓練データセット、検証データセットを配置するディレクトリ 21positive_path = os.path.join(base_dir, 'cnn_a') 22negative_path = os.path.join(base_dir, 'cnn_n') 23 24# train_set.filenamesからファイルパスを取得 25positive_files = [os.path.join(positive_path, filename) for filename in os.listdir(positive_path)] 26negative_files = [os.path.join(negative_path, filename) for filename in os.listdir(negative_path)] 27 28# データフレームを作成 29positive_df = pd.DataFrame({'filepath': positive_files, 'class': 'positive'}) 30negative_df = pd.DataFrame({'filepath': negative_files, 'class': 'negative'}) 31df = pd.concat([positive_df, negative_df], ignore_index=True) 32 33# 訓練データと検証データに分割 34train_df, test_df = train_test_split(df, test_size=0.2, random_state=42) 35 36# データの前処理とデータ拡張 37train_datagen = ImageDataGenerator(rescale=1./255, shear_range=0.8, zoom_range=0.8, horizontal_flip=True) 38test_datagen = ImageDataGenerator(rescale=1./255) 39 40# データを読み込むためのジェネレータを作成 41train_set = train_datagen.flow_from_dataframe(train_df, x_col='filepath', y_col='class', target_size=image_size, batch_size=batch_size, class_mode='binary') 42test_set = test_datagen.flow_from_dataframe(test_df, x_col='filepath', y_col='class', target_size=image_size, batch_size=batch_size, class_mode='binary') 43 44# モデルの構築 45base_model = MobileNetV3Small(weights='imagenet', include_top=False, input_shape=(*image_size, 3)) 46 47# 最後のブロックの一部の層を解凍 48for layer in base_model.layers[:fine_tune_at]: 49 layer.trainable = False 50 51# モデルに新しい出力層を追加 52model = tf.keras.Sequential([ 53 base_model, 54 tf.keras.layers.GlobalAveragePooling2D(), 55 tf.keras.layers.Dense(1, activation='sigmoid') 56]) 57 58# モデルのコンパイル 59model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=learning_rate), 60 loss='binary_crossentropy', 61 metrics=['accuracy']) 62 63# EarlyStoppingとModelCheckpointのパラメータ変更例 64early_stopping = EarlyStopping(monitor='val_loss', patience=2, restore_best_weights=True) 65model_checkpoint = ModelCheckpoint('best_model.h5', save_best_only=True, monitor='val_accuracy') 66 67# モデルの概要表示 68model.summary() 69 70# モデルのトレーニング 71history = model.fit(train_set, epochs=epochs, validation_data=test_set, callbacks=[early_stopping, model_checkpoint]) 72 73# モデルの保存先パス 74model_save_path = 'C:/Users/admin/Documents/CNN_224/a1.keras' 75 76# モデルの保存 77model.save(model_save_path) 78 79# 訓練損失と検証損失のグラフ 80plt.figure(figsize=(12, 5)) 81 82# 訓練精度と検証精度のグラフ 83plt.subplot(1, 2, 1) 84plt.plot(history.history['accuracy'], label='Train Accuracy') 85plt.plot(history.history['val_accuracy'], label='Validation Accuracy') 86plt.xlabel('Epoch') 87plt.ylabel('Accuracy') 88plt.ylim(0, 1) 89plt.legend() 90 91# 訓練損失と検証損失のグラフ 92plt.subplot(1, 2, 2) 93plt.plot(history.history['loss'], label='Train Loss') 94plt.plot(history.history['val_loss'], label='Validation Loss') 95plt.xlabel('Epoch') 96plt.ylabel('Loss') 97plt.ylim(0, 1) # Y座標は0から1まで 98plt.legend() 99 100# グラフ上に数値を表示 101print(f"最終訓練精度: {history.history['accuracy'][-1]:.4f}") 102print(f"最終検証精度: {history.history['val_accuracy'][-1]:.4f}") 103print(f"最終訓練損失: {history.history['loss'][-1]:.4f}") 104print(f"最終検証損失: {history.history['val_loss'][-1]:.4f}") 105 106plt.tight_layout() 107plt.show()

●実行結果●

Found 3200 validated image filenames belonging to 2 classes.
Found 800 validated image filenames belonging to 2 classes.
Model: "sequential_71"


Layer (type) Output Shape Param #

MobilenetV3small (Function (None, 7, 7, 576) 939120
al)

global_average_pooling2d_7 (None, 576) 0
0 (GlobalAveragePooling2D)

dense_94 (Dense) (None, 1) 577

=================================================================
Total params: 939697 (3.58 MB)
Trainable params: 112513 (439.50 KB)
Non-trainable params: 827184 (3.16 MB)


Epoch 1/100
100/100 [==============================] - ETA: 0s - loss: 0.6889 - accuracy: 0.5731
100/100 [==============================] - 80s 729ms/step - loss: 0.6889 - accuracy: 0.5731 - val_loss: 0.7155 - val_accuracy: 0.5275
Epoch 2/100
100/100 [==============================] - 66s 662ms/step - loss: 0.6816 - accuracy: 0.6153 - val_loss: 0.7061 - val_accuracy: 0.5275
Epoch 3/100
100/100 [==============================] - 68s 680ms/step - loss: 0.6662 - accuracy: 0.7319 - val_loss: 0.7009 - val_accuracy: 0.5275
Epoch 4/100
100/100 [==============================] - 67s 665ms/step - loss: 0.6411 - accuracy: 0.7066 - val_loss: 0.6971 - val_accuracy: 0.5275
Epoch 5/100
100/100 [==============================] - 65s 649ms/step - loss: 0.5886 - accuracy: 0.8319 - val_loss: 0.6939 - val_accuracy: 0.5275
Epoch 6/100
100/100 [==============================] - 67s 664ms/step - loss: 0.5381 - accuracy: 0.8397 - val_loss: 0.6931 - val_accuracy: 0.5275
Epoch 7/100
100/100 [==============================] - 66s 657ms/step - loss: 0.4948 - accuracy: 0.8697 - val_loss: 0.6923 - val_accuracy: 0.5275
Epoch 8/100
100/100 [==============================] - 64s 644ms/step - loss: 0.4434 - accuracy: 0.8844 - val_loss: 0.6918 - val_accuracy: 0.5275
Epoch 9/100
100/100 [==============================] - 65s 649ms/step - loss: 0.3913 - accuracy: 0.8994 - val_loss: 0.6923 - val_accuracy: 0.5275
Epoch 10/100
100/100 [==============================] - 68s 682ms/step - loss: 0.3495 - accuracy: 0.9106 - val_loss: 0.6930 - val_accuracy: 0.5275
最終訓練精度: 0.9106
最終検証精度: 0.5275
最終訓練損失: 0.3495
最終検証損失: 0.6930
イメージ説明

このように出たのですが、最終的には訓練データは悪くない結果なのですが、val_lossと val_accuracyが一定になってしまいます。これは何が足りないのでしょうか?学習率、学習回数、ファインチューニングの層(最後のブロックの一部の層を解凍)の設定などいろいろしても何も変化がありません。

もしかしたらプログラミングが間違っている可能性が高いです。自分がやりたいのはモバイルネットV3を使ってファインチューニングして二値分類(正解画像と不正解画像を分類する)モデルを作りたいと考えています。誤差関数は二値交差エントロピーで出力層の出力関数はシグモイド関数です。

正解画像と不正解画像は2000枚ずつ訓練データを用意しています。

改善点やプログラムの修正点があれば教えていただきたいです。

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

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

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

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

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

meg_

2024/01/15 11:58

参考までにどのような画像でしょうか?
kains

2024/01/15 12:01

人間の唇の画像です。例えば、「あ」と発音している口を大きく開けた正解画像か、それ以外かといった二値分類をしたいです。
quickquip

2024/01/16 01:44

「学習が全然足りないだけ」にも見えますが
jbpb0

2024/01/16 06:00 編集

train_datagen = ImageDataGenerator(rescale=1./255, shear_range=0.8, zoom_range=0.8, horizontal_flip=True) test_datagen = ImageDataGenerator(rescale=1./255) ↓ 変更 train_datagen = ImageDataGenerator(shear_range=0.8, zoom_range=0.8, horizontal_flip=True) test_datagen = ImageDataGenerator() で、どうでしょうか? https://www.tensorflow.org/api_docs/python/tf/keras/applications/MobileNetV3Small の「Note:」に 「For MobileNetV3, by default input preprocessing is included as a part of the model」 と書かれてるように、正規化はモデル内でされるので、別途255で割る必要は無いはず
kains

2024/01/16 06:04

コメントありがとうございます。jbpb0を試したところ問題が解決しました! ベストアンサーに選びたいので同じ内容を回答欄に投稿いただけますでしょうか? とても良い制度が得られました。ただ、どうして指摘されたコードを変更したら改善されたのか解説が欲しいです。初心者なので教えいただければ幸いです。よろしくお願いします。 ==============================] - 64s 728ms/step - loss: 0.0119 - accuracy: 0.9961 - val_loss: 0.0065 - val_accuracy: 0.9967 ​
jbpb0

2024/01/16 06:21

> どうして指摘されたコードを変更したら改善されたのか 私の一つ前のコメントの後半を見てください
kains

2024/01/16 06:23

大変失礼しました。見落としてました。ありがとうございます
guest

回答1

0

ベストアンサー

正解画像と不正解画像は2000枚ずつ訓練データを用意しています。
Found 3200 validated image filenames belonging to 2 classes.
Found 800 validated image filenames belonging to 2 classes.

人間の唇の画像です。例えば、「あ」と発音している口を大きく開けた正解画像か、それ以外かといった二値分類をしたいです。

上記情報により「あ」の画像は2000枚あるが、「い」「う」「え」「お」のそれぞれの画像はそれよりもかなり少なく、またバラツキも考えられます。
可能性ですが訓練データに「あ」の画像が多くあり「あ」について過学習していて、バリデーションデータでは正解率が低くなっているかもしれません。

random_stateを固定せずに正解率の変化を観察してみたり、train_test_splitstratifyを使用して過学習が改善されるか確認してみてはどうでしょうか?

投稿2024/01/15 12:22

meg_

総合スコア10609

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

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

kains

2024/01/15 13:00

ご指摘ありがとうございます! train_df, test_df = train_test_split(df, test_size=0.5, stratify=df['class'])にしたところ結果は以下のようになりました。 Epoch 1/100 63/63 [==============================] - ETA: 0s - loss: 0.6928 - accuracy: 0.5195 C:\anaconda\Lib\site-packages\keras\src\engine\training.py:3103: UserWarning: You are saving your model as an HDF5 file via `model.save()`. This file format is considered legacy. We recommend using instead the native Keras format, e.g. `model.save('my_model.keras')`. saving_api.save_model( 63/63 [==============================] - 80s 1s/step - loss: 0.6928 - accuracy: 0.5195 - val_loss: 0.7045 - val_accuracy: 0.5000 Epoch 2/100 63/63 [==============================] - 55s 872ms/step - loss: 0.6885 - accuracy: 0.5530 - val_loss: 0.7032 - val_accuracy: 0.5000 Epoch 3/100 63/63 [==============================] - 56s 891ms/step - loss: 0.6840 - accuracy: 0.5465 - val_loss: 0.7020 - val_accuracy: 0.5000 Epoch 4/100 63/63 [==============================] - 52s 821ms/step - loss: 0.6775 - accuracy: 0.6655 - val_loss: 0.6996 - val_accuracy: 0.5000 Epoch 5/100 63/63 [==============================] - 52s 830ms/step - loss: 0.6695 - accuracy: 0.6785 - val_loss: 0.6986 - val_accuracy: 0.5000 Epoch 6/100 63/63 [==============================] - 55s 879ms/step - loss: 0.6599 - accuracy: 0.6835 - val_loss: 0.6980 - val_accuracy: 0.5000 Epoch 7/100 63/63 [==============================] - 58s 928ms/step - loss: 0.6349 - accuracy: 0.8515 - val_loss: 0.6967 - val_accuracy: 0.5000 Epoch 8/100 63/63 [==============================] - 55s 862ms/step - loss: 0.5813 - accuracy: 0.8965 - val_loss: 0.6964 - val_accuracy: 0.5000 Epoch 9/100 63/63 [==============================] - 52s 829ms/step - loss: 0.5217 - accuracy: 0.8985 - val_loss: 0.6940 - val_accuracy: 0.5000 Epoch 10/100 63/63 [==============================] - 53s 838ms/step - loss: 0.4657 - accuracy: 0.9030 - val_loss: 0.6921 - val_accuracy: 0.5000 Epoch 11/100 63/63 [==============================] - 53s 836ms/step - loss: 0.4164 - accuracy: 0.9055 - val_loss: 0.6903 - val_accuracy: 0.5000 Epoch 12/100 63/63 [==============================] - 52s 830ms/step - loss: 0.3613 - accuracy: 0.9200 - val_loss: 0.6876 - val_accuracy: 0.5000 Epoch 13/100 63/63 [==============================] - 51s 820ms/step - loss: 0.3118 - accuracy: 0.9360 - val_loss: 0.6862 - val_accuracy: 0.5000 Epoch 14/100 63/63 [==============================] - 52s 832ms/step - loss: 0.2950 - accuracy: 0.9200 - val_loss: 0.6852 - val_accuracy: 0.6315 Epoch 15/100 63/63 [==============================] - 52s 825ms/step - loss: 0.2497 - accuracy: 0.9385 - val_loss: 0.6845 - val_accuracy: 0.9880 Epoch 16/100 63/63 [==============================] - 53s 838ms/step - loss: 0.2233 - accuracy: 0.9435 - val_loss: 0.6839 - val_accuracy: 0.5765 Epoch 17/100 63/63 [==============================] - 58s 932ms/step - loss: 0.2096 - accuracy: 0.9465 - val_loss: 0.6835 - val_accuracy: 0.5000 Epoch 18/100 63/63 [==============================] - 59s 948ms/step - loss: 0.1922 - accuracy: 0.9510 - val_loss: 0.6829 - val_accuracy: 0.5000 Epoch 19/100 63/63 [==============================] - 55s 871ms/step - loss: 0.1602 - accuracy: 0.9625 - val_loss: 0.6830 - val_accuracy: 0.5000 Epoch 20/100 63/63 [==============================] - 54s 859ms/step - loss: 0.1752 - accuracy: 0.9480 - val_loss: 0.6832 - val_accuracy: 0.5000 最終訓練精度: 0.9480 最終検証精度: 0.5000 最終訓練損失: 0.1752 最終検証損失: 0.6832 結果は検証データはまだ一定のままでした。ご意見ありがとうございました。またお気づきの点がございましたらよろしくお願いします。
meg_

2024/01/16 04:31

自分ならEarlyStoppingをやめたらどうなるか見てみたいですね。
meg_

2024/01/16 05:21

あとは、検証データで誤認識したデータを観察するのも何かヒントが得られるかもしれません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問