Обнаружение пневмонии на рентгеновских снимках - ConvNets и Transfer Learning

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

По данным ЮНИСЕФ, пневмония вызывает больше смертей среди детей, чем ВИЧ / СПИД и малярия вместе взятые. Одна из самых насущных потребностей в борьбе с пневмонией - это экономичный способ диагностики рентгеновских изображений. Современные методы требуют высококвалифицированного персонала и непрактичны для многих регионов мира.

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

Постановка задачи

Взгляните на эти две фотографии. Как вы думаете, какой из них инфицирован пневмонией?

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

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

Набор данных

Наше путешествие началось с набора данных Kaggle, доступного здесь [1]. Он состоит из 5'863 рентгеновских снимков легких, сделанных у группы педиатрических пациентов в возрасте от 1 до 5 лет. Все изображения были промаркированы двумя специалистами, чтобы минимизировать риск ошибки при маркировке. Данные уже были разделены для нас на наборы данных для обучения, проверки и тестирования.

Наш подход

Сверточная нейронная сеть (CNN или ConvNet) кажется очевидным выбором, учитывая недавние достижения в классификации изображений с использованием глубокого обучения.

CNN работают по принципу, который, кажется, немного похож на то, как работает зрительная кора головного мозга у людей и животных. Мы не будем давать еще одно объяснение того, как работает ConvNet - уже есть много хороших статей по этой теме. Например - загляните сюда [2].

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

Мы используем одну из самых простых предварительно обученных сетей под названием VGG16 [3].

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

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

Мы использовали Tensorflow для предварительной обработки изображений и операций связывания с входными конвейерами Tensorflow. Для самого обучения мы выбрали простой вариант и использовали VGG16, который поставляется с библиотекой Keras.

import keras
from keras import backend as K
from keras.models import Model
from keras.layers import Flatten, Dense
from keras.applications.vgg16 import VGG16

NUM_CLASSES = 2

base_model = VGG16(weights='imagenet', include_top=False, input_shape=(150, 150, 3))

x = base_model.output
x = Flatten()(x)
x = Dense(NUM_CLASSES, activation='softmax')(x)

model = Model(inputs=base_model.input, outputs=x)

model.summary()

Чтобы уменьшить количество обучаемых параметров, мы заблокируем первые 20 слоев модели (вплоть до фазы Flatten).

for layer in model.layers[0:20]:
    layer.trainable = False

Обучение модели так же просто, как

model.fit(
    x=x_train, y=y_train,
    validation_split=0.2,
    shuffle=True,
    batch_size=64,
    epochs=20,
    verbose=1
)

Сразу после первой попытки мы достигли точности классификации 80%. Затем мы использовали несколько приемов для улучшения конечных характеристик модели. Мы представили:

  • Функция взвешенной стоимости для предотвращения смещения в сторону более популярного класса в несбалансированном наборе данных (в 2,5 раза больше примеров класса PNEUMONIA, чем NORMAL)
  • Регуляризация CNN с дополнительными слоями Dropout и Batch Normalization, чтобы избежать переобучения тестовым примерам.
  • Увеличение данных с помощью ImageDataGenerator [5] для увеличения разнообразия изображений, манипулируя ими несколькими способами - переворачиванием, изменением размера, случайным вращением и т. Д.

В конечном итоге мы достигли точности 91% на тестовом наборе данных.

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

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

[1]: https://www.kaggle.com/paultimothymooney/chest-xray-pneumonia/home

[2]: https://medium.freecodecamp.org/an-intuitive-guide-to-convolutional-neural-networks-260c2de0a050

[3]: http://www.image-net.org/

[4]: https://healthitanalytics.com/news/deep-learning-for-medical-imaging-fares-poorly-on-external-data

[5]: https://keras.io/preprocessing/image/

Если вас интересуют другие интересные вещи, которые мы делаем в Unit8, посетите наш сайт http://unit8.co