Это часть 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.
Преимущества увеличения объема данных:
- Улучшение результатов модели
- Предотвратить переобучение
Для реализации этого мы будем использовать класс ImageDataGenerator из фреймворка Keras. ImageDataGenerator помогает создавать пакеты данных тензорного изображения с увеличением данных в реальном времени. То есть он может выполнять все эти операции:
- Генерация пакетов изображений, указанных во фрейме данных.
- Позволяет использовать основные методы увеличения данных, такие как переворачивание, масштабирование, масштабирование, поворот и т. Д.
- Преобразование значений в каждом пакете так, чтобы их среднее и стандартное отклонение было 1. Это помогает моделировать обучение за счет стандартизации входного распределения.
- Он также преобразует одноканальные рентгеновские изображения (полутоновые) в трехканальный формат, повторяя значения на изображении по всем каналам. Нам это необходимо, потому что предварительно обученная модель, которую мы будем использовать позже для обучения модели, требует трехканальных входных данных.
Реализация 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()
Мы видим, что изображения теперь нормализованы как в обучающем, так и в тестовом генераторах, но мы применили дополнения только к генератору поезда, поскольку нейронная сеть обучается только на обучающих изображениях, и мы не хотим нарушать тестовые или проверочные изображения. .
Изображения нормализованы и дополнены и теперь готовы к загрузке в нейронную сеть. В следующей части мы спроектируем нейронную сеть, чтобы увидеть, насколько хорошо она классифицирует рентгеновские изображения надлежащим образом по всем трем классам. Позже мы также увидим, как использование трансферного обучения улучшает эти результаты.
Использованная литература: