CNNで正解率、適合率、再現率の結果がすべて同じ値になる
解決したいこと
例)
cnnでvgg16のファインチューニングを使って、二値分類を行おうとしたときに起こったバグです。正解率0.5,再現率0.5,適合率0.5というように値がすべて同じになってしまします。4エポック以降の結果はここには記載していませんが、100EPOCHくらいまで様子を見ても変わりません。結果から推測するに、正解率と適合率が同じという点から、一種類のデータしか判別できていないように思われますが、原因はよくわかりません。
発生している問題・エラー
出ているエラーメッセージを入力
Epoch 2/200
239/239 [==============================] - 18s 74ms/step - loss: 0.6935 - accuracy: 0.4927 - precision: 0.4927 - recall: 0.4927 - val_loss: 0.6932 - val_accuracy: 0.5000 - val_precision: 0.5000 - val_recall: 0.5000
Epoch 3/200
239/239 [==============================] - 18s 74ms/step - loss: 0.6934 - accuracy: 0.4958 - precision: 0.4958 - recall: 0.4958 - val_loss: 0.6932 - val_accuracy: 0.5000 - val_precision: 0.5000 - val_recall: 0.5000
Epoch 4/200
239/239 [==============================] - 18s 74ms/step - loss: 0.6934 - accuracy: 0.4948 - precision: 0.4948 - recall: 0.4948 - val_loss: 0.6931 - val_accuracy: 0.5000 - val_precision: 0.5000 - val_recall: 0.5000
例)
NameError (uninitialized constant World)
または、問題・エラーが起きている画像をここにドラッグアンドドロップ
該当するソースコード
import keras
import glob
import numpy as np
import tensorflow as tf
from sklearn.model_selection import train_test_split
# from keras.preprocessing.image import load_img, img_to_array #ここでエラーとなるので以下のコードに変更
from tensorflow.keras.utils import load_img, img_to_array
from keras import models
from keras.applications import VGG16
from keras.models import Sequential, load_model, model_from_json
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Dense, Dropout, Flatten
#from keras.utils import plot_model #これはKerasのバージョンなどにより使えないのでコメントアウト
#keras.utils.to_categoricalでエラーが出るので追加
# from keras.optimizers import Adam # ここでエラーとなるので以下のコードに変更
from tensorflow.keras.optimizers import Adam # 「tensorflow.」を追加
from sklearn.metrics import confusion_matrix
from tensorflow.keras.callbacks import TensorBoard
from tensorflow.keras.metrics import Precision
import matplotlib.pyplot as plt
import time
#2 各種設定
image_size = 180
color_setting = 3 #ここを変更。データセット画像のカラー:「1」はモノクロ・グレースケール。「3」はカラー。
folder = ['desease', 'health']
class_number = len(folder)
print('今回のデータで分類するクラス数は「', str(class_number), '」です。')
#3 データセットの読み込みとデータ形式の設定・正規化・分割
X_image = []
Y_label = []
for index, name in enumerate(folder):
read_data = train_data_path + '/' + name
files = glob.glob(read_data + '/*.jpg') #ここを変更。png形式のファイルを利用する場合のサンプルです。
print('--- 読み込んだデータセットは', read_data, 'です。')
for i, file in enumerate(files):
if color_setting == 1:
img = load_img(file, color_mode = 'grayscale' ,target_size=(image_size, image_size))
elif color_setting == 3:
img = load_img(file, color_mode = 'rgb' ,target_size=(image_size, image_size))
array = img_to_array(img)
X_image.append(array)
Y_label.append(index)
X_image = np.array(X_image)
Y_label = np.array(Y_label)
X_image = X_image.astype('float32') / 255
Y_label = keras.utils.to_categorical(Y_label, class_number)
train_images, valid_images, train_labels, valid_labels = train_test_split(X_image, Y_label, test_size=0.10)
x_train = train_images
y_train = train_labels
x_test = valid_images
y_test = valid_labels
#4 機械学習(人工知能)モデルの作成 – 畳み込みニューラルネットワーク(CNN)・学習の実行等
epochs = 200
batch_size = 16
vgg_conv = VGG16(weights='imagenet', include_top=False, input_shape=(image_size, image_size, 3))
last = vgg_conv.output
mod = Flatten()(last)
mod = Dense(1024, activation='relu')(mod)
mod = Dropout(0.5)(mod)
preds = Dense(2, activation='softmax')(mod)
model = models.Model(vgg_conv.input, preds)
model.summary()
model.compile(loss='categorical_crossentropy',
optimizer=Adam(),
metrics=['accuracy' , Precision(), tf.keras.metrics.Recall()])
# モデルの訓練
history = model.fit(x_train, y_train,
batch_size=batch_size,
epochs=epochs,
validation_data=(x_test, y_test),
shuffle=True)
model.save(f"model_potato_test.h5")
print(history.history)
# Calculate TP, FP, FN, TN
y_true = np.argmax(y_test, axis=1)
y_pred = model.predict(x_test)
y_pred = np.argmax(y_pred, axis=1)
cm = confusion_matrix(y_true, y_pred)
tn, fp, fn, tp = cm.ravel()
print(f'フォールド {i + 1} TP(真陽性): {tp}')
print(f'フォールド {i + 1} FP(偽陽性): {fp}')
print(f'フォールド {i + 1} FN(偽陰性): {fn}')
print(f'フォールド {i + 1} TN(真陰性): {tn}')
model.summary()
model.compile(loss='categorical_crossentropy',
optimizer=Adam(),
metrics=['accuracy'])
model.save(f"model_potato_{i+1}.h5")
start_time = time.time()
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('Model accuracy')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.grid()
plt.legend(['Train', 'Validation'], loc='upper left')
plt.show()
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('Model loss')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.grid()
plt.legend(['Train', 'Validation'], loc='upper left')
plt.show()
#model.save('cnn_model_weight.h5')
score = model.evaluate(x_test, y_test, verbose=0)
print('Loss:', score[0], '(損失関数値 - 0に近いほど正解に近い)')
print('Accuracy:', score[1] * 100, '%', '(精度 - 100% に近いほど正解に近い)')
print('Computation time(計算時間):{0:.3f} sec(秒)'.format(time.time() - start_time))
### 自分で試したこと
最終出力層のDence(1, sigmoid)、損失関数をbinary crossentropyに変更しても解決しませんでした。モデル構造に原因があるような気がしますが、解決方法のご教授をよろしくお願いします。