"""
# Mango Classification 
"""
"""
## Transer Learning with EfficientNet-B7
"""
!pip install -q efficientnet
"""
* Website: https://aidea-web.tw/topic/72f6ea6a-9300-445a-bedc-9e9f27d91b1c
* Forum : https://www.facebook.com/groups/184056976135023/
"""
"""
## Dataset : AICUP 2020 Mango sample data
![Taiwan%20AICUP%202020%20Mango.JPG](attachment:Taiwan%20AICUP%202020%20Mango.JPG)
"""
train_dir = '/kaggle/input/aicup2020-mango-c1p1-datagen/Mango/train'
val_dir   = '/kaggle/input/aicup2020-mango-c1p1-datagen/Mango/dev'
test_dir  = '/kaggle/input/aicup2020-mango-c1p1-datagen/Mango/test'
import os
import numpy as np
import pandas as pd
trainDF = pd.read_csv('/kaggle/input/aicup2020-mango-c1p1-datagen/Mango/train.csv', header=None)
trainFiles = trainDF[0].tolist()
trainClasses = trainDF[1].tolist()
valDF = pd.read_csv('/kaggle/input/aicup2020-mango-c1p1-datagen/Mango/dev.csv', header=None)
valFiles = valDF[0].tolist()
valClasses = valDF[1].tolist()
testFiles = os.listdir(test_dir+'/unknown')
"""
### display image of a training data
"""
import matplotlib.pyplot as plt
plt.imshow(plt.imread(train_dir+'/'+trainClasses[0]+'/'+trainFiles[0]))
plt.imshow(plt.imread(val_dir+'/'+valClasses[0]+'/'+valFiles[0]))
"""
## Dataset Equilibre 
"""
labels = ['A', 'B', 'C']
# plot the circle of value counts in dataset
def plot_equilibre(equilibre, labels, title):
    plt.figure(figsize=(5,5))
    my_circle=plt.Circle( (0,0), 0.5, color='white')
    plt.pie(equilibre, labels=labels, colors=['red','green','blue'],autopct='%1.1f%%')
    p=plt.gcf()
    p.gca().add_artist(my_circle)
    plt.title(title)
    plt.show()
equilibreTrain = []
[equilibreTrain.append(trainClasses.count(label)) for label in labels]
print(equilibreTrain)
plot_equilibre(equilibreTrain, labels, 'Train Data')
del equilibreTrain
equilibreDev = []
[equilibreDev.append(valClasses.count(label)) for label in labels]
print(equilibreDev)
plot_equilibre(equilibreDev, labels, 'Development Data')
del equilibreDev
"""
## Data Augmentation
"""
from tensorflow.keras.preprocessing.image import ImageDataGenerator

target_size=(224,224)
batch_size = 16
train_datagen = ImageDataGenerator(
    rescale=1./255,
    rotation_range=40,
    width_shift_range=0.2,
    height_shift_range=0.2,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True,
    vertical_flip=True)

train_generator = train_datagen.flow_from_directory(
    train_dir,
    target_size=target_size,
    batch_size=batch_size,
    color_mode='rgb',    
    shuffle=True,
    seed=42,
    class_mode='categorical')

val_datagen = ImageDataGenerator(rescale=1./255)

val_generator = val_datagen.flow_from_directory(
    val_dir,
    target_size=target_size,
    batch_size=batch_size,
    color_mode='rgb',
    shuffle=False,    
    class_mode='categorical')
test_datagen = ImageDataGenerator(rescale=1./255)

test_generator = test_datagen.flow_from_directory(
    test_dir,
    target_size=target_size,
    batch_size=batch_size,
    color_mode='rgb',
    shuffle=False,     
    class_mode=None)
"""
## Build Model
"""
num_classes = 3
input_shape = (224,224,3)
import efficientnet.tfkeras as efn
from tensorflow.keras import models, layers, optimizers, regularizers, callbacks

base_model = efn.EfficientNetB7(input_shape=input_shape, weights='imagenet', include_top=False)
base_model.trainable = False # freeze the base model (for transfer learning)

x = base_model.output
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dense(512)(x)
x = layers.Dense(32)(x)
out = layers.Dense(num_classes, activation="softmax")(x)

model = models.Model(inputs=base_model.input, outputs=out)

model.summary()
# compile model
model.compile(loss='categorical_crossentropy', optimizer='Adam', metrics=['accuracy'])
## set Checkpoint : save best only, verbose on
#checkpoint = callbacks.ModelCheckpoint("mango_classification.hdf5", monitor='accuracy', verbose=0, save_best_only=True, mode='auto', save_freq=1)
"""
## Train Model
"""
STEP_SIZE_TRAIN=train_generator.n//train_generator.batch_size
STEP_SIZE_VAL  =val_generator.n//val_generator.batch_size
STEP_SIZE_TEST =test_generator.n//test_generator.batch_size
num_epochs = 100
# Train Model
history = model.fit_generator(train_generator,steps_per_epoch=STEP_SIZE_TRAIN,epochs=num_epochs, validation_data=val_generator, validation_steps=STEP_SIZE_VAL) #, callbacks=[checkpoint])
"""
## Save Model
"""
## Save Model
model.save('mango_enetB7.h5')
## load best model weights if using callback (save-best-only)
#model.load_weights("mango_classification.hdf5")
"""
## Evaluate Model
"""
score = model.evaluate_generator(val_generator, steps=STEP_SIZE_VAL) # with validation dataset
print(score)
"""
## Confusion Matrix
"""
from sklearn.metrics import classification_report, confusion_matrix

predY=model.predict_generator(val_generator) # with validation dataset
y_pred = np.argmax(predY,axis=1)
y_actual = val_generator.classes
cm = confusion_matrix(y_actual, y_pred)
print(cm)
"""
### report confusion matrix
"""
print(classification_report(y_actual, y_pred, target_names=labels))