"Машинное обучение"

Машинное обучение/биостатистика на клеточных изображениях для диагностики острого лимфобластного лейкоза

Если вам нравится то, что я пишу, рассмотрите возможность стать участником, используя ссылку ниже:

https://medium.com/@ashu.malgaonkar/membership

Оглавление:

I. Об этом наборе данных

II. Цитирование набора данных

III. Загрузка данных

IV. Обработка данных в Python

V. Машинное обучение

VI. Анализ показателей

VII. Заключение

I. Об этом наборе данных

Острый лимфобластный лейкоз (ОЛЛ) является наиболее распространенным типом рака у детей и составляет примерно 25% всех онкологических заболеваний у детей.

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

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

Всего имеется 15 135 изображений от 118 пациентов с двумя помеченными классами:

  • Нормальная ячейка;
  • Взрыв лейкемии.

II. Цитирование набора данных

Набор данных можно найти здесь:

Классификация лейкозов | Kaggle

Цитирование данных

Цитата публикации

  • Анубха Гупта, Рахул Дуггал, Риту Гупта, Лалит Кумар, Нисарг Тхаккар и Девпракаш Сатпати, «GCTI-SN: нормализация химических и тканевых инвариантных пятен на основе геометрии микроскопических медицинских изображений», находится на рассмотрении.
    Риту Гупта, Прамит Маллик, Рахул Дуггал, Анубха Гупта и Оджасва Шарма, «Нормализация цвета пятен и сегментация плазматических клеток в микроскопических изображениях как прелюдия к разработке автоматизированного инструмента диагностики заболеваний множественной миеломы», 16-й Международный семинар по миеломе (IMW), Индия, март 2017 г.
  • Рахул Дуггал, Анубха Гупта, Риту Гупта, Маня Вадхва и Чираг Ахуджа, «Сегментация перекрывающихся клеточных ядер в микроскопических изображениях с использованием сетей глубокого убеждения», Индийская конференция по компьютерному зрению, графике и обработке изображений (ICVGIP), Индия, декабрь 2016 г.
    Рахул Дуггал, Анубха Гупта и Риту Гупта, «Сегментация перекрывающихся/соприкасающихся ядер лейкоцитов с использованием искусственных нейронных сетей», Серия CME по гемато-онкопатологии, Всеиндийский институт медицинских наук (AIIMS), Нью-Дели, Индия, июль 2016 г.
  • Рахул Дуггал, Анубха Гупта, Риту Гупта и Прамит Маллик, SD-слой: деконволюционный слой окрашивания для CNN в медицинской микроскопии, В: Деското М., Майер-Хейн Л., Франц А., Яннин П., Коллинз Д., Дюшен С. (редакторы) Вычисление медицинских изображений и вмешательство с помощью компьютера — MICCAI 2017, MICCAI 2017. Конспект лекций по информатике, часть III, LNCS 10435, стр. 435–443. Спрингер, Чам. DOI: https://doi.org/10.1007/978-3-319-66179-7_50.

III. Загрузка данных

Перейдите по этой ссылке и скачайте данные: Классификация лейкозов | Kaggle

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

В папке «все» находятся изображения с раком:

В папке «Подол» находятся нераковые изображения:

IV. Обработка данных в Python

Для обработки данных нам понадобятся некоторые пакеты.

Нам понадобится skimage io для чтения изображения и получения пикселей:

from skimage import io

Затем нам нужен пакет для хранения наших данных. Для этого мы можем использовать пакет фрейма данных, такой как pandas:

import pandas as pd

Затем нам нужно, чтобы os указала нам каталог, в котором находятся наши изображения:

import os

Хорошо, теперь, когда у нас есть наши пакеты, давайте создадим переменную для двух наших путей, один для папки «все», а другой для папки «подол»:

pathforall= r'C:\...Desktop\Leukemia\archive\C-NMC_Leukemia\training_data\fold_0\all'
pathforhem= r'C:\...Desktop\Leukemia\archive\C-NMC_Leukemia\training_data\fold_0\hem'

Теперь нам нужно указать Python на эти папки (переменные пути выше) и сохранить в них имена файлов в виде списка. Эти две строки дают вам два списка, один для «всех» изображений, а другой для «подол» изображений:

dir_list=os.listdir(pathforall)
dir_list2=os.listdir(pathforhem)

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

Хорошо, теперь пришло время сохранить данные из этих изображений. Позвольте мне показать вам полный код, а затем рассказать, как я это сделал:

df = pd.DataFrame()
for i in dir_list[:300]:
    img=io.imread(pathforall + "\\" + i)
 
    my_df = pd.DataFrame(img.flatten()).transpose()
    my_df['Class'] = 'ALL'
    my_df=my_df.head(n=1)
    df = df.append(my_df, ignore_index=True)

Итак, давайте рассмотрим это шаг за шагом:

Первая строка в приведенном выше коде создает пустой фрейм данных. Этот фрейм данных с именем df — это то, в чем я буду хранить свои «все» данные.

df = pd.DataFrame()

Затем я инициирую цикл for, который указывает на список из папки «все». Помните, что наш список называется dir_list. Я обработал только часть изображений для своего проекта, так как все 2500 заняли у меня от получаса до часа, чтобы пройти через программу, и я не хотел ждать так долго. Вот что означает [:300], т.е. список на этом закончится:

for i in dir_list[:300]:

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

Строка ниже берет путь для всего текста и добавляет косую черту после него, а затем добавляет «i» из нашего цикла for. Это «i» — это имя файла первого изображения, затем второго изображения, когда цикл запускается во второй раз, затем третьего изображения и т. д., т. е. «i» перебирает имена файлов изображений в пределах папка «все»:

