<jupyter_start><jupyter_text>mount google drive  DATA PREPROCESSING IN RUNTIME<jupyter_code>from google.colab import drive
drive.mount('/content/drive')<jupyter_output>Go to this URL in a browser: https://accounts.google.com/o/oauth2/auth?client_id=947318989803-6bn6qk8qdgf4n4g3pfee6491hc0brc4i.apps.googleusercontent.com&redirect_uri=urn%3aietf%3awg%3aoauth%3a2.0%3aoob&response_type=code&scope=email%20https%3a%2f%2fwww.googleapis.com%2fauth%2fdocs.test%20https%3a%2f%2fwww.googleapis.com%2fauth%2fdrive%20https%3a%2f%2fwww.googleapis.com%2fauth%2fdrive.photos.readonly%20https%3a%2f%2fwww.googleapis.com%2fauth%2fpeopleapi.readonly

Enter your authorization code:
··········
Mounted at /content/drive<jupyter_text>copy leaf data to local runtime for faster processing<jupyter_code>!rm -rf TrainData/
!mkdir TrainData/
!cp /content/drive/My\ Drive/train_val_split_projc2.zip TrainData/
!unzip -q TrainData/train_val_split_projc2.zip -d TrainData/<jupyter_output><empty_output><jupyter_text>check no of images in training and validation<jupyter_code>!ls TrainData/train | wc -l && ls TrainData/val | wc -l<jupyter_output>1020
255<jupyter_text>remove train_sep and val_sep folders if they exist<jupyter_code>!rm -rf TrainData/train_sep
!rm -rf TrainData/val_sep<jupyter_output><empty_output><jupyter_text>import libraries<jupyter_code>import numpy as np
import pandas as pd
import os, random, math, glob, cv2, pickle
from datetime import datetime

import matplotlib.pyplot as plt
%matplotlib inline

from sklearn.utils import shuffle
from sklearn.model_selection import  train_test_split
from keras.utils import to_categorical
from sklearn.decomposition import PCA
from sklearn.svm import LinearSVC
from sklearn.metrics import confusion_matrix, classification_report

from skimage.io import imread, imshow
from skimage.transform import resize
from skimage.feature import hog
from skimage import exposure<jupyter_output>Using TensorFlow backend.<jupyter_text>make folders for class labels<jupyter_code>n_class = 5
class_labels = list(range(n_class))

base_dir = 'TrainData/'

train_input = 'TrainData/train/'
val_input = 'TrainData/val/'

train_save = base_dir+'train_sep/'
val_save = base_dir+'/val_sep/'

if os.path.exists(train_save):
    os.system('rm -rf '+train_save)
if os.path.exists(val_save):
    os.system('rm -rf '+val_save)

os.mkdir(train_save)
os.mkdir(val_save)

# validation
for filenm in glob.glob(val_input+'*.jpg'):
    filename = filenm.split('/')[-1]
    label = filename.split('.')[0].split('_')[-1]

    # print(filename, label)

    dest_dir = val_save+label+'/'
    if not os.path.exists(dest_dir):
        os.mkdir(dest_dir)
    
    # print(dest_dir)
    cmd = 'cp '+filenm+' '+dest_dir+filename
    # print(cmd)
    os.system(cmd)

# train
for filenm in glob.glob(train_input+'*.jpg'):
    filename = filenm.split('/')[-1]
    label = filename.split('.')[0].split('_')[-1]

    # print(filename, label)

    dest_dir = train_save+label+'/'
    if not os.path.exists(dest_dir):
        os.mkdir(dest_dir)
    
    # print(dest_dir)
    cmd = 'cp '+filenm+' '+dest_dir+filename
    # print(cmd)
    os.system(cmd)<jupyter_output><empty_output><jupyter_text>verify if images have been copied properly<jupyter_code>!ls TrainData/val_sep/0 | wc -l
!ls TrainData/val_sep/1 | wc -l
!ls TrainData/val_sep/2 | wc -l
!ls TrainData/val_sep/3 | wc -l
!ls TrainData/val_sep/4 | wc -l

!ls TrainData/train_sep/0 | wc -l
!ls TrainData/train_sep/1 | wc -l
!ls TrainData/train_sep/2 | wc -l
!ls TrainData/train_sep/3 | wc -l
!ls TrainData/train_sep/4 | wc -l<jupyter_output>51
51
51
51
51
437
278
79
80
146<jupyter_text>determine class weights for imbalanced training<jupyter_code>import fnmatch
import numpy as np
from sklearn.utils import class_weight

y=[]
for i in range(5):
    y.extend([i for j in range(len(fnmatch.filter(os.listdir('TrainData/train_sep/'+str(i)), '*.jpg')))])

print(np.bincount(y))

