Prévention de la cécité oculaire en prédisant les stades de la rétinopathie diabétique

Preventing ocular blindness by predicting stages of diabetic retinopathy.

Introduction

La rétinopathie diabétique est une affection oculaire qui provoque des modifications des vaisseaux sanguins de la rétine. Lorsqu’elle n’est pas traitée, elle entraîne une perte de vision. Il est donc crucial de détecter les stades de la rétinopathie diabétique pour prévenir la cécité. Cette étude de cas porte sur la détection de la cécité oculaire à partir des symptômes de la sévérité de la rétinopathie diabétique afin d’empêcher la personne de devenir aveugle. Les données ont été collectées dans des zones rurales par différents experts cliniques formés à l’utilisation de caméras rétiniennes (caméras qui photographient l’arrière de l’œil). Ces photos ont été prises dans différentes conditions d’imagerie. En 2019, Kaggle a organisé une compétition (APTOS 2019 Blindness Detection) pour détecter les stades de la rétinopathie diabétique ; nos données proviennent de la même compétition Kaggle. La détection précoce de cette rétinopathie diabétique peut accélérer le traitement et réduire considérablement le risque de perte de vision.

L’intervention manuelle d’experts cliniques formés nécessite du temps et des efforts, surtout dans les pays en développement. Par conséquent, l’objectif principal de cette étude de cas est d’utiliser une technologie efficace pour détecter la sévérité de la maladie et prévenir la cécité. Nous mettons en œuvre des techniques d’apprentissage profond pour obtenir des résultats efficaces dans la classification de la sévérité de la maladie.

Objectifs d’apprentissage

  • Comprendre la rétinopathie diabétique : Apprenez à connaître l’affection oculaire et son impact sur la vision, en mettant l’accent sur l’importance d’une détection précoce.
  • Fondements de l’apprentissage profond : Explorez les bases de l’apprentissage profond et sa pertinence dans le diagnostic de la rétinopathie diabétique.
  • Prétraitement et augmentation des données : Comprenez comment préparer et améliorer efficacement l’ensemble de données pour l’entraînement des modèles d’apprentissage profond.
  • Sélection et évaluation du modèle : Apprenez à choisir et à évaluer les performances des modèles d’apprentissage profond pour la classification de la sévérité.
  • Déploiement pratique : Découvrez le déploiement du meilleur modèle à l’aide de Flask pour des prédictions réelles.

Cet article a été publié dans le cadre du Data Science Blogathon.

Problème commercial

Ici, la sévérité de la maladie d’une personne est classée en cinq catégories, c’est-à-dire une classification multi-classes car la personne ne peut être reconnue que par l’un des niveaux de gravité.

Contraintes commerciales

La précision et l’interprétabilité sont essentielles dans le domaine médical. En effet, des prédictions erronées peuvent conduire à l’ignorance, ce qui peut coûter la vie à une personne. Nous n’avons pas de contraintes strictes en termes de latence, mais nous devons obtenir des résultats précis.

Description de l’ensemble de données

L’ensemble de données comprend 3 662 images de rétine étiquetées de patients cliniques, pour lesquelles des experts cliniciens formés catégorisent chaque image en termes de sévérité de la rétinopathie diabétique, comme suit :

0 – Aucune rétinopathie diabétique,

1 – Légère

2 – Modérée

3 – Sévère

4 – Rétinopathie diabétique proliférante.

Le tableau ci-dessus indique que nos images d’ensemble de données sont identifiées par l’un des stades de la rétinopathie diabétique.

Métrique de performance

Nous utilisons le Quadratic weighted Kappa et la matrice de confusion comme métriques d’évaluation pour notre classification multi-classes.

Le Kappa mesure l’accord (similarité) entre les étiquettes réelles et prédites. Un score de Kappa de 1,0 indique que les prédictions et les étiquettes réelles sont identiques, un score de Kappa de -1 indique que les prédictions sont très différentes des étiquettes réelles. Notre objectif pour cette métrique est d’obtenir un score de Kappa supérieur à 0,6.

La métrique Kappa joue un rôle crucial dans le diagnostic médical, car dans le cas d’un score de -1, elle indique à quel point les deux évaluateurs (évaluateurs prédits et réels) sont similaires et impose une pénalité en cas de désaccord. Par exemple, dans notre cas, si notre étiquette prédite est 0 et l’étiquette réelle est 1, cela pose un problème grave pour le patient car ce cas sera ignoré car aucun diagnostic supplémentaire n’est recommandé pour le patient.

Comme nous le savons, la matrice de confusion est utilisée pour évaluer les performances d’un modèle de classification. La matrice compare les valeurs cibles réelles à celles prédites par notre modèle. Cela nous donne une vue d’ensemble de la performance de notre modèle de classification et des types d’erreurs qu’il commet.