img=io.imread(pathforall + "\\" + i)

IMG — это n-мерный массив, состоящий из пиксельных данных изображения.

Однако нам нужно сгладить это, чтобы оно стало похоже на список. Для этого мы можем использовать img.flatten(). Затем нам нужно сохранить эти значения в виде кадра данных Pandas, чтобы мы могли хранить их и манипулировать ими позже. Однако, когда мы создаем фрейм данных из нашего списка, он будет хранить список в одном столбце. Это не полезно для нас. Мы хотим, чтобы наш список хранился горизонтально в строке, чтобы мы могли иметь наш класс «все/рак» в качестве последнего столбца, а затем использовать алгоритм машинного обучения для его классификации. Для этого нам нужно транспонировать данные. Позвольте мне сначала объяснить, что это будет делать.

Во-первых, массив, который выглядит так:

когда он сплющивается с помощью img.flatten, он будет выглядеть так:

{0,0,0,0…}

Когда это преобразовано во фрейм данных, это будет выглядеть так:

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

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

my_df = pd.DataFrame(img.flatten()).transpose()

Затем мы хотим, чтобы строка, которую мы только что создали, имела правильную метку. В этом случае мы перебираем раковые клетки, поэтому наша метка/класс будет «ВСЕ»:

my_df['Class'] = 'ALL'

Теперь давайте удостоверимся, что мы берем только одну строку, которую мы сделали:

my_df=my_df.head(n=1)

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

df = df.append(my_df, ignore_index=True)

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

Теперь давайте сделаем то же самое для данных «кромки», повторив на пути «кромки»:

df2 = pd.DataFrame()
for i in dir_list2[:300]:
    img2=io.imread(pathforhem + "\\" + i)
 
    my_df2 = pd.DataFrame(img2.flatten()).transpose()
    my_df2['Class'] = 'Not ALL'
    my_df2=my_df2.head(n=1)
    df2 = df2.append(my_df2, ignore_index=True)

Обратите внимание, что это класс «Не все».

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

Теперь, чтобы запустить алгоритм классификации, нам сначала нужно сделать его одним набором данных. Мы можем сделать это с помощью команды concat. Команда concat по сути представляет собой «объединение» в терминах SQL. Он складывает наборы данных друг над другом:

df_stack = pd.concat([df, df2])

Когда вы запустите команду concat, как показано выше, вы заметите следующее в обозревателе переменных:

Обратите внимание на размер. Размер df и df2 равен 300 каждый. Когда вы ставите их друг на друга, получается 600. Это быстрый способ проверить свою работу.

V. Машинное обучение

Алгоритм, который я буду использовать здесь, представляет собой машину опорных векторов:

«Машины опорных векторов Часть 1 (из 3): Основные идеи!!! - YouTube"

Машины опорных векторов, часть 2: полиномиальное ядро ​​(часть 2 из 3) — YouTube

Машины опорных векторов, часть 3: радиальное (RBF) ядро ​​(часть 3 из 3) — YouTube

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

#Store class as y and rest of data as x
X = df_stack.drop('Class', axis=1)
y = df_stack['Class']

Давайте разделим набор данных на тестирование и обучение. Обучающий набор будет составлять 80%, а тестовый набор — 20%. Это означает, что алгоритм будет использовать 80% данных для обучения и построения правил, а затем использовать их для прогнозирования класса в остальных 20%.

#split data
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.20)

Теперь давайте реализуем нашу машину опорных векторов:

from sklearn.svm import SVC

Ядро, которое мы собираемся выбрать:

svclassifier = SVC(kernel='rbf')

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

Машины опорных векторов, часть 3: радиальное (RBF) ядро ​​(часть 3 из 3) — YouTube

svclassifier.fit(X_train, y_train)

А теперь сделаем некоторые прогнозы:

#make predictions
y_pred = svclassifier.predict(X_test)

Давайте теперь посмотрим на метрики из прогноза:

#metrics
from sklearn.metrics import classification_report, confusion_matrix
print(confusion_matrix(y_test,y_pred))
print(classification_report(y_test,y_pred))

Распечатка показателей выглядит так:

VI. Анализ показателей

Посмотрите на матрицу путаницы:

[[59 5]

[16 40]]

В sklearn прогнозируемая метка находится вверху, а фактическая метка сбоку:

Это означает, что на тестовых данных алгоритм имел следующую точность:

Accuracy --> (59+40)/(59+5+16+40) = 82.5%

Чувствительность = количество истинных положительных результатов / (количество истинных положительных результатов + количество ложноотрицательных результатов)

Sensitivity --> 59 / (59 + 5) = 59/64 = 92%

Специфика = количество истинно отрицательных результатов / (количество истинно отрицательных результатов + количество ложноположительных результатов)

Specificity --> 40 / (16+40) = 40/56 = 71%

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

VII. Вывод:

Этот тест действительно хорошо подходит для диагностики ВСЕХ случаев, когда у человека есть ВСЕ, т. е. он имеет хорошую чувствительность на уровне 92 %. Однако, когда у человека НЕТ ВСЕХ, это может иногда давать ложноположительный результат.

Другие статьи:

1 — Как обнаружить различия в изображениях с помощью Python | Ашутош Малгаонкар | ноябрь 2021 г. | Навстречу ИИ

2 — Как создать систему определения местоположения для города | Ашутош Малгаонкар | Навстречу ИИ