Uploaded by Александр Петров

Работа с последовательной нейронной сетью на примере классификации электроэнцефалограмм

advertisement
1
Работа с последовательной нейронной
сетью на примере классификации
электроэнцефалограмм
1 Последовательные нейронные сети
Последовательные искусственные нейронные сети представляют собой
устройства
параллельных
вычислений,
состоящие
из
множества
взаимодействующих простых искусственных нейронов. Искусственный
нейрон является упрощенной моделью естественного нейрона и с
математической точки зрения представляет некоторую нелинейную функцию
от единственного аргумента - линейной комбинации всех входных сигналов.
Данную функцию называют функцией активации или функцией срабатывания,
передаточной функцией. Полученный результат посылается на единственный
выход (рисунок 1).
f
f (net)
Рисунок 1 – Структурная схема искусственного нейрона
Линейная комбинация входных сигналов (значение комбинированного
входа) определяется выражением:
2
n
net   xii .
(1.1)
i 1
где 
- весовой коэффициент. Полученное значение подвергается
нелинейному преобразованию с помощью функции активации
f.
В
большинстве случаев она является монотонно возрастающей и имеет область
значений [−1, 1] или [0, 1]. Примеры функций активации нейронов:
Линейная передаточная функция
Сигнал на выходе нейрона линейно связан с взвешенной суммой
сигналов на его входе:
f  x   t  net ,
где t - параметр функции.
Рисунок 2 – Линейная передаточная функция
Пороговая передаточная функция
Другое название — функция Хевисайда. Представляет собой перепад.
До тех пор, пока взвешенный сигнал на входе нейрона не достигает
некоторого уровня T , сигнал на выходе равен нулю. Как только сигнал на
входе нейрона превышает указанный уровень — выходной сигнал
3
скачкообразно изменяется на единицу. Математическая запись этой функции
выглядит так:
1 if net  T
f  net   
.
else
0
Рисунок 3 – Пороговая функция активации
Сигмоидальная передаточная функция
Один из самых часто используемых на данный момент типов
передаточных функций. Введение функций сигмоидального типа было
обусловлено ограниченностью нейронных сетей с пороговой функцией
активации нейронов — при такой функции активации любой из выходов сети
равен либо нулю, либо единице, что ограничивает использование сетей не в
задачах классификации. Математически сигмоидальную функцию можно
выразить так
f  net  
1
.
1  exp  t  net 
4
Здесь t — это параметр функции, определяющий её крутизну. Когда t
стремится к бесконечности, функция вырождается в пороговую. При t  0
сигмоида вырождается в постоянную функцию со значением 0,5. Область
значений данной функции находится в интервале (0,1). Изображение функции
активации представлено на рисунке 4.
Рисунок 4 – Сигмоидальная функция активации
Существует множество функций активации нейронов. Выше были
рассмотрены
самые
распространённые.
Благодаря
использованию
нелинейных функций активации значения на выходе всех нейронов
нейронной сети имеют один и тот же динамический диапазон. Кроме-того,
использование нелинейных функций активации расширяет возможности
многослойных нейронных сетей.
При использовании многослойных нейронных сетей в случае линейных
функций активности можно найти один слой весов, дающий тот же результат,
что и сеть с несколькими слоями. Другими словами, многослойная сеть с
линейными функциями активности сможет решать только те проблемы,
5
которые могут быть решены однослойной сетью (т.е. сетью, имеющей только
входные и выходные элементы) [1].
Изображение многослойной нейронной сети представлено на рисунке
5.
0
3
0, 4
3, 6
3, 8
0, 5
3, 7
4
1 1, 4
1, 5
2, 4
2
4, 6
f (net4) 
4, 7
4, 8
5 
6
f (net6)
O6
7
f (net7)
O7
5, 6
2, 5
5, 7
f (net5)
5, 8
8
f (net8)
O8
Рисунок 5 – Многослойная нейронная сеть
Данная нейронная сеть состоит из трех слоев. Как правило
многослойные нейронные сети в каждом слое содержат еще и элемент
смещения. На рисунке 5 он обозначен белым кружком. Элемент смещения не
связан с нейронами из предыдущего слоя и всегда имеет единичное значение
на выходе. Нулевой слой представленной нейронной сети содержит два
входных нейрона и один элемент смещения, таким образом, данная
нейронная сеть принимает на вход вектор, содержащий две компоненты.
Нейроны входного слоя нейронной сети никак не модифицируют сигнал, а
лишь передают его нейронам следующих слоев, называемых скрытыми.
На рисунке 5 каждый искусственный нейрон имеет свой порядковый
номер j  0...8. В соответствии с такой нумерацией сигнал на выходе j -го
нейрона скрытого слоя будет равен
6


