<jupyter_start><jupyter_text><jupyter_code>from google.colab import drive
drive.mount('/content/drive')
train_df = pd.read_csv('/content/drive/MyDrive/COURSES/CS231/train_split.txt', sep=" ", header=None)
train_df.columns = ['patient id', 'file_paths', 'labels', 'data source']
train_df = train_df.drop(['patient id', 'data source'], axis=1)
train_df.head()
test_df = pd.read_csv('/content/drive/MyDrive/COURSES/CS231/test_split.txt', sep=" ", header=None)
test_df.columns = ['patient id', 'file_paths', 'labels', 'data source']
test_df = test_df.drop(['patient id', 'data source'], axis=1)
test_df.head()
TRAIN_PATH = "/content/drive/MyDrive/COURSES/CS231/data/train"
TEST_PATH = "/content/drive/MyDrive/COURSES/CS231/data/test"<jupyter_output><empty_output><jupyter_text>Balancing Classes<jupyter_code>train_df['labels'].value_counts()
file_count = 4649
samples = []
for category in train_df['labels'].unique():
    category_slice = train_df.query("labels == @category")
    samples.append(category_slice.sample(file_count, replace=False, random_state=1))
train_df = pd.concat(samples, axis=0).sample(frac=1.0, random_state=1).reset_index(drop=True)
print(train_df['labels'].value_counts())
print(len(train_df))<jupyter_output>normal       4649
COVID-19     4649
pneumonia    4649
Name: labels, dtype: int64
13947<jupyter_text>Spliting train_df into train_df and valid_df<jupyter_code>train_df, valid_df = train_test_split(train_df, train_size=0.9, random_state=0)
print(train_df.labels.value_counts())
print(valid_df.labels.value_counts())
print(test_df.labels.value_counts())<jupyter_output>COVID-19     4213
normal       4189
pneumonia    4150
Name: labels, dtype: int64
pneumonia    499
normal       460
COVID-19     436
Name: labels, dtype: int64
COVID-19     274
pneumonia    105
normal       100
Name: labels, dtype: int64<jupyter_text>Image Data Generators<jupyter_code>batch_size = 32
img_height = 224
img_width = 224
target_size = (img_height, img_width)
train_datagen = ImageDataGenerator(preprocessing_function=tf.keras.applications.resnet_v2.preprocess_input, 
                                   horizontal_flip=True, zoom_range=0.1)
test_datagen = ImageDataGenerator(preprocessing_function=tf.keras.applications.resnet_v2.preprocess_input)
train_generator = train_datagen.flow_from_dataframe(train_df, directory=TRAIN_PATH, x_col='file_paths', y_col='labels',
                                                    target_size=target_size, batch_size=batch_size, color_mode='rgb', class_mode='categorical')

valid_generator = test_datagen.flow_from_dataframe(valid_df, directory=TRAIN_PATH, x_col='file_paths', y_col='labels',
                                                    target_size=target_size, batch_size=batch_size, color_mode='rgb', class_mode='categorical')

test_generator = test_datagen.flow_from_dataframe(test_df, directory=TEST_PATH, x_col='file_paths', y_col='labels',
                                                    target_size=target_size, batch_size=batch_size, color_mode='rgb', class_mode='categorical', shuffle = False)<jupyter_output>Found 12552 validated image filenames belonging to 3 classes.
Found 1395 validated image filenames belonging to 3 classes.
Found 479 validated image filenames belonging to 3 classes.<jupyter_text>Create Model<jupyter_code>base_model = ResNet50V2(include_top=False, weights="imagenet", input_shape=(img_height, img_width, 3))

for layer in base_model.layers[:190]:
    layer.trainable = False
for i, layer in enumerate(base_model.layers):
    print(i, layer.name, "-", layer.trainable)
