Про волнения в головах

f882ead70e094eafa8515cd7c87eaed3.png
Пару месяцев назад мне захотелось поэкспериментировать с нейроинтерфейсом. Никогда этой темой не занимался, но вдруг стало любопытно. Вроде как лет 5–10 назад обещали бум нейроустройств, а всё что мы сейчас имеем на рынке — устройство чтобы махать ушами, устройство чтобы светить камешком, да устройство чтобы левитировать шаром. Где-то на подходе устройство чтобы будить вовремя. Вот тут есть неплохая статья про всё это дело. В то же время регулярно появляются какие-то исследования, где рассказывают, что люди могут научиться двигать роботическими руками-ногами или писать тексты (1, 2, 3, вот тут есть подборка). Но это всё опытное, в единственном экземпляре, со стоимостью аппаратуры как хорошее авто.

А где что-то посередине? Что-то полезное обычному пользователю? Пусть даже не везде, а в каких-то отдельных применениях. Ведь даже навскидку придумывается несколько вещей: детектор засыпания для водителя, повышение работоспособности (например через выбор музыки, или управление перерывами!). Можно выбрать что-то более специфическое. Например смотреть и анализировать своё состояние в киберспорте. Для этого же даже трекеры зрачков выпускают и используют. Почему нет таких применений? Этот вопрос мучил меня. В итоге решил почитать куда наука движется, а так же купить простенькую нейрогарнитуру и затестить. В статье — попытка разобраться в теме, немного исходников и много анализа текущих достижений потребительской электроники.

Что использовал и почему


В продаже есть много различных нейрогарнитур. Вот несколько подборок на тему: 1, 2.
В Москве есть далеко не все из них. Взять решил банальный MindWave NeuroSky. Он бюджетный, а главное — есть неплохое SDK с примерами на нескольких языках.
9a89607c4d374d078557cf973845c7b1.jpgМинусы Neurosky
Сразу о минусах. Почему-то о них мало пишут. Но они есть:
1) Сам Mindwave цепляется к компу как COM-порт. Приложение может цепляться к нему напрямую через функции .NET обёртки. А может цепляться через веб-сервер Neurosky, висящий на 127.0.0.1. Второе необходимо, если разработка идёт через какой-нибудь флеш, у которого нет прямого доступа к COM-порту. Но COM пример приложенный к SDK недоработан, устройство часто не цепляется. По сути, единственный способ работать стабильно — через сервер. В конце статьи будет ссылка на GitHub, я там привёл пример того, как всё же можно работать через COM порт (используя сервер для инициализации).
2) Библиотеки. Тестовый пример не запустился. Библиотеки, которые лежат в SDK не работают с последними драйверами. Нужно выкапывать в установленном с драйверами софте последние версии библиотек и использовать их с примерами из SDK.
3) Как бы NeuroSky не хвастался алгоритмами фильтрации помех, но всё же, самые низкочастотные волны не юзабильны (Delta и Theta). Реально использовать от силы ½–1/5 данных по ним. При этом нужно подключать либо свою систему фильтрации, либо брать какую-то готовую (например OpenVibe openvibe.inria.fr).
4) Детектор моргания, которым так хвастается NeuroSky функционален наполовину. В инструкции сказано: «моргайте как можно более естественно». Но тогда моргания не детектируются. Если моргнуть сильно, напрягаясь, то тоже. Нужно где-то посередине. Ах да. COM версия протокола их ещё некорректно передаёт программе. Вот как будут выглядеть сильное/среднее/слабое моргание на графике. Чуть ниже будет пример как выглядит на фурье-спектре. Отличить можно не всегда.
8629a1e268a44443989b7e46a27c4275.png8307455fe4a74d1bb152c85380230936.png
b922ebb85c094b4b8a058784a2b51b73.png
5) Зараза неудобный. Так и хочется его сдёрнуть с головы. Причём, судя по всему, не я один таков.Что собственно NeuroSky видит
Но, не всё так плохо:
1) Низкие, высокие альфа, бета, гамма волны видны неплохо. Всплески по ним есть, но фильтруются. Небольшое усреднение + фильтр выбросов даёт объективную картину:
7646e77b656d4f72952deb030775bd8b.png
2) Есть два параметра, за которые все любят Neurosky: «Медитация» и «Внимание». Они слабо скоррелированы, но ими можно управлять. Я не уверен, что данные параметры означают именно это. Первый из них максимизируется если что-то представить с закрытыми глазами, второй, если начинать вспоминать и ассоциировать различные факторы. Но при игре в Quake | Работе показания весьма средние, хотя оба занятия требуют максимального погружения и внимания. Показатели при прокрастинации для «внимания» даже выше:
e4e9a44a2f634c22ae80d322f97004b8.png
С другой стороны, данными величинами можно научиться более-менее эффективно управлять. Они представляют собой некоторые зависимые от параметров «альфа», «бета», «дельта», «гамма», «тета» величины. У «медитации» максимальная зависимость от альфы:
2c3051b4c0614240913b7c8e03d9e480.png
Видно, что не всегда, но пики и производные часто зависимы.
3) Сами показания «Альфа-волн» фильтруются устройством. Для теста я сам построил полный спектр входного сигнала, вычислил по нему альфу и сравнил (на рисунке спектр где-то для 0–40Hz):
7b108e99420e43be815980a240556683.png
d45c62cde1a94c0889f564246dd5fb2c.png
В принципе, после закрытия глаз видно, что альфа, вычисленная вручную начала расти. Для преобразование я использовал окно преобразования порядка 1.5–2х секунд. Если сузить окно где-то до ⅓ секунды, то эффект от моргания будет занимать значительно меньше площади.
Я провёл ещё несколько тестов и в целом у меня получилось, что альфа, которую выдаёт прибор, достаточно неплохо фильтруется по сравнению с альфой, которую можно посчитать руками. Но, посчитанное руками будет, безусловно, точнее. Например, если брать короткие выборки без моргания, то лучше всё считать вручную. Если брать среднее, то показания прибора — лучше, если не запариваться с фильтром.