о j  f   xi  i , j  ,
 i

где i - порядковый номер нейрона из предыдущего слоя нейронной сети, f функция активации, которая чаще всего является сигмоидной ( t  0 ), xi входной сигнал, который в зависимости от расположения нейрона в
нейронной сети может быть равен либо входному отсчету, либо значению с
выхода нейрона предыдущего слоя.
Чаще всего с помощью последовательных нейронных сетей решают три
задачи: задачу классификации (распознавания), задачу предсказания и задачу
аппроксимации данных.
Изображенная на рисунке 5 нейронная сеть может подразделять
входные образцы данных на три класса, поскольку содержит три нейрона в
последнем слое. В случае решения задачи классификации с помощью
нейронной сети вектор, полученный на ее выходе, требуется преобразовать с
помощью функции softmax. Эта функция преобразует вектор o с выхода
нейронной сети к вектору σ той же размерности, где каждая координата
полученного вектора  i представлена вещественным числом в интервале
[0,1] и сумма координат равна 1. Т.е. каждая координата  i , полученного
вектора, является вероятностью, с которой объект принадлежит к классу с
порядковым номером i. Функция softmax определяется выражением:
  o i 
eoi
,
K 1
e
ok
k 0
где K - количество нейронов в последнем слое нейронной сети (количество
распознаваемых образов). Номер класса, к которому относится входной
образец, определяется индексом максимального элемента вектора σ.
7
2 Обучение последовательной нейронной сети
Наиболее часто нейронные сети реализуют программно с помощью
языков программирования Python и С++. При инициализации нейронной сети
указывают количество ее слоев, количество нейронов в каждом слое
нейронной сети, функцию активации нейронов. Чаще всего все нейроны
имеют одинаковую функцию активации. Весовые коэффициенты нейронов
принимают случайные значения в диапазоне [-0,3; 0,3] и корректируются в
процессе обучения нейронной сети.
Для обучения нейронных сетей требуются значительные объемы
обучающих данных, содержащие от тысячи до десятков тысяч образцов.
Задача обучения нейронной сети сводится к поиску значений весовых
коэффициентов ее нейронов, при которых она успешно решает требуемые
задачи. Последовательные нейронные сети обучаются в соответствии с
алгоритмом обратного распространения ошибки [1]. Подробный анализ
алгоритма обратного распространения ошибки будет дан в следующей
лабораторной работе, здесь ограничимся лишь кратким обзором процесса
обучения нейронной сети.
При обучении нейронной сети каждому вектору X   xl  , подаваемому
на ее вход, ставится в соответствие целевой вектор T  t j  , который должен
быть поучен на ее выходе. При этом на выходе нейронной сети получаем
вектор O  o j  , значения которого отличаются от требуемого вектора T .
Тогда ошибка (потеря) нейронной сети для образца
p может быть
определена по формуле
Ep 
2
1
t

o


 j j ,
