数据集 https://www.kaggle.com/crowww/a-large-scale-fish-dataset
import numpy as np
import pandas as pd
from pathlib import Path
import os.path
import matplotlib.pyplot as plt
from IPython.display import Image, display
import matplotlib.cm as cm
import tensorflow as tf
import os
import shutil
from tqdm import tqdm
from random import shuffle
import cv2
from glob import glob
from keras import backend as K
import random
import albumentations as A
from sklearn.model_selection import train_test_split, StratifiedKFold
from tensorflow.keras.layers import *
from tensorflow.keras.optimizers import *
from tensorflow.keras.models import *
from tensorflow.keras.preprocessing.image import *
from tensorflow.keras.callbacks import *
from tensorflow.keras.applications.efficientnet import *
EfficientNets 是 Google Brain 开源发布的最先进的卷积神经网络。一系列图像分类模型实现了最先进的准确性,但比之前的模型(如ResNet-152和 ResNet-50)更小、更快。
image_dir = Path('../input/a-large-scale-fish-dataset/Fish_Dataset/Fish_Dataset')
# Get filepaths and labels
filepaths = list(image_dir.glob(r'**/*.png'))
labels = list(map(lambda x: os.path.split(os.path.split(x)[0])[1], filepaths))
filepaths = pd.Series(filepaths, name='Filepath').astype(str)
labels = pd.Series(labels, name='Label')
# Concatenate filepaths and labels
image_df = pd.concat([filepaths, labels], axis=1)
# Drop GT images
image_df = image_df[image_df['Label'].apply(lambda x: x[-2:] != 'GT')]
# Shuffle the DataFrame and reset index
image_df = image_df.sample(frac=1).reset_index(drop = True)
# Show the result
image_df.head(3)
Filepath | Label | |
---|---|---|
0 | ../input/a-large-scale-fish-dataset/Fish_Datas... | Red Mullet |
1 | ../input/a-large-scale-fish-dataset/Fish_Datas... | Red Sea Bream |
2 | ../input/a-large-scale-fish-dataset/Fish_Datas... | Red Sea Bream |
2. Display 15 pictures of the dataset
# Display 20 picture of the dataset with their labels
fig, axes = plt.subplots(nrows=3, ncols=5, figsize=(15, 7),
subplot_kw={'xticks': [], 'yticks': []})
for i, ax in enumerate(axes.flat):
ax.imshow(plt.imread(image_df.Filepath[i]))
ax.set_title(image_df.Label[i])
plt.tight_layout()
plt.show()
3. Load the Images with a generator
# Separate in train and test data
train_df, test_df = train_test_split(image_df, train_size=0.9, shuffle=True, random_state=1)
train_generator = tf.keras.preprocessing.image.ImageDataGenerator(
preprocessing_function=tf.keras.applications.mobilenet_v2.preprocess_input,
validation_split=0.2
)
test_generator = tf.keras.preprocessing.image.ImageDataGenerator(
preprocessing_function=tf.keras.applications.mobilenet_v2.preprocess_input
)
train_images = train_generator.flow_from_dataframe(
dataframe=train_df,
x_col='Filepath',
y_col='Label',
target_size=(224, 224),
color_mode='rgb',
class_mode='categorical',
batch_size=32,
shuffle=True,
seed=42,
subset='training'
)
val_images = train_generator.flow_from_dataframe(
dataframe=train_df,
x_col='Filepath',
y_col='Label',
target_size=(224, 224),
color_mode='rgb',
class_mode='categorical',
batch_size=32,
shuffle=True,
seed=42,
subset='validation'
)
test_images = test_generator.flow_from_dataframe(
dataframe=test_df,
x_col='Filepath',
y_col='Label',
target_size=(224, 224),
color_mode='rgb',
class_mode='categorical',
batch_size=32,
shuffle=False
)
def create_model(input_shape=(224, 224, 3)):
inputs = Input(input_shape)
base_model = EfficientNetB1(input_shape=input_shape, include_top=False, classes=9)
x = base_model(inputs)
x = GlobalAveragePooling2D()(x)
# x = Dropout(0.1)(x)
x = Dense(56, activation='relu')(x)
x = Dropout(0.1)(x)
outputs = Dense(9, activation='sigmoid')(x)
model = Model(inputs, outputs)
return model
K.clear_session()
model = create_model((224, 224, 3))
# model = load_model('models/checkpoint/EfficientNetB0.h5')
metrics = [
'accuracy',
'AUC'
]
model.compile(optimizer=Adam(), loss='categorical_crossentropy', metrics=metrics)
Downloading data from https://storage.googleapis.com/keras-applications/efficientnetb1_notop.h5
27025408/27018416 [==============================] - 0s 0us/step
checkpoint_path = 'models/EfficientNetB1/model_224.h5'
callbacks = [
EarlyStopping(monitor='val_loss', mode='min', patience=10, verbose=1),
ReduceLROnPlateau(monitor='val_loss', mode='min', factor=0.1, patience=5, min_lr=0.000001, verbose=1),
ModelCheckpoint(monitor='val_loss', mode='min', filepath=checkpoint_path, verbose=1, save_best_only=True, save_weights_only=False)
]
history = model.fit(
train_images,
validation_data=val_images,
epochs=10,
callbacks=callbacks
)
Epoch 1/10
203/203 [==============================] - 1810s 9s/step - loss: 0.4755 - accuracy: 0.8515 - auc: 0.9527 - val_loss: 2.5939 - val_accuracy: 0.1099 - val_auc: 0.5008
Epoch 00001: val_loss improved from inf to 2.59388, saving model to models/EfficientNetB1/model_224.h5
Epoch 2/10
203/203 [==============================] - 1768s 9s/step - loss: 0.0422 - accuracy: 0.9865 - auc: 0.9956 - val_loss: 3.4738 - val_accuracy: 0.1105 - val_auc: 0.4984
Epoch 00002: val_loss did not improve from 2.59388
Epoch 3/10
203/203 [==============================] - 1706s 8s/step - loss: 0.0232 - accuracy: 0.9925 - auc: 0.9969 - val_loss: 4.3550 - val_accuracy: 0.1247 - val_auc: 0.4953
Epoch 00003: val_loss did not improve from 2.59388
Epoch 4/10
203/203 [==============================] - 1741s 9s/step - loss: 0.0296 - accuracy: 0.9910 - auc: 0.9949 - val_loss: 3.0401 - val_accuracy: 0.1099 - val_auc: 0.4752
Epoch 00004: val_loss did not improve from 2.59388
Epoch 5/10
203/203 [==============================] - 1758s 9s/step - loss: 0.0336 - accuracy: 0.9928 - auc: 0.9954 - val_loss: 3.6292 - val_accuracy: 0.1117 - val_auc: 0.5109
Epoch 00005: val_loss did not improve from 2.59388
Epoch 6/10
203/203 [==============================] - 1704s 8s/step - loss: 0.0051 - accuracy: 0.9986 - auc: 0.9978 - val_loss: 4.1182 - val_accuracy: 0.1191 - val_auc: 0.5059
Epoch 00006: ReduceLROnPlateau reducing learning rate to 0.00010000000474974513.
Epoch 00006: val_loss did not improve from 2.59388
Epoch 7/10
203/203 [==============================] - 1684s 8s/step - loss: 0.0032 - accuracy: 0.9987 - auc: 0.9978 - val_loss: 0.0016 - val_accuracy: 1.0000 - val_auc: 0.9996
Epoch 00007: val_loss improved from 2.59388 to 0.00159, saving model to models/EfficientNetB1/model_224.h5
Epoch 8/10
203/203 [==============================] - 1648s 8s/step - loss: 0.0020 - accuracy: 0.9997 - auc: 0.9984 - val_loss: 5.4939e-04 - val_accuracy: 1.0000 - val_auc: 0.9996
Epoch 00008: val_loss improved from 0.00159 to 0.00055, saving model to models/EfficientNetB1/model_224.h5
Epoch 9/10
203/203 [==============================] - 1660s 8s/step - loss: 0.0017 - accuracy: 0.9996 - auc: 0.9987 - val_loss: 4.9128e-05 - val_accuracy: 1.0000 - val_auc: 0.9997
Epoch 00009: val_loss improved from 0.00055 to 0.00005, saving model to models/EfficientNetB1/model_224.h5
Epoch 10/10
203/203 [==============================] - 1634s 8s/step - loss: 9.9217e-04 - accuracy: 0.9997 - auc: 0.9988 - val_loss: 2.8125e-05 - val_accuracy: 1.0000 - val_auc: 0.9997
Epoch 00010: val_loss improved from 0.00005 to 0.00003, saving model to models/EfficientNetB1/model_224.h5
pd.DataFrame(history.history)[['accuracy','val_accuracy']].plot()
plt.title("Accuracy")
plt.show()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HqCifGHZ-1640521898421)(output_14_0.png)]
pd.DataFrame(history.history)[['loss','val_loss']].plot()
plt.title("Loss")
plt.show()
5. Visualize the result
results = model.evaluate(test_images, verbose=0)
print(" Test Loss: {:.5f}".format(results[0]))
print("Test Accuracy: {:.2f}%".format(results[1] * 100))
Test Loss: 0.00006
Test Accuracy: 100.00%
# Predict the label of the test_images
pred = model.predict(test_images)
pred = np.argmax(pred,axis=1)
# Map the label
labels = (train_images.class_indices)
labels = dict((v,k) for k,v in labels.items())
pred = [labels[k] for k in pred]
# Display the result
print(f'The first 5 predictions: {pred[:5]}')
The first 5 predictions: ['Red Mullet', 'Shrimp', 'Red Mullet', 'Red Mullet', 'Striped Red Mullet']
from sklearn.metrics import classification_report
y_test = list(test_df.Label)
print(classification_report(y_test, pred))
precision recall f1-score support
Black Sea Sprat 1.00 1.00 1.00 86
Gilt-Head Bream 1.00 1.00 1.00 86
Hourse Mackerel 1.00 1.00 1.00 120
Red Mullet 1.00 1.00 1.00 93
Red Sea Bream 1.00 1.00 1.00 102
Sea Bass 1.00 1.00 1.00 108
Shrimp 1.00 1.00 1.00 98
Striped Red Mullet 1.00 1.00 1.00 92
Trout 1.00 1.00 1.00 115
accuracy 1.00 900
macro avg 1.00 1.00 1.00 900
weighted avg 1.00 1.00 1.00 900
from sklearn.metrics import confusion_matrix
import seaborn as sns
cf_matrix = confusion_matrix(y_test, pred, normalize='true')
plt.figure(figsize = (10,6))
sns.heatmap(cf_matrix, annot=True, xticklabels = sorted(set(y_test)), yticklabels = sorted(set(y_test)))
plt.title('Normalized Confusion Matrix')
plt.show()
Examples of prediction
# Display 15 picture of the dataset with their labels
fig, axes = plt.subplots(nrows=3, ncols=5, figsize=(15, 7),
subplot_kw={'xticks': [], 'yticks': []})
for i, ax in enumerate(axes.flat):
ax.imshow(plt.imread(test_df.Filepath.iloc[i]))
ax.set_title(f"True: {test_df.Label.iloc[i]}\nPredicted: {pred[i]}")
plt.tight_layout()
plt.show()