Обнаружение рака легких с использованием сверточной нейронной сети (CNN)

Опубликовано: 14 Декабря, 2022

Компьютерное зрение — это одно из приложений глубоких нейронных сетей, которое позволяет нам автоматизировать задачи, которые ранее требовали многолетнего опыта, и одно из таких применений для прогнозирования наличия раковых клеток.

В этой статье мы узнаем, как создать классификатор, используя простую нейронную сеть свертки, которая может классифицировать нормальные ткани легких от раковых. Этот проект был разработан с использованием совместной работы, а набор данных был взят из Kaggle, ссылка на который также была предоставлена.

Процесс, который будет сопровождаться для создания этого классификатора:

Используемые модули

Библиотеки Python позволяют нам очень легко обрабатывать данные и выполнять типичные и сложные задачи с помощью одной строки кода.

  • Pandas эта библиотека помогает загружать фрейм данных в формате 2D-массива и имеет несколько функций для выполнения задач анализа за один раз.
  • Numpy массивы Numpy очень быстрые и могут выполнять большие вычисления за очень короткое время.
  • Matplotlib эта библиотека используется для рисования визуализаций.
  • Sklearn — этот модуль содержит несколько библиотек с предварительно реализованными функциями для выполнения задач от предварительной обработки данных до разработки и оценки моделей.
  • OpenCV это библиотека с открытым исходным кодом, в основном предназначенная для обработки и обработки изображений.
  • Tensorflow — это библиотека с открытым исходным кодом, которая используется для машинного обучения и искусственного интеллекта и предоставляет ряд функций для реализации сложных функций с помощью одной строки кода.

Python3




import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from PIL import Image
from glob import glob
 
from sklearn.model_selection import train_test_split
from sklearn import metrics
 
import cv2
import gc
import os
 
import tensorflow as tf
from tensorflow import keras
from keras import layers
 
import warnings
warnings.filterwarnings("ignore")

Импорт набора данных

Набор данных, который мы будем здесь использовать, был взят с https://www.kaggle.com/datasets/andrewmvd/lung-and-colon-cancer-histopathological-images. Этот набор данных включает 5000 изображений для трех классов заболеваний легких:

  • Нормальный класс
  • Аденокарциномы легких
  • Плоскоклеточный рак легкого

Эти изображения для каждого класса были разработаны из 250 изображений путем выполнения над ними увеличения данных. Вот почему мы больше не будем использовать Data Augmentation для этих изображений.

Python3




from zipfile import ZipFile
 
data_path = "lung-and-colon-cancer-histopathological-images.zip"
 
with ZipFile(data_path,"r") as zip:
  zip.extractall()
  print("The data set has been extracted.")

Выход:

The data set has been extracted.

Визуализация данных

В этом разделе мы попытаемся понять визуализацию некоторых изображений, которые были предоставлены нам для создания классификатора для каждого класса.

Python3




path = "lung_colon_image_set/lung_image_sets"
classes = os.listdir(path)
classes

Выход:

["lung_n", "lung_aca", "lung_scc"]

Вот три класса, которые у нас есть.

Python3




path = "/lung_colon_image_set/lung_image_sets"
 
for cat in classes:
    image_dir = f"{path}/{cat}"
    images = os.listdir(image_dir)
 
    fig, ax = plt.subplots(1, 3, figsize=(15, 5))
    fig.suptitle(f"Images for {cat} category . . . .", fontsize=20)
 
    for i in range(3):
        k = np.random.randint(0, len(images))
        img = np.array(Image.open(f"{path}/{cat}/{images[k]}"))
        ax[i].imshow(img)
        ax[i].axis("off")
    plt.show()

Выход:

Изображения для категории lung_n

Изображения для категории lung_aca

Изображения для категории lung_scc

Приведенный выше вывод может отличаться, если вы будете запускать его в своей записной книжке, потому что код был реализован таким образом, что он будет отображать разные изображения каждый раз, когда вы перезапускаете код.

Подготовка данных для обучения

В этом разделе мы преобразуем данные изображения в массивы пикселей NumPy после изменения их размера, потому что обучение глубокой нейронной сети на изображениях большого размера крайне неэффективно с точки зрения вычислительных затрат и времени.

Для этой цели мы будем использовать библиотеку OpenCV и библиотеку Python Numpy. Кроме того, после того, как все изображения будут преобразованы в нужный формат, мы разделим их на данные обучения и проверки, чтобы мы могли оценить производительность нашей модели.

Python3




IMG_SIZE = 256
SPLIT = 0.2
EPOCHS = 10
BATCH_SIZE = 64

Некоторые из гиперпараметров, которые мы можем настроить здесь для всей записной книжки.

Python3




X = []
Y = []
 
for i, cat in enumerate(classes):
  images = glob(f"{path}/{cat}/*.jpeg")
 
  for image in images:
    img = cv2.imread(image)
     
    X.append(cv2.resize(img, (IMG_SIZE, IMG_SIZE)))
    Y.append(i)
 
X = np.asarray(X)
one_hot_encoded_Y = pd.get_dummies(Y).values

Одно горячее кодирование поможет нам обучить модель, которая может предсказывать мягкие вероятности того, что изображение относится к каждому классу с наибольшей вероятностью для класса, к которому оно действительно принадлежит.

