<jupyter_start><jupyter_text>Model description (this model is still being trained, it should be ready in about 2 hours, I will recommit the new version)This was the best performing model we found.It is based on InceptionV3 model pretrained on ImageNet,we put our own classifier on top, we frozed the weights of the baseand we trained only the top for a few epochs.Then we thawed all the layers and have been training whole model.During the first training, this model was reaching 75% accuracy ona balanced dataset (we trained on equal amount of eyes with and without symptoms for easier assesment).This model seemed to perform the best on images preprocessed byContrast Limited Adaptive Histogram Equalization (CLAHE), to read more about how we preprocessedour images open [this](https://github.com/rozni/uni-ml/blob/master/Cognitive_Systems_for_Health_Technology_Applications/Case_2/Image_Preprocessing.ipynb) notebook and [here](https://github.com/rozni/uni-ml/tree/master/Cognitive_Systems_for_Health_Technology_Applications/Case_2) is the full report.We also tried NASNetLarge and MobileNetV2 as our base model,however, InceptionV3 is a simplier and easier to train model,so it was faster to reach better results.<jupyter_code>import os
import pandas as pd

import matplotlib.pyplot as plt
import seaborn as sns
import keras
from keras import layers, regularizers
from keras.applications.inception_v3 import InceptionV3
from keras.preprocessing import image
from keras.models import Model
from keras.layers import Dense, GlobalAveragePooling2D
from keras import backend as K
BASE_DIR = '/content/'
TRAIN_DIR = '500x500_cropped_clahe_128/'
TARGET_SIZE = (299, 299)
# load the labels and balance the training set
labels_df = pd.read_csv(os.path.join(BASE_DIR, 'labels.csv'))

# balance classes
fifty_fifty_subset = pd.concat([
    labels_df[labels_df['class']=='symptoms'].sample(n=9000, random_state=0),
    labels_df[labels_df['class']=='nosymptoms'].sample(n=9000, random_state=0)
]).sample(frac=1.0, random_state=0) # shuffle

# training/validation split (70% to 30%)
split = 70*len(fifty_fifty_subset)//100
train_df = fifty_fifty_subset.iloc[:split]
valid_df = fifty_fifty_subset.iloc[split:]
# set up image geterators

common_flow_kwargs = dict(
    directory=os.path.join(BASE_DIR, TRAIN_DIR),
    x_col='file_name',
    y_col='class',
    target_size=TARGET_SIZE,
    batch_size=32,
    class_mode='binary',
)

train_gen = keras.preprocessing.image.ImageDataGenerator(
    rotation_range=360,
    fill_mode='nearest',
    horizontal_flip=True,
    rescale=1/255,
).flow_from_dataframe(
    dataframe=train_df,
    **common_flow_kwargs,
)

valid_gen = keras.preprocessing.image.ImageDataGenerator(
    rescale=1./255,
).flow_from_dataframe(
    dataframe=valid_df,
    **common_flow_kwargs,
)
# create the base pre-trained model
base_model = InceptionV3(weights='imagenet', include_top=False)

# add a global spatial average pooling layer
x = base_model.output
x = layers.GlobalAveragePooling2D()(x)
# add a classifier
x = layers.Dropout(0.3)(x)
x = layers.BatchNormalization()(x)
x = layers.Dense(64, activation='elu')(x)
x = layers.BatchNormalization()(x)
x = layers.Dense(32, activation='elu')(x)
x = layers.BatchNormalization()(x)
x = layers.Dense(16, activation='elu')(x)
output = layers.Dense(1, activation='sigmoid')(x)

# this is the final model
model = Model(inputs=base_model.input, outputs=output)
# train only the top layers
for layer in base_model.layers:
    layer.trainable = False

# compile the model
model.compile(
    optimizer='rmsprop',
    loss='binary_crossentropy',
    metrics=['acc']
)
# train the top of the model
model.fit_generator(
      train_gen,
      steps_per_epoch=train_gen.n//train_gen.batch_size,
      epochs=6,
      validation_data=valid_gen,
      validation_steps=valid_gen.n//valid_gen.batch_size,
)
# make all layers trainable
for layer in model.layers:
    layer.trainable = True
# setup a model checkpoint (because we have already lost many)
checkpoint = keras.callbacks.ModelCheckpoint(
    filepath='Inception-e{epoch:02d}-vl{val_loss:.2f}-va{val_acc:.3f}.hdf5',
    monitor='val_acc',
    verbose=1,
    save_best_only=False,
    save_weights_only=False,
    mode='auto',
    period=1
)

# compile again and decrease the learning rate
model.compile(
    optimizer=keras.optimizers.Adam(lr=0.0001),
    loss='binary_crossentropy',
    metrics=['acc'],
)

# final training
model.fit_generator(
      train_gen,
      steps_per_epoch=train_gen.n//train_gen.batch_size,
      epochs=35,
      validation_data=valid_gen,
      validation_steps=valid_gen.n//valid_gen.batch_size,
      callbacks=[checkpoint]
)
#print statistics
acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']

epochs = range(len(acc))

plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()

plt.figure()

plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()

plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10764818355640535, 'fraction_numerical': 0.016634799235181644, 'mean_word_length': 5.317632850241546, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '325595', 'license': 'MIT', 'n_tokens_mistral': 1791, 'n_tokens_neox': 1711, 'n_words': 437, 'path': 'Cognitive_Systems_for_Health_Technology_Applications/Case_2/Model-Incepted.ipynb', 'repo_name': 'rozni/uni-ml', 'size': '5230'}