class_weights = class_weight.compute_class_weight('balanced', np.unique(y), y)
class_weights_dict = dict(zip(range(5), class_weights))
print(class_weights_dict)<jupyter_output>[437 278  79  80 146]
{0: 0.4668192219679634, 1: 0.7338129496402878, 2: 2.5822784810126582, 3: 2.55, 4: 1.3972602739726028}<jupyter_text>TRANSFER LEARNING CODE  delete model h5 files if experiment useless<jupyter_code>!rm *.h5
import pandas as pd
import numpy as np
import os
import keras
import matplotlib.pyplot as plt
from tensorflow.keras.layers import Dense,GlobalAveragePooling2D
from tensorflow.keras.applications import InceptionResNetV2, VGG16, ResNet50
from tensorflow.keras.preprocessing import image
from tensorflow.keras.applications.resnet import preprocess_input
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam, SGD<jupyter_output><empty_output><jupyter_text>define model based on variable "model_to_use"<jupyter_code>model_to_use='resnet50'

base_model=ResNet50(weights='imagenet',include_top=False)
for layer in base_model.layers:
    layer.trainable=False

x=base_model.output
x=GlobalAveragePooling2D()(x)
x=Dense(128,activation='relu')(x)
x=Dense(128,activation='relu')(x)
preds=Dense(5,activation='softmax')(x) 

model=Model(inputs=base_model.input, outputs=preds)<jupyter_output>Downloading data from https://storage.googleapis.com/tensorflow/keras-applications/resnet/resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5
94773248/94765736 [==============================] - 1s 0us/step<jupyter_text>define train and validation generators and images folders<jupyter_code>base_dir = 'TrainData/'

train_save = base_dir+'train_sep/'
val_save = base_dir+'/val_sep/'

#train
train_datagen = ImageDataGenerator(preprocessing_function=preprocess_input,
                                    rotation_range=15,
                                    shear_range=0.2,
                                    width_shift_range=0.2,
                                    height_shift_range=0.2,
                                    zoom_range=0.2,
                                    brightness_range=(0.1, 0.9),
                                    channel_shift_range=150.0,
                                    horizontal_flip=True)

train_generator=train_datagen.flow_from_directory(train_save, 
                                                target_size=(224,224),
                                                color_mode='rgb',
                                                batch_size=16,
                                                class_mode='categorical',
                                                shuffle=True)
# val
val_datagen = ImageDataGenerator(preprocessing_function=preprocess_input) 

val_generator=val_datagen.flow_from_directory(val_save, 
                                                target_size=(224,224),
                                                color_mode='rgb',
                                                batch_size=16,
                                                class_mode='categorical',
                                                shuffle=False)<jupyter_output>Found 1020 images belonging to 5 classes.
Found 255 images belonging to 5 classes.<jupyter_text>train model and save the best validation accuracy checkpoint<jupyter_code>from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping

model.compile(optimizer='Adam',loss='categorical_crossentropy',metrics=['accuracy'])

step_size_train=train_generator.n//train_generator.batch_size
step_size_val=val_generator.n//val_generator.batch_size

earlystop = EarlyStopping(monitor='val_accuracy', patience=10)
checkpoint = ModelCheckpoint('model-epoch-{epoch:03d}-valacc-{val_accuracy:03f}.h5', verbose=1, monitor='val_accuracy',save_best_only=True, mode='auto')  

no_epochs = 25
hist = model.fit_generator(train_generator,
                   steps_per_epoch=step_size_train,
                   epochs=no_epochs,
                   validation_data=val_generator,
                   validation_steps=step_size_val,
                   callbacks=[earlystop, checkpoint], #callbacks=[checkpoint],
                   class_weight=class_weights_dict)<jupyter_output>WARNING:tensorflow:From <ipython-input-13-f9293cfc74c8>:18: Model.fit_generator (from tensorflow.python.keras.engine.training) is deprecated and will be removed in a future version.
Instructions for updating:
Please use Model.fit, which supports generators.
Epoch 1/25
63/63 [==============================] - ETA: 0s - loss: 1.5031 - accuracy: 0.3661
Epoch 00001: val_accuracy improved from -inf to 0.48750, saving model to model-epoch-001-valacc-0.487500.h5
63/63 [==============================] - 22s 355ms/step - loss: 1.5031 - accuracy: 0.3661 - val_loss: 1.3337 - val_accuracy: 0.4875
Epoch 2/25
63/63 [==============================] - ETA: 0s - loss: 1.1780 - accuracy: 0.5229
Epoch 00002: val_accuracy improved from 0.48750 to 0.53750, saving model to model-epoch-002-valacc-0.537500.h5
63/63 [==============================] - 22s 346ms/step - loss: 1.1780 - accuracy: 0.5229 - val_loss: 1.0846 - val_accuracy: 0.5375
Epoch 3/25
63/63 [==============================] - ETA: 0s - loss: 1.0[...]<jupyter_text>visualize training and validation loss and accuracy<jupyter_code># visualizing losses and accuracy
train_loss = hist.history['loss']
val_loss = hist.history['val_loss']
train_accu = hist.history['accuracy']
val_accu = hist.history['val_accuracy']
xc = range(len(train_loss))

plt.figure()
plt.plot(xc, train_loss, label='Training loss')
plt.plot(xc, val_loss, label='Validation loss')
plt.legend(loc="lower left")
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.savefig('train_val_loss.png')
plt.show()

