モバイルネット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枚ずつ訓練データを用意しています。
改善点やプログラムの修正点があれば教えていただきたいです。
回答1件
あなたの回答
tips
プレビュー