Это часть 5 применения глубокого обучения в области рентгеновских изображений. Здесь основное внимание будет уделено различным способам реализации увеличения данных.

Мы видели в предыдущей части - части 4 - https://towardsdatascience.com/deep-learning-in-healthcare-x-ray-imaging-part-4-the-class-imbalance-problem-364eff4d47bb, как решить Проблема несбалансированности классов. В этом разделе мы сосредоточимся на нормализации изображения и увеличении данных.

После того, как проблема дисбаланса классов будет решена, мы рассмотрим способы улучшить производительность нейронной сети, а также сделать ее быстрее. У нас уже есть аналогичное количество изображений в трех классах данных обучения - 1. Нормальный (без инфекции), 2. Бактериальная пневмония, 3. Вирусная пневмония.

Масштабирование / нормализация изображения:

Нейронные сети работают лучше всего, когда все функции находятся в одном масштабе. Точно так же алгоритмы оптимизации, такие как градиентный спуск, работают очень хорошо, когда объекты центрированы на среднем нуле со стандартным отклонением, равным единице, т. Е. Данные имеют свойства стандартного нормального распределения.

Это можно сделать несколькими способами, как показано ниже.

Случай 1: не рекомендуется

scaled_dataset = (dataset - dataset_mean) / dataset_std_deviation

train, test = split(scaled_dataset)

Весь набор данных масштабируется, а затем разделяется на набор для обучения и тестирования.

Случай 2: не рекомендуется

train, test = split(dataset)

scaled_train =  (train - train_mean) / train_std_deviation

scaled_test = (test - test_mean) / test_std_deviation

Набор данных разделяется на обучающий и тестовый, а затем обучающий набор и набор для тестирования масштабируются отдельно.

Случай 3: рекомендуется

train, test = split(dataset)
scaled_train =  (train - train_mean) / train_std_deviation

scaled_test = (test - train_mean) / train_std_deviation

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

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

Тестовые данные - это «невидимые данные» для модели, и мы используем тестовые данные, чтобы проверить, как модель работает с невидимыми данными, то есть они дают хорошую оценку, готова ли модель к использованию в реальных сценариях.

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

Таким образом, лучший способ решить эту проблему - использовать случай 3 и нормализовать входящие тестовые данные, используя статистику, вычисленную на основе обучающего набора. Затем мы будем использовать эту статистику для преобразования наших тестовых данных и любых будущих данных позже.

Увеличение данных:

Увеличение данных - это стратегия, которая позволяет практикам значительно увеличить разнообразие данных, доступных для обучающих моделей, без фактического сбора новых данных. [1]