2 j
(2.1)
8
а полная ошибка будет равна
E   Ep .
(2.2)
Алгоритм обратного распространения ошибки корректирует веса
нейронной сети каждый раз при подаче на ее вход какого-либо вектора
входных отчетов из множества обучающих данных, минимизируя ошибку E p .
При этом в результате обучения нейронной сети может возникнуть ситуация
переобучения. Переобученная нейронная сеть хорошо классифицирует
данные, которые использовались в процессе ее обучения, при этом не
справляется с задачей классификации новых данных, отсутствующих в
обучающей выборке. Для исключения подобной ситуации, данные,
используемые в процессе ее обучения, делят на обучающие и проверочные.
Проверочные данные используются лишь для вычисления ошибки нейронной
сети. Последовательность шагов при обучении нейронной сети выглядит
следующим образом:
Шаг 1. Разграничиваем данные на обучающие и проверочные (обычно
проверочные данные составляют 25% от обучающих);
Шаг 2. Случайным образом выбираем из массива обучающих данных
отсчеты и подаем их на вход нейронной сети. При этом для каждого отчета
(входного вектора) известен целевой вектор T нейронной сети. На вход
нейронной сети требуется подать все отсчеты из множества обучающих
данных. Для каждого отсчета вычисляется ошибка нейронной сети в
соответствии с выражением (2.1). После этого может быть сделана
корректировка весовых значений нейронной сети в соответствие с
алгоритмом обратного распространения ошибки. После того, как все отсчеты
из обучающих данных были поданы на вход нейронной сети, вычисляется
общая ошибка нейронной сети в соответствии с выражением (2.2).
9
Полученное значение запоминается в памяти ЭВМ. Если нейронная сеть
решает задачу классификации, то в память ЭВМ записывается также
вероятность успешного классификации отсчетов из обучающих данных. Шаг 2
принято называть этапом обучения.
Шаг 3. В соответствие с выражением (2.2) вычисляется общая ошибка
нейронной
сети
для
проверочных
данных.
Полученное
значение
запоминается в памяти ЭВМ. Если нейронная сеть решает задачу
классификации, то в память ЭВМ записывается также вероятность успешного
классификации отсчетов из проверочных данных. Шаг 3 приято называть
этапом проверки.
Шаги 2 и 3 в общем случае принято назвать эпохой.
Шаг 4. Повторяем Шаг 2 и Шаг 3 несколько раз (100 или 200). Строим
зависимости вероятности правильной классификации нейронной сети от
номера эпохи на этапе обучения и проверки. Строим зависимости общей
ошибки (потери) нейронной сети от номера эпохи на этапе обучения и
проверки.
Ниже представлены примеры графиков обучения нейронной сети [2].
Рисунок 6 - Потери на этапах обучения и проверки
10
Рисунок 7 - Точность на этапах обучения и проверки
Как видите, на этапе обучения потери снижаются с каждой эпохой, а
точность растет. Именно такое поведение ожидается от оптимизации
нейронной сети с помощью алгоритма обратного распространения ошибки:
величина, которую вы пытаетесь минимизировать, должна становиться все
меньше с каждой итерацией. Но это не относится к потерям и точности на
этапе проверки: похоже, что они достигли пика в четвертую эпоху. Это пример
того, о чем мы предупреждали выше: модель, показывающая хорошие
результаты на обучающих данных, не обязательно будет показывать такие же
хорошие результаты на данных, которые не видела прежде. Выражаясь
точнее, в данном случае наблюдается переобучение: после второй эпохи
произошла чрезмерная оптимизация на обучающих данных, и в результате
получилось представление, характерное для обучающих данных, не
обобщающее данные за пределами обучающего набора [2].
В данном случае для предотвращения переобучения можно прекратить
обучение после третьей эпохи.
Отметим, что в настоящее время не существует точных правил по
выбору количества слоев нейронной сети, функций активации нейронов,
количества слоев в каждом скрытом слое нейронной сети. Как правило
архитектура нейронной сети для решения определенной задачи выбирается
11
эмпирически. Ниже будет представлен пример одной из возможных
архитектур
последовательной
нейронной
сети
для
классификации
электроэнцефалограмм.
3 Проблемы классификации в электроэнцефалографии
В современной литературе по клинической электроэнцефалографии
электроэнцефалограммы принято делить на три класса: нормальные ЭЭГ,
пограничные ЭЭГ и патологические ЭЭГ. Решение о классе ЭЭГ принимается на
основе визуальной оценки их форм. В литературе по клинической
электроэнцефалографии
приводятся
вербальные
описания
форм
электроэнцефалограмм, но основе которых выполняется их классификация.
Как правило «нормальные» ЭЭГ характеры для здорового человека без
церебральной патологии. «Пограничные» ЭЭГ не указывают явным образом
на церебральную патологию, но при этом являются указанием на проведение
дополнительных
компьютерной
клинических
и
исследований
магнитно-резонансной
с
помощью
томографии.
методов
«Пограничные»
электроэнцефалограммы могут наблюдаться как у здорового пациента, так и
у пациента с различными патологиями центральной нервной системы,
которые
выявляются
с
помощью
дополнительных
исследований.
Патологические ЭЭГ явным образом указывают на наличие серьезных
заболеваний центральной нервной системы, таких как эпилепсия или опухоль
долей головного мозга. Подробнее о вербальных критериях классификации
электроэнцефалограмм можно прочитать в работе [3].
12
4 Классификация
электроэнцефалограмм
последовательной
нейронной сетью
Рассмотрим пример классификации электроэнцефалограмм с помощью
последовательной нейронной сети. Для обучения будем использовать
собственную базу данных, содержащую 500 фрагментов нормальной, 500
фрагментов пограничной и 500 фрагментов патологической ЭЭГ. Сигналы
были получены в ГБУ РМЭ Республиканская клиническая больница, а также из
верифицированных баз данных, расположенных в открытом доступе в сети
интернет: TUH EEG (www.isip.piconepress.com/projects/tuh_eeg/) и PhisioNet
(www.physionet.org/). Длительность каждого фрагмента составляет 0,5 с, при
частоте дискретизации 500 Гц. В заданную длительность сигнала как раз
укладываются основные ЭЭГ-феноменомы, характерные для нормальной,
пограничной и патологической ЭЭГ. Ниже представлены фрагменты сигналов
из рассматриваемой базы данных.
Рисунок 8 – Эпоха нормальной ЭЭГ длительностью 0,5 с, сигнал состоит из
следующих друг за другом альфа-волн частотой 10 Гц
13
Рисунок 9 – Эпоха нормальной ЭЭГ длительностью 0,5 с, сигнал состоит из
следующих друг за другом альфа-волн частотой 10 Гц, амплитуда альфа
ритма не превышает 100 мкВ
Рисунок 10 – Эпоха нормальной ЭЭГ длительностью 0,5 с, сигнал состоит из
следующих друг за другом альфа-волн частотой 10 Гц, имеется одна бета
волна частотой 15 Гц и амплитудой ниже 7 мкВ
14
U, мкВ
t, c
Рисунок 11– Эпоха патологической ЭЭГ длительностью 0,5 с, в состав
сигнала входит острая волна частой порядка 20 Гц и амплитудой 55 мкВ
(первая волна на графике)
Рисунок 12 – Эпоха патологической ЭЭГ длительностью 0,5 с, в состав
сигнала входит спайк с амплитудой порядка 140 мкВ
15
Рисунок 13 – Эпоха пограничной ЭЭГ длительностью 0,5 с, содержит тетаволну частотой 5 Гц и амплитудой выше 50 мкВ
Рисунок 14 – Эпоха пограничной ЭЭГ длительностью 0,5 с, содержит альфаволну с вершиной «заостренной» формы
Для классификации будем использовать последовательную нейронную
сеть, содержащую 250 нейронов во входном слое (поскольку число отсчетов в
классифицируемом сигнале равно 250), 16 нейронов в первом скрытом слое,
16 нейронов во втором скрытом слое и 3 нейрона в последнем слое. Число
16
нейронов в последнем слое нейронной сети равно числу классов. В
соответствии с функцией softmax определяется номер класса, к которому
относится каждая электроэнцефалограмма. Если максимальное значение
будет наблюдать на выходе первого нейрона последнего слоя нейронной сети
– это будет нормальная ЭЭГ, на выходе второго – патологическая ЭЭГ, на
выходе третьего – пограничная ЭЭГ. 1000 случайно выбранных сигналов ЭЭГ
будем использовать в качестве обучающих данных, 250 – в качестве
проверочных. Оставшиеся 250 сигналов будем использовать в качестве
тестовых данных, которые нейронная сеть «не видела» на этапе обучения и
проверки. Обучение нейронной сети будем проводить на 500 эпохах, т.е. 500
раз будем подавать на ее вход весь массив обучающих и проверочных
данных. Построим графики обучения нейронной сети, чтобы выявить номер
эпохи, после которой наступает переобучение.
Ниже представлен пример реализации данной нейронной сети на языке
Python. Представленный скрипт сохранен в отдельную папку с проектом. Эта
директория в свою очередь содержит папку data, в которой хранятся
обучающие данные. Папка data содержит 3 директории: border-epochs, normepochs и pathology-epochs, в которых содержится по 500 файлов пограничной,
нормальной и патологической ЭЭГ соответственно.
from tensorflow.keras import models
from tensorflow.keras import layers
from tensorflow.keras.utils import to_categorical
import signal_proc as sp
import random
import numpy as np
import matplotlib.pyplot as plt
# загрузка имен файлов
epoch_paths = (sp.get_abs_fpaths("data/norm-epochs") +
sp.get_abs_fpaths("data/pathology-epochs") +
sp.get_abs_fpaths("data/border-epochs"))
17
# перемешиваем имена файлов в случайном порядке
random.seed(42)
random.shuffle(epoch_paths)
data = []
labels = []
# загружаем данные
for path in epoch_paths:
data.append(sp.load_segment(path))
# определение типа эпохи (нормальная, пограничная или патологическая) в
зависимости от имени файла
labels.append(sp.get_epoch_label_by_path(path))
# преобразуем данные из list в ndarray
data = np.array(data, dtype=np.float)
labels = np.array(labels)
# нормализация значений сигнала [-1, 1]
eeg_signal_max_value = np.max(data) # максимальное значение амплитуды
загруженных сигналов
eeg_signal_min_value = np.min(data) # минимальное значение амплитуды
загруженных сигналов
sweep = eeg_signal_max_value - eeg_signal_min_value
normalized_data = (data - eeg_signal_min_value) / sweep # нормализация
данных
# разграничиваем данные на обучающие, проверочные и тестовые
train_labels = labels[0:1000]
val_labels = labels[1000:1250]
test_labels = labels[1250:1500]
one_hot_train_labels = to_categorical(train_labels)
one_hot_val_labels = to_categorical(val_labels)
one_hot_test_labels = to_categorical(test_labels)
train_data = normalized_data[0:1000]
val_data = normalized_data[1000:1250]
test_data = normalized_data[1250:1500]
# конструирование нейронной сети
model = models.Sequential()
model.add(layers.Dense(16, activation='relu', input_shape=(250,)))
model.add(layers.Dense(16, activation='relu'))
model.add(layers.Dense(3, activation='softmax'))
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['acc'])
history = model.fit(train_data,
one_hot_train_labels,
epochs=500,
18
batch_size=25,
validation_data=(val_data, one_hot_val_labels))
# значение функции потер для обучающих данных
loss = history.history['loss']
# значение функции потерь для проверочных данных
val_loss = history.history['val_loss']
# значение функции точности для обучающих данных
acc = history.history['acc']
# значение функции точности для проверочных данных
val_acc = history.history['val_acc']
sp.show_train_history_2(sp.smooth_curve(acc))
results = model.evaluate(test_data, one_hot_test_labels)
print(results)
Графики обучения нейронной сети выглядят следующим образом
(рисунок 15).
Рисунок 15 – Графики обучения нейронной сети
19
Из рисунка видно, что переобучение наступает где-то после 270 эпох.
Точность распознавания модели, обученной на 270 эпохах составляет 82,4 %.
5 Список литературы
1. Каллан Р. Основные концепции нейронных сетей.: Пер. с англ. / Р.
Каллан. М.: Издательский дом «Вильямс», 2001. – 291 с.
2. Франсуа Ш. Глубокое обучение на Python / Ш. Франсуа. СПб.: Питер,
2018. - 400 c.
3. Цыган, В.Н. Электроэнцефалография / В.Н Цыган, М.М Богословский,
А.В Миролюбов; под. ред. М.М Дьяконова – СПб.: Наука, 2008. – 192 с.
Приложение. Установка среды разработки
Для запуска скриптов, написанных на Python, необходимо установить
его интерпретатор версии 3.8. Интерпретатор Python можно скачать на сайте
https://www.python.org/downloads/windows/.
Рисунок 0.1 иллюстрирует начало установки интерпретатора Python. В
начальном окне необходимо поставить галочку напротив «ADD python 3.8 to
PATH» и нажать на ссылку «Customize installation». Далее все делать по
умолчанию до момента, когда появится окно с выбором пути для установки
интерпретатора. Необходимо выбрать путь C:\Python38. Далее все действия
выполнять по умолчанию.
После установки интерпретатора необходимо выполнить установку
дополнительных библиотек. Для этого запустить командную строку Windows
и перейти в директорию C:\Python38. Далее необходимо установить
библиотеку OpenCV и Keras. OpenCV используется для цифровой обработки
изображений, Keras – для построения нейронных сетей.
20
Рисунок 0.1 – Окно начала установки интерпретатора Python
Рисунок 0.2 – Выбор пути для установки интерпретатора Python
Также для корректного запуска скриптов нам понадобятся библиотека
для численных вычислений NumPy и библиотека для визуализации графиков
Matplotlib. Для установки указанных библиотек необходимо ввести в консоль
следующие команды:
pip install numpy;
pip install keras;
pip install opencv-python;
pip install matplotlib.
21
После установки библиотек можно запускать скрипты на Python из
какого-нибудь редактора кода. Мы будем использовать Visual Studio Code,
скачать которую можно на сайте https://code.visualstudio.com/download.
После установки среды на вкладке Extensions необходимо ввести в окно
поиска Python и установить Python for VS (рис. 0.3).
Рисунок 0.3 – Установка плагинов для программирования на Python в
VS Code
Далее можно приступать к реализации проекта.
Download