我正在嘗試對影像使用二進制分類器,無論它是否是蜜蜂。我收集了一個包含 6 個類別的 12,000 張影像的資料集,其中一個是蜜蜂。所以我有一列is_bee,其值為"0"和"1"與"Not a bee"和"It is a bee"匹配。我正在訓練分類器,當我嘗試將經過訓練的模型應用于任何影像(甚至是經過訓練的影像)時,它(幾乎)以 73.11% 的置信度為我提供了(幾乎)完全值“0”。我的代碼如下:
import pandas as pd
import numpy as np
import sys
import os
import random
from pathlib import Path
import imageio
import skimage
import skimage.io
import skimage.transform
import matplotlib.pyplot as plt
import seaborn as sns
import scipy
from sklearn.model_selection import train_test_split
from sklearn import metrics
from keras import optimizers, losses
from keras.models import Sequential
from keras.layers import Dense, Conv2D, Flatten, MaxPool2D, Dropout, BatchNormalization,LeakyReLU
from keras.preprocessing.image import ImageDataGenerator
from keras.callbacks import ModelCheckpoint, Callback, EarlyStopping, ReduceLROnPlateau
from tensorflow.keras.utils import to_categorical
import tensorflow
np.random.seed(42)
tensorflow.random.set_seed(42)
# Global variables
imgs_folder='images/'
img_width=100
img_height=100
img_channels=3
def read_img(file):
img = skimage.io.imread(file)
img = skimage.transform.resize(img, (img_width, img_height), mode='reflect')
return img[:,:,:img_channels]
images=pd.read_csv('/content/gdrive/MyDrive/Colab Notebooks/beeID/images.csv',
index_col=False, sep=";",
dtype={'type':'category', 'is_bee':'category'})
images['file'] = imgs_folder images['file']
# Cannot impute nans, drop them
images.dropna(inplace=True)
# Some image files don't exist. Leave only bees with available images.
img_exists = images['file'].apply(lambda f: os.path.exists(f))
images = images[img_exists]
images['type'] = images['type'].astype('category')
images['is_bee'] = images['is_bee'].astype('category')
def split_balance(df, field_name):
train_df, test_df = train_test_split(df, random_state=23)
train_df, val_df = train_test_split(train_df, test_size=0.1, random_state=23)
ncat_bal = int(len(train_df)/train_df[field_name].cat.categories.size)
train_df_bal = train_df.groupby(field_name, as_index=False).apply(lambda g: g.sample(ncat_bal, replace=True)).reset_index(drop=True)
return(train_df_bal, val_df, test_df)
def prepare2train(train_p2t_df, val_p2t_df, test_p2t_df, field_name):
# Train data
train_X = np.stack(train_p2t_df['file'].apply(read_img))
#train_y = to_categorical(train_bees[field_name].values)
train_y = pd.get_dummies(train_p2t_df[field_name], drop_first=False)
# Validation during training data to calc val_loss metric
val_X = np.stack(val_p2t_df['file'].apply(read_img))
#val_y = to_categorical(val_bees[field_name].values)
val_y = pd.get_dummies(val_p2t_df[field_name], drop_first=False)
# Test data
test_X = np.stack(test_p2t_df['file'].apply(read_img))
#test_y = to_categorical(test_bees[field_name].values)
test_y = pd.get_dummies(test_p2t_df[field_name], drop_first=False)
# Data augmentation
generator = ImageDataGenerator(
featurewise_center=False, # set input mean to 0 over the dataset
samplewise_center=False, # set each sample mean to 0
featurewise_std_normalization=False, # divide inputs by std of the dataset
samplewise_std_normalization=False, # divide each input by its std
zca_whitening=False, # apply ZCA whitening
rotation_range=180, # randomly rotate images in the range (degrees, 0 to 180)
zoom_range=0.1, # Randomly zoom image
width_shift_range=0.2, # randomly shift images horizontally (fraction of total width)
height_shift_range=0.2, # randomly shift images vertically (fraction of total height)
horizontal_flip=True, # randomly flip images
vertical_flip=True)
generator.fit(train_X)
return (generator, train_X, val_X, test_X, train_y, val_y, test_y)
def eval_model(training, model, test_X, test_y, field_name):
## Trained model analysis and evaluation
f, ax = plt.subplots(2,1, figsize=(5,5))
ax[0].plot(training.history['loss'], label="Loss")
ax[0].plot(training.history['val_loss'], label="Validation loss")
ax[0].set_title('%s: loss' % field_name)
ax[0].set_xlabel('Epoch')
ax[0].set_ylabel('Loss')
ax[0].legend()
# Accuracy
ax[1].plot(training.history['accuracy'], label="Accuracy")
ax[1].plot(training.history['val_accuracy'], label="Validation accuracy")
ax[1].set_title('%s: accuracy' % field_name)
ax[1].set_xlabel('Epoch')
ax[1].set_ylabel('Accuracy')
ax[1].legend()
plt.tight_layout()
plt.show()
# Accuracy by subspecies
test_pred = model.predict(test_X)
acc_by_subspecies = np.logical_and((test_pred > 0.5), test_y).sum()/test_y.sum()
acc_by_subspecies.plot(kind='bar', title='Accuracy by %s' % field_name)
plt.ylabel('Accuracy')
plt.show()
# Print metrics
print("Classification report")
test_pred = np.argmax(test_pred, axis=1)
test_truth = np.argmax(test_y.values, axis=1)
# Loss function and accuracy
test_res = model.evaluate(test_X, test_y.values, verbose=1)
# Split/balance and plot the result
train_bees_bal, val_bees, test_bees = split_balance(bees, 'health')
# Split/balance and plot the result
train_images_bal, val_images, test_images = split_balance(images, 'type')
# Will use balanced dataset as main
train_images = train_images_bal
generator_images, train_images_X, val_images_X, test_images_X, train_images_y, val_images_y, test_images_y = prepare2train(train_images, val_images, test_images, 'is_bee')
# We'll stop training if no improvement after some epochs
earlystopper_images = EarlyStopping(monitor='val_accuracy', patience=20, verbose=1)
# Save the best model during the training
checkpointer_images = ModelCheckpoint('model_images.h5'
,monitor='val_accuracy'
,verbose=1
,save_best_only=True
,save_weights_only=True)
# Build CNN model
model_images=Sequential()
model_images.add(Conv2D(5, kernel_size=3, input_shape=(img_width, img_height,3), activation='relu', padding='same'))
model_images.add(MaxPool2D(2))
model_images.add(Conv2D(10, kernel_size=3, activation='relu', padding='same'))
model_images.add(Dropout(0.25))
model_images.add(Flatten())
model_images.add(Dropout(0.5))
model_images.add(Dense(train_images_y.columns.size, activation='sigmoid', name='preds'))
# show model summary
model_images.summary()
model_images.compile(loss=losses.binary_crossentropy,optimizer='adam',metrics=['accuracy'])
# Train
training_images = model_images.fit_generator(generator_images.flow(train_images_X,train_images_y, batch_size=60)
,epochs=100
,validation_data=(val_images_X, val_images_y)
,steps_per_epoch=10
,callbacks=[earlystopper_images, checkpointer_images])
# Get the best saved weights
model_images.load_weights('model_images.h5')
eval_model(training_images, model_images, test_images_X, test_images_y, 'is_bee')
scores = model_images.evaluate(test_images_X, test_images_y, verbose=0)
print("Accuracy: %.2f%%" % (scores[1]*100))
import numpy as np
from google.colab import files
from keras.preprocessing import image
for fn in os.listdir('/content/bee_imgs'):
# predicting images
path = '/content/bee_imgs/' fn
img = image.load_img(path, target_size=(100, 100))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
checkImages = np.vstack([x])
classes_images = model_images.predict(checkImages)
score = tensorflow.nn.softmax(classes_images[0])
print(
"This image {} most likely belongs to {} with a {:.2f} percent confidence."
.format(fn, test_images_y.columns[np.argmax(score)], 100 * np.max(score))
)
對已經訓練過的影像進行上述測驗的結果(但也發生在我用未訓練過的影像嘗試它時)是這樣的:
This image 016_252.png most likely belongs to 0 with a 73.11 percent confidence.
This image 031_117.png most likely belongs to 0 with a 73.11 percent confidence.
This image 019_1026.png most likely belongs to 0 with a 73.11 percent confidence.
This image 008_243.png most likely belongs to 1 with a 73.11 percent confidence.
...
This image 039_016.png most likely belongs to 0 with a 73.11 percent confidence.
This image 022_364.png most likely belongs to 0 with a 73.11 percent confidence.
This image 022_274.png most likely belongs to 0 with a 73.11 percent confidence.
因此,盡管該模型在預測影像是否為蜜蜂方面的準確率已達到 96%,但當我將其應用于任何蜜蜂影像時,它很少將其識別為蜜蜂。我的模型構建或嘗試應用它時是否有問題?
uj5u.com熱心網友回復:
洗掉softmax函式 和后np.argmax,您應該只使用read_img在訓練期間用于預測的相同函式,它應該沒問題。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/479019.html