Пару слов о теории


Существует достаточно разветвлённая теория о том, какие электрические колебания генерирует мозг в каких ситуациях. Введение в эту теорию заняло бы всю эту статью. К тому же, я явно не тот, кто сможет это объяснить достаточно подробно ответив на все вопросы. Так что ограничусь ссылкой на Википедию и небольшим резюме:
Разные режимы работы мозга вызывают электрические колебания на разных характеристических частотах. Были выделены несколько групп таких частот и проведена их идентификация с деятельностью. Например глубокий сон вызывает колебания на частотах ниже четырёх герц. Расслабленность и закрытые глаза на частотах порядка 8–12 герц. NeuroSky выводит следующие параметры:
• Дельта волны:
• Тета волны: 4–7 Hz. Быстрый сон, или когда мозг сосредоточен на одном источнике информации.
• Альфа волны: 8–15 Hz. Расслабление, спокойное бодрствование.
• Бета волны: 16–31 Hz. Внимание, напряжение, умственная деятельность.
• Гамма волны: >=32 Hz. Решение задач, максимальное напряжение внимания.
Данные показатели являются некоторой усреднённой метрикой. Для каждой новой головы они могут быть различны или сдвинуты. Зато они достаточно стабильны + для большинства людей могут быть репрезентативны. Например отклик по альфа-волнам для меня для разных состояний:
88c610725df543629524deebc4ae38ab.png
Согласно теории, чем больше альфа, тем более расслаблен человек. Вроде сходится. Для бета волн вроде как тоже видна зависимость, но уже не такая явная:
d96ee0a7f52b4dd69c2c17d8b9355f1a.png
Для Гамма-волн у меня не получилось никакого различия в зависимости от деятельности. Может мозг не тот, может чувствительности прибора не хватает, может 50hz наводки убивают всякие попытки детектировать что-то ощутимое:
3f0ef71755284a55ac2675de1c42f9a1.png
В принципе, у меня складывается ощущение, что на частотах выше 30Hz какое-то немыслимое количество различных колебаний. Что-то дельное в качестве стабильной метрики на первый взгляд там выцепить сложно (спектр где-то от 0 до 80Hz):
94e635431d0347b1bd022faba4ed83bc.jpg
Сам прибор втыкается в точку головы Fp1. Говорят, что это не самая оптимальная точка, но вполне репрезентативная. Вроде как точки задней части головы должны более чёткие альфы выдавать.
759c33a66a254466852d3736eeb2fccd.png
Ну ладно. Вроде как прибор покрутили, потестировали. Попробуем что-нибудь сделать?

Щенячий восторг вокруг