В части 4 (https://towardsdatascience.com/deep-learning-in-healthcare-x-ray-imaging-part-4-the-class-imbalance-problem-364eff4d47bb) мы увидели, как мы можем создавать искусственные изображения с помощью увеличения данных. Мы использовали OpenCV для поворота, перевода, отражения и размытия изображений. Здесь мы рассмотрим, как увеличение данных выполняется в Keras.

Преимущества увеличения объема данных:

  1. Улучшение результатов модели
  2. Предотвратить переобучение

Для реализации этого мы будем использовать класс ImageDataGenerator из фреймворка Keras. ImageDataGenerator помогает создавать пакеты данных тензорного изображения с увеличением данных в реальном времени. То есть он может выполнять все эти операции:

  1. Генерация пакетов изображений, указанных во фрейме данных.
  2. Позволяет использовать основные методы увеличения данных, такие как переворачивание, масштабирование, масштабирование, поворот и т. Д.
  3. Преобразование значений в каждом пакете так, чтобы их среднее и стандартное отклонение было 1. Это помогает моделировать обучение за счет стандартизации входного распределения.
  4. Он также преобразует одноканальные рентгеновские изображения (полутоновые) в трехканальный формат, повторяя значения на изображении по всем каналам. Нам это необходимо, потому что предварительно обученная модель, которую мы будем использовать позже для обучения модели, требует трехканальных входных данных.

Реализация ImageDataGenerator:

Приведенный ниже код является продолжением кода из части 3 и части 4:

Ссылка на часть 3 - https://towardsdatascience.com/deep-learning-in-healthcare-x-ray-imaging-part-3-analyzing-images-using-python-915a98fbf14c

Ссылка на часть 4 - https://towardsdatascience.com/deep-learning-in-healthcare-x-ray-imaging-part-4-the-class-imbalance-problem-364eff4d47bb

def get_train_generator(X_train,y_train, batch_size = 32, shuffle = True, seed = 1):
      
    print("getting train generator...") 
    # normalize and augment images
    image_generator = ImageDataGenerator(
        samplewise_center=True,
        samplewise_std_normalization= True,
        rotation_range = 15,
        width_shift_range=0.2,
        height_shift_range=0.2,
        shear_range=0.2,
        zoom_range=0.2,
        fill_mode="nearest",
        cval=0.0,
        rescale = 0.2)
    
    generator = image_generator.flow(
            X_train,
            y=y_train,
            shuffle=shuffle,
            batch_size=batch_size,
            seed=seed
            )
    
    return generator

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

samplewise_center=True,
samplewise_std_normalization= True

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

Вот как Keras выполняет нормализацию / стандартизацию / масштабирование изображения без необходимости использования каких-либо формул.

Визуализация того, как работает ImageDataGenerator:

Используя одно изображение кошки, мы увидим, как работают различные дополнения в ImageDataGenerator -

#importing the necessary libraries
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

from tensorflow.keras.preprocessing.image import load_img
from tensorflow.keras.preprocessing.image import img_to_array
from tensorflow.keras.preprocessing.image import ImageDataGenerator
#define a function to display 9 augmented images
def show_image(iterator):

    # generate samples and plot
    for i in range(9):
        plt.subplot(330 + 1 + i)
        batch = iterator.next()
        image = batch[0].astype('uint8')
        plt.imshow(image)
    plt.show()
#load and display the original image
img = load_img('cat.jpg') 
plt.imshow (img) 
data = img_to_array(img) 
samples = np.expand_dims(data, 0)

# height_shift_range
datagen = ImageDataGenerator(height_shift_range=0.5)
iterator = datagen.flow(samples, batch_size=1)

show_image(iterator)

# width_shift_range
datagen = ImageDataGenerator(width_shift_range=0.5)
iterator = datagen.flow(samples, batch_size=1)

show_image(iterator)

# rotation_range 
datagen = ImageDataGenerator(rotation_range = 50)
iterator = datagen.flow(samples, batch_size=1)

show_image(iterator)

# shear_range 
datagen = ImageDataGenerator(shear_range = 50)
iterator = datagen.flow(samples, batch_size=1)

show_image(iterator)

# brightness_range 
datagen = ImageDataGenerator(brightness_range = [0.3,1.9])
iterator = datagen.flow(samples, batch_size=1)

show_image(iterator)

# zoom_range
datagen = ImageDataGenerator(zoom_range = [0.5,1.5])
iterator = datagen.flow(samples, batch_size=1)

show_image(iterator)

# flip
datagen =ImageDataGenerator(horizontal_flip=True,vertical_flip=True)
iterator = datagen.flow(samples, batch_size=1)

show_image(iterator)

По изображениям, я считаю, понятно, что делает каждая функция в ImgaeDataGenerator. Для получения дополнительной информации перейдите по следующей ссылке - https://keras.io/api/preprocessing/image/.

Возвращаясь к рентгеновским снимкам, мы уже видели, как реализовать ImageDataGenerator на обучающей выборке. Но мы не должны напрямую реализовывать его на тестовом наборе, как показано в случае 3 масштабирования / нормализации изображения (описанном выше). Поэтому мы создаем отдельный генератор для набора тестов и валидации.

def get_test_val_generator(X_train,y_train,X_test,y_test,X_val,y_val,
                      batch_size=32, seed=1, sample_size=100):
    
    raw_train_generator = ImageDataGenerator().flow(
        X_train,y_train, 
        batch_size=sample_size, 
        shuffle=False)
    
    # get data sample
    batch = raw_train_generator.next()
    data_sample = batch[0]

    # use sample to fit mean and std for test set generator
    image_generator = ImageDataGenerator(
        featurewise_center=True,
        featurewise_std_normalization= True)
    
    # fit generator to sample from training data
    image_generator.fit(data_sample)
    
    # get test generator
    test_generator = image_generator.flow(
            X_test,
            y=y_test,
            batch_size=batch_size,
            shuffle=False,
            seed=seed)
    
    #get validation generator
    val_generator = image_generator.flow(
            X_val,
            y=y_val,
            batch_size=batch_size,
            shuffle=False,
            seed=seed)
    
    return test_generator,val_generator

В этой реализации мы используем статистику обучающего набора и применяем его к тестовым и проверочным наборам. В идеале мы хотели бы вычислить среднее значение нашей выборки и стандартное отклонение, используя весь обучающий набор.
Однако, поскольку это очень велико, это потребует очень много времени.
Итак, мы берем случайную выборку из набор данных (в данном случае 100 изображений) и вычислите среднее значение выборки и стандартное отклонение выборки.

Затем мы создаем генераторы поездов, тестов и валидации.

#create the train, test and validation generator  
train_generator = get_train_generator(X_train,y_train) 
test_generator,valid_generator = get_test_val_generator(X_train,y_train,X_test,y_test,X_val,y_val)

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

# Displays 9 generated train_generator images 

print('Display Random Images')

# Adjust the size of your images
plt.figure(figsize=(20,10))

for i in range(12):
    num = random.randint(1,30)
    plt.subplot(3,4, i + 1)
    
    x,y = train_generator.__getitem__(num)
    
    plt.imshow(x[num],cmap='gray')
    plt.axis('off')
    
# Adjust subplot parameters to give specified padding
plt.tight_layout()

# Displays 9 generated test_generator images   
print('Display Random Images')  
# Adjust the size of your images 
plt.figure(figsize=(20,10))  
   for i in range(12):     
   num = random.randint(1,17)     
   plt.subplot(3,4, i + 1)          
   x,y = test_generator.__getitem__(num)
   plt.imshow(x[num],cmap='gray')     
   plt.axis('off')    
  
# Adjust subplot parameters to give specified padding plt.tight_layout()

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

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

Использованная литература:

  1. Https://bair.berkeley.edu/blog/2019/06/07/data_aug