Zoidberg¶
Introduction¶
Ce projet vise à comparer deux approches de machine learning - les réseaux de neurones convolutifs (CNN) et les K-Nearest Neighbors (KNN) - pour détecter la pneumonie à partir d'images de radiographie. Nous évaluerons ces modèles en fonction de leur précision, de leur perte, et d'autres métriques pertinentes, incluant les faux négatifs, faux positifs, et des graphiques tels que la matrice de confusion et la courbe ROC.
Structure du Dataset¶
Le dataset se compose de trois dossiers principaux :
- train : utilisé pour l'entraînement des modèles
- val : utilisé pour la validation des modèles après l'entraînement
- test : utilisé pour tester les modèles
Chaque dossier contient deux sous-dossiers :
- NORMAL : contient des images de radiographies normales
- PNEUMONIA : contient des images de radiographies avec pneumonie
Filtrage des images avec ImageUtils¶
La classe ImageUtils est utilisée pour filtrer les images de radiographie afin de s'assurer qu'elles respectent certaines dimensions minimales. Elle permet aussi de récupérer des informations sur le contenu du dataset, comme par exemple le nombre total d'images, les tailles minimales et maximales, les largeurs et hauteurs moyennes, ainsi que le nombre d'images filtrées. Voici comment elle fonctionne :
class ImageUtils:
@staticmethod
def filter_images(data_dir, img_size=(256, 256)):
"""
Filter out images that are too small and gather statistics on the image sizes.
"""
min_img_size = (img_size[0] * 2, img_size[1] * 2)
image_stats = {
'total_images': 0,
'min_size': (float('inf'), float('inf')),
'max_size': (0, 0),
'avg_width': 0,
'avg_height': 0,
'filtered_images': 0
}
filepaths = []
total_width, total_height = 0, 0
for dirpath, _, filenames in os.walk(data_dir):
for filename in filenames:
if filename.lower().endswith(('png', 'jpg', 'jpeg')):
filepath = os.path.join(dirpath, filename)
with Image.open(filepath) as img:
width, height = img.size
image_stats['total_images'] += 1
total_width += width
total_height += height
if width < min_img_size[0] or height < min_img_size[1]:
image_stats['filtered_images'] += 1
else:
filepaths.append(filepath)
image_stats['min_size'] = (
min(image_stats['min_size'][0], width),
min(image_stats['min_size'][1], height)
)
image_stats['max_size'] = (
max(image_stats['max_size'][0], width),
max(image_stats['max_size'][1], height)
)
image_stats['avg_width'] += width
image_stats['avg_height'] += height
remaining_images = image_stats['total_images'] - image_stats['filtered_images']
if remaining_images > 0:
image_stats['avg_width'] /= remaining_images
image_stats['avg_height'] /= remaining_images
image_stats['avg_width'] = round(image_stats['avg_width'])
image_stats['avg_height'] = round(image_stats['avg_height'])
filtered_filepaths = [fp for fp in filepaths if
Image.open(fp).size[0] >= min_img_size[0] and Image.open(fp).size[1] >=
min_img_size[1]]
return filtered_filepaths, image_stats
Modèle KNN¶
Le modèle KNN (K-Nearest Neighbors) est un modèle de machine learning simple mais efficace pour la classification. Voici comment il est construit et utilisé dans ce projet :
Prétraitement et création du dataset avec ImageUtils¶
Pour le modèle KNN, nous utilisons la classe ImageUtils pour filtrer et prétraiter les images de notre dataset. Nous choisissons une taille d'image plus petite (64x64) pour réduire la complexité computationnelle :
data_handler = DataHandler(data_directory, image_size=(64, 64))
file_paths, image_stats = ImageUtils.filter_images(data_directory, img_size=(64, 64))
train_df, val_df = data_handler._create_dataframe(file_paths)
X_train, X_val, y_train, y_val = data_handler._create_datasets()
Construction du modèle KNN¶
Le modèle KNN est construit en utilisant la bibliothèque scikit-learn. Voici les étapes de construction :
- Chargement et Prétraitement des Images :
X_train = np.array([self._load_image(fp) for fp in self.train_df['filepath']])
y_train = np.array([1 if label == 'PNEUMONIA' else 0 for label in self.train_df['class']])
X_val = np.array([self._load_image(fp) for fp in self.val_df['filepath']])
y_val = np.array([1 if label == 'PNEUMONIA' else 0 for label in self.val_df['class']])
- Entraînement du modèle :
self.model = KNeighborsClassifier(n_neighbors=n_neighbors)
self.scaler = StandardScaler()
X_train = self.scaler.fit_transform(X_train)
self.model.fit(X_train, y_train)
- Évaluation du modèle :
X_val = self.scaler.transform(X_val)
y_pred = self.model.predict(X_val)
accuracy = accuracy_score(y_val, y_pred)
report = classification_report(y_val, y_pred, target_names=['NORMAL', 'PNEUMONIA'])
cm = confusion_matrix(y_val, y_pred)
roc_auc = roc_auc_score(y_val, y_proba)
fpr, tpr, thresholds = roc_curve(y_val, y_proba)
Résultats du modèle KNN¶
## Résultats du modèle KNN
- Précision: 0.9342442356959864
- Rapport de classification:
precision recall f1-score support
NORMAL 0.93 0.80 0.86 296
PNEUMONIA 0.93 0.98 0.96 875
accuracy 0.93 1171
macro avg 0.93 0.89 0.91 1171
weighted avg 0.93 0.93 0.93 1171
Graphique KNN¶
Modèle CNN¶
Le modèle CNN (Convolutional Neural Network) est un modèle de machine learning puissant pour la classification d'images. Voici comment il est construit et utilisé dans ce projet :
Prétraitement et création du dataset avec ImageUtils¶
Pour le modèle CNN, nous utilisons également la classe ImageUtils pour filtrer et prétraiter les images
, mais avec une taille d'image plus grande (256x256) pour exploiter pleinement la capacité du modèle CNN :
data_handler = DataHandler(data_directory, image_size=(256, 256))
file_paths, image_stats = ImageUtils.filter_images(data_directory, img_size=(256, 256))
train_df, val_df = data_handler._create_dataframe(file_paths)
train_ds = data_handler.get_dataset(data_handler.train_generator)
val_ds = data_handler.get_dataset(data_handler.validation_generator)
Construction du modèle CNN¶
Le modèle CNN est construit en utilisant la bibliothèque TensorFlow. Voici les étapes de construction :
- Définition de l'architecture du modèle :
model = tf.keras.models.Sequential([
tf.keras.layers.Input(shape=input_shape),
tf.keras.layers.Conv2D(32, (3, 3), activation='relu'),
tf.keras.layers.MaxPooling2D((2, 2)),
tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),
tf.keras.layers.MaxPooling2D((2, 2)),
tf.keras.layers.Conv2D(128, (3, 3), activation='relu'),
tf.keras.layers.MaxPooling2D((2, 2)),
tf.keras.layers.Conv2D(256, (3, 3), activation='relu'),
tf.keras.layers.MaxPooling2D((2, 2)),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(512, activation='relu'),
tf.keras.layers.Dropout(0.5),
tf.keras.layers.Dense(1, activation='sigmoid')
])
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.001), loss='binary_crossentropy', metrics=['accuracy'])
- Entraînement du modèle :
history = self.model.fit(
train_ds,
steps_per_epoch=train_steps,
epochs=epochs,
validation_data=val_ds,
validation_steps=val_steps
)
self.model.summary()
- Évaluation du modèle :
loss, accuracy = self.model.evaluate(test_ds, steps=test_steps)
y_true = []
y_pred = []
y_proba = []
for x, y in test_ds.take(test_steps):
y_true.extend(y.numpy())
preds = self.model.predict(x)
y_pred.extend(np.where(preds >= 0.5, 1, 0))
y_proba.extend(preds)
y_true = np.array(y_true)
y_pred = np.array(y_pred).flatten()
y_proba = np.array(y_proba).flatten()
cm = confusion_matrix(y_true, y_pred)
roc_auc = roc_auc_score(y_true, y_proba)
fpr, tpr, _ = roc_curve(y_true, y_proba)
Résultats du modèle CNN¶
## Résultats du modèle CNN - Précision de test: 0.9496221542358398 - Perte de test: 0.14307883381843567
Graphique CNN¶
Comparaison de la précision¶
Conclusion¶
En comparant les deux modèles, nous observons que :
- Le modèle CNN montre une meilleure précision et un score AUC ROC plus élevé.
- Le modèle KNN reste une option valide et plus simple à implémenter.
Recommandations¶
Modèle CNN :
- Plus fiable et précis pour la détection de la pneumonie.
- Peut encore être amélioré avec un entraînement plus long.
Modèle KNN :
- Option simple et rapide à implémenter.
- Utile dans des scénarios avec des ressources informatiques limitées.
Pour des applications nécessitant une haute précision et la capacité de traiter de grands ensembles de données avec des images complexes, le modèle CNN est recommandé. En revanche, pour des scénarios où les ressources informatiques sont limitées et une implémentation rapide est nécessaire, le modèle KNN peut être plus approprié.