Начал я с того, что полистал в интернете на тему существующих проектов и идей для MindWave и других устройств на 1–3 электрода. И, если честно, пришёл в ужас.
Во-первых, чудовищное количество бессмысленной движухи вокруг. Тысячи видео на Ютубе где человек показывает свои мозговые сигналы через приложение Brainwave Visualizer или аналоги. Ещё много приложений, которые по переменным «медитация» и «внимание» делают какое-то простейшее действие: управляют вертолётом, или машинкой. Движуха вокруг arduino и то в миллион раз полезнее и интереснее. Тут же всё сводится к двум величинам (щааа как у нас сведётся всё к ним).
Ещё есть тема. Писать статьи о там как всё это круто, что нейронауки спасут мир. Даже здесь, на Хабре. После статьи обязательно следует предложение либо купить девайсину в соответствующей конторе, либо как-то ещё доставить выгоду писателю статьи. Основное направление таких статей — не «сделать полезное устройство», а «стрясти с пользователя денюжку».
Для устройств с большим числом электродов, того же «Emotiv epoc» применений куда больше. В первую очередь связанных с управлением в играх, или управлением устройств. Но Emotive неплохо детектирует микромимику, на базе которой и строятся такие системы. Управление за счёт мозговой активности практически не встречается.
Серьёзные работы. Да, есть, но они глубоко зарыты.

Закапываемся глубже в мозг


Темы поднятые мной в заголовке статьи не новы. Вообще мало что ново под луной в науке и технике. Можно ли с помощью нескольких электродов определить состояние человека? Устал он, работает, засыпает, водит машину? И как это вообще реализовать?
Наиболее очевидным кажется анализ данных, поступающих с ЭЭГ алгоритмами анализа данных и обучения: SVM, Random Forest, ANN, KNN и.т.д. И действительно. Соответствующий запрос в гугле выдаёт достаточно много работ на эту тему. Не все идеальны, много есть мест, где можно подкопаться, но их достаточно для понимания существующего прогресса и возможностей. Разберём поподробнее.

Во-первых, это coolworld.me/classifying-EEG-SVM. Исследование производилось на MindWave. Автор записал много коротких сетов по 10 секунд со следующими ментальными действиями: «вообразить вращение куба», «вообразить мотор», «вообразить аудиторию». При этом, судя по всему, пробовал комбинировать их с микродвижениями мышц. По каждому сету делалось быстрое фурье-преобразование с базой в 2 секунды. Полученные 5 векторов служили для обучения. Всего делалось по 3 записи каждого действия. Итого 15 векторов.
Уверяет, что получилось классифицировать в 97–100% случаев. Верится, если честно, с трудом. Но, автор описал эксперимент очень плохо. Возможно, используется очень специфический датасет, может, кроме ментальной активности используются микродвижения, может, в 10 секундах записи нет моргания (или вообще писалось с закрытыми глазами), может разделение сетов было бинарно, и.т.д. Вот тут и тут есть чуть больше статей автора.
В целом, автор скорее исследовал не «различие ментальных состояний», а способы через ЭЭГ передавать определённые метки. И на мой взгляд данный способ реально работает. Может не в 97% случаев, но в 90% всё же и можно давать фиксированные команды. При этом отвязанные от «медитации» и «внимания», которые не всегда можно контролировать. Заняты руки — включил мозгом музыку.
Очень немаловажным является отказ автора от использования встроенных величин «альфа», «бета», «дельта», «гамма», «тета» спектров. Автор работал с быстрыми процессами. В показателях MindWave же происходит фильтрация и накопление, что приводит к падению точности и латентности. Автор объясняет данный подход тем, что честно подсчитанный спектр точнее. Но я так не думаю. Как я показал выше — при моргании ошибка будет выше у спектров, которые считаются руками. Плюс у них большая подверженность шумам.

Во-вторых, мне очень понравилась данная статья. Она про Emotiv, а не про NeuroSky. Но тут делается именно то, что на мой взгляд должны делать такие системы. Анализируется возможность детектирования различных ментальных состояний. Авторы записали датасеты с вождением и описали их несколькими способами, как «работа», «удовольствие», «сложность» и.т.д. После чего обучили и протестировали.
3054213028aa41ce8729bcf5fc50b624.png
В работе они показали не только принципиальную возможность классификации. Они проанализировали различные классификаторы и рассчитали их точности. А так же рассмотрели несколько применений, в том числе — анализ ментального состояния водителя (собственно этому и посвящена работа).
Сделано было практически всё, что было можно. Единственный минус — использовался Emotiv EPOC с 14 электродами. А у меня Mindwave с полутора.

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

Есть работа такая. Она посвящена определению движений по показаниям Emotiv. Я бы не стал так однозначно говорить, что в ней используют именно волны мозга (может статься что мимика тоже причастна).

Ещё есть работа, где всё делалось без обучения, а просто по порогам различным + по хитрой логике. Но на мой взгляд она слабая.

Время что-нибудь сделать


Если честно, то делать я начал ещё до того как изучил все статьи. Решил взять SVM и попробовать распознать деятельность человека на продолжительном участке времени. Работает ли человек, водит, читает, играет, и.т.д. Возможно, я ещё опробую остальные идеи из статей выше, но пока на это не хватило времени.
Первым делом я собрал базу на несколько ситуаций:
• Сижу и работаю (Такое проще всего собрать. 90% времени — прогаю)
• Прокрастинирую. В реальности сложно собрать. Старался записывать те момент когда проглядываю вконтакт, или читаю что-нибудь простое типа гиктаймса. Но иногда ловил себя на мысли, что чересчур погружаюсь.
• Читаю. Сейчас на читалке новый роман Гиббсона, а до этого был Мьевиль. Так что погружение неплохое.
• Вожу машину.
• Сижу с закрытыми глазами, пробую заснуть. Обычно записывал вечером, когда уставший. Из-за схемы крепления MindWave к голове сам сон записать сложно.
• Бегаю на беговой дорожке. Пару сетов данных записал, но на мой взгляд использовать их нельзя. Слишком большие помехи.
• Играю на гитаре. Играю весьма средненько, но для тестирования хватит.
• Играю на компе. Для чистоты эксперимента отдельно записал Quake и пару партий в Starcraft.
Каждый процесс я записывал небольшими кусками где-то по 10–15 минут. Это не очень честный набор базы. Читая, я отвлекался на то, чтобы проверить как идёт запись. Работая я мог отвлечься на скайп. Прокрастинируя, я мог начать думать, и.т.д. Среди полученных данных я пробовал откинуть очевидно некондиционные (MindWave часто имеет плохой контакт). Для автомобиля и для бега очень часто измерения некондиционны.
В работах, упомянутых мной выше очень много внимания уделяли именно корректности базы. За этот счёт получили достаточно неплохие результаты. Но ведь понятно, что в реальных условиях такая база будет некорректной. Люди моргают. Люди отвлекаются. Хотелось добавить именно стабильности. При этом понятно, что точность падает. Поэтому работать с большим числом ситуаций и распознавать их одновременно будет невозможно.
Тут я осветил не все примеры, а на мой взгляд наиболее интересные. Все собранные базы выложены в репозитории (ссылка в конце статьи). Можно потестировать самому.

Что будем подавать на вход. Возможно, это ошибка, а может и нет. Но я решил подавать на вход не спектр DCT, а рассчитанные MindWave величины альфа-бета-… волн + параметры «Медитация» и «Концентрация». По хорошему, нужно другое: подавать исходный спектр, отфильтровав его во времени, как это делается почти во всех статьях. Но праздники закончились и в ближайшее время я это не проверю. Как проверю — либо добавлю главу к этой статье, либо напишу ещё одну.
Сделал я это по двум причинам. Во-первых, на тот момент, как начал собирать базу, я нашёл всего одну статью. Во-вторых, мне показалось, что величины MindWave несколько стабильнее. Особенно к морганию. Не хотелось делать свой алгоритм его подавления.
Понимая, что более двух классов различить сложно, я использовал различие только между двумя классами. В качестве решающей машины я использовал SVM. Судя по всем статьям оно неплохо. Его проще всего настроить. Плюс знаком с несколькими реализациями. Входной вектор был:
Тета, Бета, Альфа1, Альфа2, Бета1, Бета2, Гамма1, Гамма2, Медитация, Концентрация
540 248 374 110 98 181 61 120 64 27
Вектор нормировался, чтобы параметры лежали примерно в одной области. Для одного класса результатом подавался +1, для второго -1.