Python3




X_train, X_val, Y_train, Y_val = train_test_split(X, one_hot_encoded_Y,
                                                  test_size = SPLIT,
                                                  random_state = 2022)
print(X_train.shape, X_val.shape)

Выход:

(12000, 256, 256, 3) (3000, 256, 256, 3)

На этом шаге мы добьемся автоматического перемешивания данных, потому что функция train_test_split случайным образом разделяет данные в заданном соотношении.

Разработка модели

Начиная с этого шага, мы будем использовать библиотеку TensorFlow для построения нашей модели CNN. Платформа Keras библиотеки тензорных потоков содержит все функции, которые могут понадобиться для определения архитектуры сверточной нейронной сети и ее обучения данным.

Архитектура модели

Мы реализуем последовательную модель, которая будет содержать следующие части:

  • Три сверточных слоя, за которыми следуют слои MaxPooling.
  • Слой Flatten для выравнивания выходных данных сверточного слоя.
  • Тогда у нас будет два полносвязных слоя, за которыми следует вывод сглаженного слоя.
  • Мы включили несколько слоев BatchNormalization, чтобы обеспечить стабильное и быстрое обучение, и слой Dropout перед последним слоем, чтобы избежать любой возможности переобучения.
  • Последний слой — это выходной слой, который выводит мягкие вероятности для трех классов.

Python3




model = keras.models.Sequential([
    layers.Conv2D(filters=32,
                  kernel_size=(5, 5),
                  activation="relu",
                  input_shape=(IMG_SIZE,
                               IMG_SIZE,
                               3),
                  padding="same"),
    layers.MaxPooling2D(2, 2),
 
    layers.Conv2D(filters=64,
                  kernel_size=(3, 3),
                  activation="relu",
                  padding="same"),
    layers.MaxPooling2D(2, 2),
 
    layers.Conv2D(filters=128,
                  kernel_size=(3, 3),
                  activation="relu",
                  padding="same"),
    layers.MaxPooling2D(2, 2),
 
    layers.Flatten(),
    layers.Dense(256, activation="relu"),
    layers.BatchNormalization(),
    layers.Dense(128, activation="relu"),
    layers.Dropout(0.3),
    layers.BatchNormalization(),
    layers.Dense(3, activation="softmax")
])

Напечатаем сводку по архитектуре модели:

Python3




model.summary()

Выход:

Model: “sequential”

_________________________________________________________________

 Layer (type)                Output Shape              Param #   

=================================================================

 conv2d (Conv2D)             (None, 256, 256, 32)      2432      

                                                                 

 max_pooling2d (MaxPooling2D  (None, 128, 128, 32)     0         

 )                                                               

                                                                 

 conv2d_1 (Conv2D)           (None, 128, 128, 64)      18496     

                                                                 

 max_pooling2d_1 (MaxPooling  (None, 64, 64, 64)       0         

 2D)                                                             

                                                                 

 conv2d_2 (Conv2D)           (None, 64, 64, 128)       73856     

                                                                 

 max_pooling2d_2 (MaxPooling  (None, 32, 32, 128)      0         

 2D)                                                             

                                                                 

 flatten (Flatten)           (None, 131072)            0         

                                                                 

 dense (Dense)               (None, 256)               33554688  

                                                                 

 batch_normalization (BatchN  (None, 256)              1024      

 normalization)                                                   

                                                                 

 dense_1 (Dense)             (None, 128)               32896     

                                                                 

 dropout (Dropout)           (None, 128)               0         

                                                                 

 batch_normalization_1 (Batc  (None, 128)              512       

 hNormalization)                                                 

                                                                 

 dense_2 (Dense)             (None, 3)                 387       

                                                                 

=================================================================

Total params: 33,684,291

Trainable params: 33,683,523

Non-trainable params: 768

_________________________________________________________________

Сверху мы можем видеть изменение формы входного изображения после прохождения через разные слои. Разработанная нами модель CNN содержит около 33,5 миллионов параметров. Именно это огромное количество параметров и сложность модели помогают получить высокопроизводительную модель, которая используется в реальных приложениях.

Python3




keras.utils.plot_model(
    model,
    show_shapes = True,
    show_dtype = True,
    show_layer_activations = True
)

Выход:

Python3




model.compile(
    optimizer = "adam",
    loss = "categorical_crossentropy",
    metrics = ["accuracy"]
)

При составлении модели мы предоставляем эти три основных параметра:

  • оптимизатор — это метод, который помогает оптимизировать функцию стоимости с помощью градиентного спуска.
  • потеря — функция потерь, с помощью которой мы отслеживаем, улучшается ли модель с обучением или нет.
  • Метрики — это помогает оценить модель, предсказывая данные обучения и проверки.

Перезвонить

Обратные вызовы используются для проверки того, улучшается ли модель с каждой эпохой или нет. Если нет, то какие необходимые шаги необходимо предпринять, например, ReduceLROnPlateau еще больше снижает скорость обучения. Даже в этом случае, если производительность модели не улучшится, обучение будет остановлено EarlyStopping. Мы также можем определить некоторые пользовательские обратные вызовы, чтобы остановить обучение между ними, если желаемые результаты были получены раньше.

Python3