Analyse exploratoire des données et prétraitement

Vérifions la distribution de nos données en traçant un graphique à barres.

v=df['diagnosis'].value_counts().plot(kind='bar')

À partir du graphique ci-dessus, nous pouvons déduire que nos données sont clairement déséquilibrées. Nous devons nous assurer d’équilibrer nos données pour éviter d’obtenir des résultats inexacts.

Nous pouvons appliquer des poids de classe pour maintenir l’uniformité dans l’ensemble de données afin d’obtenir une distribution uniforme dans les données.

Notre ensemble de données d’entraînement ne contient que 3 662 images, donc l’ensemble de données fourni par Kaggle est très petit. Il est souhaitable de surajuster en raison de l’entraînement sur le petit ensemble de données, donc ici le prétraitement joue un rôle crucial dans de meilleures performances en augmentant nos ensembles de données. Nous nous tournons donc vers l’augmentation des données pour améliorer nos ensembles de données. Avant l’augmentation des données, nous devons vérifier les conditions de l’image, comme si les images sont très sombres, ont un arrière-plan noir supplémentaire et sont des images de différentes tailles d’image. Par conséquent, nous devons appliquer des techniques de lissage aux images pour maintenir l’uniformité de la qualité de l’image en recadrant les arrière-plans noirs supplémentaires, en redimensionnant les images à une taille d’image typique, etc.

À partir de ce qui précède, nous pouvons observer que notre ensemble de données contient des images de différentes tailles avec un recadrage horizontal, un recadrage vertical et des régions noires supplémentaires.

Nous appliquons les techniques de lissage ci-dessous pour obtenir toutes les images de qualité uniforme.

Fonction de recadrage

→ Fonction de recadrage – utilisation pour supprimer les parties sombres supplémentaires autour de l’image

def crop(img,tol=7):
 # ici tol est la tolérance  
  '''
  cette fonction de recadrage est utilisée pour supprimer les parties sombres autour de l'image
  '''

  if img.ndim==2:
# cette boucle est utilisée pour recadrer les images GRIS
    mask=img>tol
    return img[np.ix_(mask.any(1),mask.any(0))]
  elif img.ndim==3:
# cette boucle est utilisée pour recadrer les images couleur    
    grayimg=cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)
    mask=grayimg>tol
    shap=img[:,:,0][np.ix_(mask.any(1),mask.any(0))].shape[0]
    if shap==0:
# l'image est trop sombre donc nous recadrons tout    
      return img
    else:
      img0=img[:,:,0][np.ix_(mask.any(1),mask.any(0))]
      img1=img[:,:,1][np.ix_(mask.any(1),mask.any(0))]
      img2=img[:,:,2][np.ix_(mask.any(1),mask.any(0))]
      img=np.stack([img0,img1,img2],axis=-1)
    return img #import csv

La figure ci-dessous indique qu’après l’application de la fonction, nous obtenons des images en recadrant les parties sombres autour.

→ La fonction de recadrage circulaire recadre une image de manière circulaire en prenant pour référence le centre.

def circlecrop(img):
  '''
  utilisé pour recadrer l'image de manière circulaire à partir du centre de l'image
  '''

  h,w,d= img.shape
  x = int(w/2)
  y = int(h/2)
  r = np.amin((x,y))
  circle_img = np.zeros((h,w), np.uint8)
  cv2.circle(circle_img, (x,y), int(r), 1, thickness=-1)
  img = cv2.bitwise_and(img, img, mask=circle_img) 
  return img

La figure ci-dessous est obtenue après l’application de la fonction de recadrage circulaire

Fonction de Ben Graham

→ Fonction de Ben Graham – Cette fonction est appliquée pour améliorer la luminosité de l’image

def ben(img,sigmaX=10):
  '''
  Méthode de Ben Graham pour améliorer les conditions d'éclairage.

  '''
  image=cv2.addWeighted( img,4, cv2.GaussianBlur( img , (0,0) , sigmaX) ,-4 ,128)
  return image

La figure ci-dessous indique qu’après l’application de la fonction de Ben Graham, nous avons amélioré les conditions d’éclairage de l’image.

Vérifions les images de la rétine prétraitées après l’application des fonctions ci-dessus.

Comme notre ensemble de données est très petit, nous risquons de subir un surajustement. Pour surmonter cette situation, nous devons augmenter nos données d’entraînement. Augmentez les données en utilisant des techniques d’augmentation telles que la symétrie horizontale, la symétrie verticale, la rotation des images, le zoom et le réglage de la luminosité.

from keras_preprocessing.image import ImageDataGenerator

