EfficientNets使用 CNN 进行鱼类物种分类

数据集 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)
FilepathLabel
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()

请添加图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mrrunsen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值