model = tf.keras.Sequential([
    base_model,
    Flatten(),
    BatchNormalization(),
    Dense(256, activation='relu'),
    Dropout(0.5),
    BatchNormalization(),
    Dense(128, activation='relu'),
    Dropout(0.5),
    BatchNormalization(),
    Dense(64, activation='relu'),
    Dropout(0.5),
    BatchNormalization(),
    Dense(3, activation='softmax'),
])
lr = 5e-3
model.compile(loss='categorical_crossentropy', optimizer=Adam(learning_rate=lr), metrics=['accuracy'])
model.summary()<jupyter_output>Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
resnet50v2 (Functional)      (None, 7, 7, 2048)        23564800  
_________________________________________________________________
flatten (Flatten)            (None, 100352)            0         
_________________________________________________________________
batch_normalization (BatchNo (None, 100352)            401408    
_________________________________________________________________
dense (Dense)                (None, 256)               25690368  
_________________________________________________________________
dropout (Dropout)            (None, 256)               0         
_________________________________________________________________
batch_normalization_1 (Batch (None, 256)               1024      
________________________________________________________[...]<jupyter_text>Callbacks<jupyter_code>patience = 10
# stop_patience = 10
factor = 0.1
callbacks = [
    ModelCheckpoint("resnet50v2-final.h5", save_best_only=True, verbose = 0),
    # EarlyStopping(patience=stop_patience, monitor='val_loss', verbose=1),
    ReduceLROnPlateau(monitor='val_loss', factor=factor, patience=patience, min_lr=1e-6, verbose=1)
]<jupyter_output><empty_output><jupyter_text>Model Training<jupyter_code>epochs = 50
history = model.fit(train_generator, validation_data=valid_generator, epochs=epochs, callbacks=callbacks, verbose=1)
train_loss = [0.6487, 0.4469, 0.4074, 0.3849, 0.3576, 0.3427, 0.3471, 0.3380, 0.3410, 0.3383, 0.3361, 0.2940, 0.2783, 0.2717, 0.26, 0.2624, 0.2369, 0.2470, 0.2358, 0.2311, 0.2263, 0.2218, 0.2233, 0.2167, 0.2231, 0.2227, 0.2213, 0.2096, 0.2241, 0.2239, 0.2176, 0.2176, 0.2072, 0.2219, 0.2164, 0.2101, 0.2049, 0.2178, 0.2090, 0.2152, 0.2185, 0.2181, 0.2128, 0.2176, 0.2096, 0.2130, 0.2160, 0.2083, 0.2108, 0.2143]
val_loss = [0.3612, 0.3654, 0.6374, 0.3819, 0.5943, 1.1585, 0.4505, 0.4302, 0.5506, 0.6574, 1.1695, 1.3079, 1.7884, 3.1584, 5.1392, 4.6225, 4.8016, 4.9733, 4.8234, 5.7820, 6.4980, 4.4179, 4.2063, 4.1806, 4.2003, 5.5932, 1.5663, 1.1069, 3.2203, 2.6253, 3.3542, 4.0708, 4.2337, 5.4792, 4.8195, 3.8897, 4.0073, 4.3476, 5.2787, 5.0320, 5.5412, 3.6614, 3.8046, 4.0843, 3.6718, 3.9051, 4.3147, 4.5132, 6.02, 4.8454]
plt.plot(train_loss, label='Loss (training data)')
plt.plot(val_loss, label='Loss (validation data)')
plt.title('Loss for Training')
plt.ylabel('Loss')
plt.xlabel('No. epoch')
plt.legend(['train', 'validation'], loc="upper left")
plt.savefig('/content/drive/MyDrive/COURSES/CS231/results/resnet50_50-1')
plt.show()
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'validation'], loc='upper left')
plt.savefig("plot/resnet50_plot.png")
plt.show()<jupyter_output><empty_output><jupyter_text>Predictions on Test Set<jupyter_code>best_model = model
best_model.load_weights('/content/drive/MyDrive/COURSES/CS231/resnet50v2-final.h5')
best_model.evaluate(test_generator)
preds = best_model.predict(test_generator)
def print_info( test_gen, preds, print_code, save_dir, subject ):
    class_dict=test_gen.class_indices
    labels= test_gen.labels
    file_names= test_gen.filenames 
    error_list=[]
    true_class=[]
    pred_class=[]
    prob_list=[]
    new_dict={}
    error_indices=[]
    y_pred=[]

    for key,value in class_dict.items():
        new_dict[value]=key             # dictionary {integer of class number: string of class name}
    # store new_dict as a text fine in the save_dir
    classes=list(new_dict.values())     # list of string of class names
    dict_as_text=str(new_dict)
    dict_name= subject + '-' +str(len(classes)) +'.txt'  
    dict_path=os.path.join(save_dir, dict_name)    
    with open(dict_path, 'w') as x_file:
        x_file.write(dict_as_text)    
    errors=0      

    for i, p in enumerate(preds):
        pred_index=np.argmax(p)        
        true_index=labels[i]  # labels are integer values
        if pred_index != true_index: # a misclassification has occurred
            error_list.append(file_names[i])
            true_class.append(new_dict[true_index])
            pred_class.append(new_dict[pred_index])
            prob_list.append(p[pred_index])
            error_indices.append(true_index)            
            errors=errors + 1
        y_pred.append(pred_index)    

    if print_code !=0:
        if errors>0:
            if print_code>errors:
                r=errors
            else:
                r=print_code           
            msg='{0:^28s}{1:^28s}{2:^28s}{3:^16s}'.format('Filename', 'Predicted Class' , 'True Class', 'Probability')
            print_in_color(msg, (0,255,0),(55,65,80))
            for i in range(r):
                msg='{0:^28s}{1:^28s}{2:^28s}{3:4s}{4:^6.4f}'.format(error_list[i], pred_class[i],true_class[i], ' ', prob_list[i])
                print_in_color(msg, (255,255,255), (55,65,60))
                #print(error_list[i]  , pred_class[i], true_class[i], prob_list[i])               
        else:
            msg='With accuracy of 100 % there are no errors to print'
            print_in_color(msg, (0,255,0),(55,65,80))
            
    if errors>0:
        plot_bar=[]
        plot_class=[]
        for  key, value in new_dict.items():        
            count=error_indices.count(key) 
            if count!=0:
                plot_bar.append(count) # list containg how many times a class c had an error
                plot_class.append(value)   # stores the class 
        fig1=plt.figure()
        fig1.set_figheight(len(plot_class)/3)
        fig1.set_figwidth(10)
        plt.style.use('fivethirtyeight')
        for i in range(0, len(plot_class)):
            c=plot_class[i]
            x=plot_bar[i]
            plt.barh(c, x, )
            plt.title( ' Errors by Class on Test Set')
    
    if len(classes)<= 30:
        # create a confusion matrix and a test report        
        y_true= np.array(labels)        
        y_pred=np.array(y_pred)        
        cm = confusion_matrix(y_true, y_pred )
        clr = classification_report(y_true, y_pred, target_names=classes)
        length=len(classes)
        if length<8:
            fig_width=8
            fig_height=8
        else:
            fig_width= int(length * .5)
            fig_height= int(length * .5)
        fig2 = plt.figure(figsize=(fig_width, fig_height))
        sns.heatmap(cm, annot=True, vmin=0, fmt='g', cmap='Blues', cbar=False)       
        plt.xticks(np.arange(length)+.5, classes, rotation= 90)
        plt.yticks(np.arange(length)+.5, classes, rotation=0)
        plt.xlabel("Predicted")
        plt.ylabel("Actual")
        plt.title("Confusion Matrix")
        plt.savefig("/content/drive/MyDrive/COURSES/CS231/results/resnet50_50-4.png", dpi = 100)
        plt.show()    
        print("Classification Report:\n----------------------\n", clr)

        fig1.savefig("/content/drive/MyDrive/COURSES/CS231/results/resnet50_50-3.png", dpi = 100)
save_dir = '/content/drive/MyDrive/COURSES/CS231'
subject = "kq"
print_code = 0
print_info(test_generator, preds, print_code, save_dir, subject)<jupyter_output><empty_output>