plt.figure()
plt.plot(xc, train_accu, label='Training accuracy')
plt.plot(xc, val_accu, label='Validation accuracy')
plt.legend(loc="lower left")
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.savefig('train_val_accuracy.png')
plt.show()<jupyter_output><empty_output><jupyter_text>VALIDATE MODEL  load model with best validation accuracy<jupyter_code>from sklearn.metrics import confusion_matrix, accuracy_score, classification_report

model_path = '/content/drive/My Drive/Models_Resnet/classweight/Best_model/model-epoch-024-valacc-0.625000.h5'
model.load_weights(model_path)<jupyter_output><empty_output><jupyter_text>model predict on validation data<jupyter_code>val_generator.reset()
val_steps = np.math.ceil(val_generator.samples/val_generator.batch_size)
ypred = model.predict_generator(val_generator, steps=len(val_generator))

print(ypred.shape)<jupyter_output>(255, 5)<jupyter_text>final class labels for validation images<jupyter_code>ypred_labels = np.argmax(ypred, axis=1)
np.bincount(ypred_labels)<jupyter_output><empty_output><jupyter_text>compute confusion matrix, accuracy score and display classification report<jupyter_code>ytrue = []
for filenm in val_generator.filenames:
    ytrue.append(int(filenm.split('/')[0]))
confusion_matrix(ytrue, ypred_labels)
accuracy_score(ytrue, ypred_labels)
print(classification_report(ytrue, ypred_labels))<jupyter_output>precision    recall  f1-score   support

           0       0.59      0.84      0.69        51
           1       0.71      0.33      0.45        51
           2       0.60      0.47      0.53        51
           3       0.55      0.75      0.63        51
           4       0.88      0.84      0.86        51

    accuracy                           0.65       255
   macro avg       0.67      0.65      0.63       255
weighted avg       0.67      0.65      0.63       255<jupyter_text>TEST MODEL  bring test data into runtime<jupyter_code>!mkdir TestData/
!cp -r /content/drive/My\ Drive/ECE542_sp20_CompetitionData/TestData TestData/<jupyter_output><empty_output><jupyter_text>import libraries<jupyter_code>import pandas as pd
import numpy as np
import os
import keras
import matplotlib.pyplot as plt
from tensorflow.keras.layers import Dense,GlobalAveragePooling2D
from tensorflow.keras.applications import InceptionResNetV2, VGG16, ResNet50
from tensorflow.keras.preprocessing import image
from tensorflow.keras.applications.resnet import preprocess_input
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam, SGD
from keras.models import load_model<jupyter_output><empty_output><jupyter_text>define model and load weights<jupyter_code>base_model=ResNet50(weights='imagenet',include_top=False)
for layer in base_model.layers:
    layer.trainable=False

x=base_model.output
x=GlobalAveragePooling2D()(x)
x=Dense(128,activation='relu')(x)
x=Dense(128,activation='relu')(x)
preds=Dense(5,activation='softmax')(x)

model=Model(inputs=base_model.input, outputs=preds)

model_path = '/content/drive/My Drive/Models_Resnet/classweight/Best_model/model-epoch-024-valacc-0.625000.h5'
model.load_weights(model_path)<jupyter_output><empty_output><jupyter_text>define test generator<jupyter_code>test_save = 'TestData/'

test_datagen = ImageDataGenerator(preprocessing_function=preprocess_input)

test_generator=test_datagen.flow_from_directory(test_save, 
                                                target_size=(224,224),
                                                color_mode='rgb',
                                                batch_size=16,
                                                class_mode=None,
                                                shuffle=False)<jupyter_output>Found 200 images belonging to 1 classes.<jupyter_text>check if generator filenames arrives in sorted order of filenames<jupyter_code>non_sorted = test_generator.filenames
sorted_list = sorted(non_sorted)

sorted_list == non_sorted<jupyter_output><empty_output><jupyter_text>predict labels for test data and save predictions as CSV file<jupyter_code>from keras.utils import to_categorical

ypred = model.predict_generator(test_generator, steps=len(test_generator))
ypred_labels = np.argmax(ypred, axis=1)
ypred_onehot = to_categorical(ypred_labels, num_classes=5)

print(ypred.shape)
print(np.bincount(ypred_labels))
# np.savetxt('predictions_model-epoch-024-valacc-0.625000.csv', ypred_onehot, fmt='%d', delimiter=',')
print('Predictions onehot file saved!')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11460012616527651, 'fraction_numerical': 0.043737295857573424, 'mean_word_length': 3.8202702702702704, 'pattern_counts': {'":': 0, '<': 83, '<?xml version=': 0, '>': 83, 'https://': 2, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 46, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '23', 'dir': 'jupyter-structured-clean-dedup', 'id': '338059', 'license': 'MIT', 'n_tokens_mistral': 5125, 'n_tokens_neox': 4682, 'n_words': 877, 'path': 'Code/ProjC2_Transfer_Learning_ResNet50.ipynb', 'repo_name': 'shreyas-muralidhara/Leaf-Wilting-Classification-Transfer-Learning', 'size': '14267'}