datagen=ImageDataGenerator(horizontal_flip=True,vertical_flip=True,rotation_range=360,
                           brightness_range=[0.5, 1],
                           zoom_range = 0.2,rescale=1./255.,validation_split=0.25)
validation_datagen = ImageDataGenerator(rescale = 1./255)

train_generator=datagen.flow_from_dataframe(
dataframe=df,
directory="prep",
x_col="add",
y_col="diagnosis",
subset="training",
batch_size=12,
seed=42,
shuffle=True,
class_mode="categorical",
target_size=(256, 256))
     

Comme nous avons utilisé une division de validation de 0,25, nous obtenons 2 747 images d’entraînement et 915 images de validation.

Ici, chaque image est répliquée cinq fois car nous avons utilisé cinq techniques de symétrie horizontale, de symétrie verticale, de plage de rotation, de plage de luminosité et de plage de zoom.

Modèle d’apprentissage profond

Tout d’abord, nous construisons un modèle de base avec une architecture CNN simple.

inp=Input(shape=(256,256,3))
x=Conv2D(32,(3,3),activation='relu')(inp)
x=MaxPooling2D(pool_size=(2, 2))(x)
x=Dropout(0.5)(x)
x=Flatten()(x)
x=BatchNormalization()(x)
x=Dense(5, activation='softmax')(x)

Pour le modèle ci-dessus, nous obtenons un score kappa de 0,554, ce qui n’est pas acceptable pour prédire le stade de la maladie.

Nous nous tournons vers le transfert d’apprentissage pour utiliser le modèle pré-entraîné afin d’obtenir un score kappa élevé.

VGG-16

model_vgg16= VGG16(weights='imagenet', include_top=False,input_shape=(256,256, 3))
x=GlobalAveragePooling2D()(model_vgg16.layers[-1].output)
x=Dropout(0.5)(x)
x=Dense(5, activation='softmax')(x)

→Score kappa d’entraînement : 0,913

→Score d’exactitude d’entraînement : 0,817

Avec le modèle ci-dessus, nous obtenons un score kappa de 0,913

DENSENET

modeldense=DenseNet121(weights='imagenet', include_top=False,input_shape=(256,256, 3))
x=GlobalAveragePooling2D()(modeldense.layers[-1].output)
x=Dropout(0.5)(x)
x=Dense(5, activation='softmax')(x)

→Score kappa d’entraînement : 0,933

→Score d’exactitude d’entraînement : 0,884

Avec le modèle ci-dessus, nous obtenons un score kappa de 0,933

RESNET

modelres152=ResNet152(weights='imagenet', include_top=False,input_shape=(256,256, 3))
x=GlobalAveragePooling2D()(modelres152.layers[-1].output)
x=Dropout(0.5)(x)
x=Dense(5, activation='softmax')(x)

→Score kappa d’entraînement : 0,910

→Score d’exactitude d’entraînement : 0,844

Avec le modèle ci-dessus, nous obtenons un score kappa de 0,91

EFFICIENTNET

Après avoir implémenté différents modèles efficaces tels que EEfficientNetB0, B3, B4, et B7, nous pouvons obtenir de meilleurs résultats en utilisant EfficientNetB7.

modeleffB7 = EfficientNetB7(weights='imagenet', include_top=False, input_shape=(256,256, 3))
x = GlobalAveragePooling2D()(modeleffB7.layers[-1].output)
x = Dropout(0.5)(x)
x = Flatten()(x)
x = Dense(5, activation='softmax')(x)

→Score de Cohen Kappa d’entrainement : 0,877

→Score d’exactitude d’entrainement : 0,838

A partir du modèle ci-dessus, nous obtenons un score de kappa de 0,877

XCEPTION

modelxcep = Xception(weights='imagenet', include_top=False, input_shape=(256,256, 3))
x = GlobalAveragePooling2D()(modelxcep.layers[-1].output)
x = Dropout(0.5)(x)
x = Flatten()(x)
x = Dense(5, activation='softmax')(x)

→Score de Cohen Kappa d’entrainement : 0,925

→Score d’exactitude d’entrainement : 0,854

A partir du modèle ci-dessus, nous obtenons un score de kappa de 0,925

A partir du modèle ci-dessus, nous observons que le modèle Denset obtient un meilleur score de Kappa. Nous choisissons donc notre modèle Denset comme le meilleur et nous nous dirigeons vers la prédiction d’étape.

Prédiction en utilisant notre meilleur modèle

Prédire les étapes en utilisant notre meilleur modèle :