Примеры работы
Точной статистики приводить не буду. Из-за того, как собиралась база — сложно сказать что-то определённое. Собрать базу на 100 примеров каждого класса по 15 минут почти нереально. Поэтому я строю классификатор для двух классов по выборкам Х1 и У1, а потом смотрю, как распознались примеры X2, X3,…, Xn, Y2, Y3,…Yn.
Вектор «альфа», «бета», «гамма», … изменяется где-то раз в секунду. Из-за наличия шумов, вызванных морганием, поворотами головы и не смотря на внутренние фильтрации вектор крайне нестабилен. Часто ему нужно 2–3 секунды чтобы вернуться в норму. Поэтому вводим усредняющее окно длинной в 30 секунд. Получается как-то так: Тест Работа-Прокрастинация
ee4464477cff4c52894b5ccea2d87cf3.png
Пример распознавания прокрастинации, где >80% примера распозналось верно. А вот пример записи с работой на 20 минут, где распозналось верно >90%:
5c6b58c9121c44f398eb5becf07a29d9.png
Всего у меня было 5 записей с работой на 15–25 минут. Из них одна использовалась для обучения. 4 остальных распознались верно. Каждая больше чем на 90% длительности. Из 6 записей прокрастинации одна использовалась как обучение, остальные как тест. Четыре распознались как прокрастинация более чем на 80%, одна как работа почти вся. Вероятно недостаточно прокрастинировал:(Тест Гитара-Чтение
Не очень полезный тест, но так как по этим двум классам я накопил много примеров — тестировал много. Различается очень хорошо. Для чтения была выборка 9 примеров. Для гитары 6 примеров. По одному на тестирования. Неправильно распозналась только одна гитара (где-то только на 60% определилась как гитара, остальные 40% — чтение). Вот данный пример:
2a31433ff2c545ba822ca6a794a06822.pngТест Гитара — Квака
А вот и первый плохо работающий тест. По Q — 4 теста, из них 1 обучение, остальные 3 распознались. Но по игре в Гитару 6 тестов, из них 2 не распознано корректно.Тест Гитара — прокрастинация
Не работает практически целиком. Переобучается в сторону игры на гитаре. Почти все записи причисляет к игре на гитаре.Сидение с закрытыми глазами — вождение машины
Вот это очень обидно, но у меня тоже не работает. Всё же я почти уверен, что причина в том, что сидение с закрытыми глазами != засыпание. Засыпание у меня получилось сделать только на одном из четырёх примеров (высокие альфа волны были, пример ниже). Но как собрать базу засыпания в разумные сроки, если честно, не понимаю. Тем более с Mindwave в которым практически невозможно лечь это сложно.
314134e58f0b4ec5ae046b4fa2699480.png
Что обнадёживает — в статьях, которые были приведены выше отсечку засыпания при вождении дать можно. Даже по уровне альфы. И скорее всего по правильно собранной базе всё заработает

Итоговые мысли где работает где нет


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

А справедливо ли?


А вообще зачем мне нужны были альфа-бета-гамма волны? Может быть достаточно медитации и концентрации? Ведь эти два параметра результирующие?
Такая мысль посетила меня, и я проверил её. Всё же получается, что введение волн значительно уточняет точность распознавания. Привожу примеры для чтения и игры на гитаре. Для остальных классов примерно так же. Видно, что качество улучшилось, хотя общие тренды сохранились:
3a90d0b96b004833bdd9719cfb47d0c3.png
f321c536181c4de3ae07cbd5e81d8a9d.png
e12c1450775244708b57d6a4b57dd46c.png
e717a678b0db4bc8bcbcd829aae7d670.png
98d89da57344430eb060aa4ea7864952.png
В принципе, как было и показано во вводных частях, параметры Медитация и Концентрация сильно завязаны на волны и неплохо показывают что волны представляют собой. Но они не несут в себе 100% информации из волн.

Выводы


Такая небольшая статейка получилась на тему EEG. Новогодние выходные были не очень длинными:)
Вернёмся к вопросам, заданным в начале. Почему не произошло бума нейроустройств в потребительском классе? На мой взгляд основная проблема — сложность создания чего-то универсального. Алгоритмы, кроме самых базовых, будут требовать тюнинга под каждого человека. А сделать автоматический тюнинг без того, чтобы пользователь сам вносил настройки — очень сложно.
Вторая проблема — сложность эксплуатации. Датчики нестабильны. Закрепить их, чтобы не было шумов нетривиально. При этом сухой контакт возможен только для лобовой части. Тот же Emotiv желательно крепить с гелем.
В итоге имеем технологию, которая сама по себе нестабильна. Она неплоха для какой-то аналитики. Но как только дело касается какого-то гарантированного результата — сразу проигрывает. Решить ту же проблему с засыпанием водителя можно куда более простыми и дешёвыми способами. Аналитика с ЭКГ куда интереснее, чем ЭЭГ в общем случае.
Да, есть ряд применений, куда можно пробовать развиваться. В конце концов сделать детектор «работает человек» или «прокрастинирует» другими способами сложно (разве что сделать видеоаналитику изображения на мониторе). Но все такие решения требуют очень больших разработок и вряд ли будут работать на 100% людей.
В сухом остатке, на мой взгляд, ниша бюджетных ЭЭГ устройств может занять только рынок игрушек и бесполезных гаджетов. Чем успешно и занимается.

Коды


Ужасные и сырые исходники всего данного дела я выложил тут.
SVM взят из Accord Framework, для простоты отображения подцеплен старый EmguCV. Так же есть библиотеки Neurosky для взаимодействия с MindWawe.

© Habrahabr.ru