X = '/content/00a8624548a9.png'
img = cv2.imread(X)
img = crop(img)
img = cv2.resize(img, (256,256), interpolation=cv2.INTER_AREA)
img = circlecrop(img)
img = ben(img)
img = np.reshape(img, [1,256,256,3])
cd = ImageDataGenerator(horizontal_flip=True, vertical_flip=True,
                          rotation_range=360, brightness_range=[0.5, 1],
                           zoom_range = 0.2, rescale=1./255)
cg = cd.flow(img, batch_size=1)
tp = model.predict(cg)
op = np.argmax(tp)
if op == 0:
  matter = "Étape 0 - Pas de rétinopathie diabétique"
elif op == 1:
  matter = "Étape 1 - Légère"
elif op == 2:
  matter = "Étape 2 - Modérée"
elif op == 3:
  matter = "Étape 3 - Sévère"
elif op == 4:
  matter = "Étape 4 - Rétinopathie diabétique proliférative"
print(matter)

A partir de l’image ci-dessus, nous pouvons observer que notre meilleur modèle prédit les étapes de la rétinopathie diabétique.

Déploiement de notre modèle en utilisant Flask

J’ai utilisé Flask pour déployer mon modèle afin que nous puissions prédire l’étape de la rétinopathie diabétique de notre image rétinienne téléchargée. Voici la vidéo des instances en cours d’exécution de mon modèle déployé.

Conclusion

En conclusion, ce blog a mis en évidence le pouvoir transformateur de l’apprentissage profond dans la détection de la rétinopathie diabétique et la prévention de la perte de vision. Grâce à une détection précoce et une classification précise de la gravité, l’IA peut améliorer considérablement les résultats des patients. L’applicabilité réelle de ces techniques à travers le déploiement de modèles utilisant Flask met en évidence leur praticité dans les contextes de soins de santé.

La recherche continue sur les techniques d’augmentation et l’affinement des modèles améliorera encore les capacités de diagnostic. En exploitant le potentiel de l’IA, nous pouvons révolutionner le diagnostic médical et ouvrir la voie à un avenir plus sain.

  • Les modèles d’apprentissage profond tels que VGG-16, DENSENET, RESNET, EFFICIENTNET et XCEPTION ont efficacement classifié la gravité de la rétinopathie diabétique.
  • Le modèle performant, DENSENET, a obtenu des scores Kappa élevés, démontrant sa capacité à effectuer des prédictions précises.
  • La prétraitement et l’augmentation des données sont essentiels pour améliorer les performances et la généralisabilité du modèle.
  • Le déploiement de Flask met en évidence l’applicabilité pratique de l’apprentissage profond dans des scénarios réels, facilitant un diagnostic et un traitement efficaces.
  • La recherche continue sur les techniques d’augmentation et l’affinement des modèles offre la possibilité d’améliorer encore l’exactitude du diagnostic et de faire progresser le diagnostic médical grâce à l’IA.

Travaux futurs

  • Nous pouvons mettre en œuvre plus de techniques d’augmentation.
  • Nous pouvons essayer différentes couches de convolution sur nos modèles.
  • Nous avons besoin de récupérer plus d’images rétiniennes pour l’entrainement.

Foire aux questions

 Références

  • https://github.com/btgraham/SparseConvNet/blob/kaggle_Diabetic_Retinopathy_competition/competitionreport.pdf
  • https://arxiv.org/abs/1905.11946
  • https://arxiv.org/abs/0704.1028
  • https://www.kaggle.com/xhlulu/aptos-2019-densenet-keras-starter
  • https://www.kaggle.com/c/aptos2019-blindness-detection/discussion/108065

Les médias présentés dans cet article ne sont pas la propriété d’Analytics Vidhya et sont utilisés à la discrétion de l’auteur.

We will continue to update IPGirl; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more

AI

MPT-30B MosaicML brille plus que GPT-3 avec un nouveau LLM pour repousser les limites du NLP.

Découvrez l'avancée révolutionnaire de MosaicML dans le domaine de LLM avec la série MPT. Explorez comment MPT-30B et...

AI

Apprentissage Transformers Code Première Partie 2 - GPT de près et personnellement

Bienvenue à la deuxième partie de mon projet, où je plonge dans les subtilités des modèles transformer et GPT utilisa...

Actualités sur l'IA

Les voitures Mercedes-Benz deviennent encore plus intelligentes avec ChatGPT.

Mercedes-Benz, le célèbre fabricant de voitures de luxe, repousse les limites de l’intégration de l’intel...

Recherche en IA

IA probabiliste qui sait à quel point elle fonctionne bien.

Il est plus important que jamais pour l'intelligence artificielle d'estimer avec précision comment elle explique les ...

AI

Microsoft Research introduit BatteryML un outil open-source pour l'apprentissage automatique sur la dégradation de la batterie.

Les batteries lithium-ion sont devenues l’élément central du stockage d’énergie à l’ère moderne grâ...