Электроэнцефалография (ЭЭГ) — это неинвазивный метод регистрации электрической активности мозга через электроды на поверхности головы. За последние годы ЭЭГ-данные перестали быть исключительно медицинской прерогативой и прочно вошли в мир data science. Сегодня их используют в нейромаркетинге для оценки реакций на рекламу, в когнитивных исследованиях для измерения внимания и памяти, в разработке Brain-Computer Interface (BCI) и даже в спортивной аналитике.

Популярность ЭЭГ объясняется несколькими факторами:

  • Доступность: относительно недорогие портативные устройства (Emotiv, Muse, OpenBCI)

  • Безопасность: полностью неинвазивная процедура

  • Скорость: данные в реальном времени с миллисекундным разрешением

  • Открытость: сотни публичных датасетов на Kaggle, PhysioNet и других платформах

В этой статье я покажу, как работать с реальными EEG-датасетами из Kaggle — от загрузки сырых данных до обучения классификатора на Python.


Типы EEG-датасетов: что и зачем измеряют

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

1. Эмоциональные состояния

Типичные датасеты: DEAP, Feeling Emotions

Что измеряют: реакцию на аудиовизуальные стимулы (музыкальные клипы, видео)

Метки: emotional valence (позитив/негатив), arousal (возбуждение), dominance (доминирование)

DEAP — один из самых цитируемых наборов данных. 32 участника смотрели 40 музыкальных клипов по одной минуте, после чего оценивали свои эмоции. Данные включают 32 канала ЭЭГ и дополнительные физиологические сигналы (GSR, EOG, EMG).

В научных статьях на основе таких датасетов строят гибридные LSTM+CNN модели, достигающие точности до 97% (Sensors, 2025; Electronics, 2022).

2. Когнитивная нагрузка

Типичные датасеты: EEGMAT (Arithmetic Task), Cognitive Load

Что измеряют: мозговую активность при решении задач разной сложности

Применение: оценка стресса, усталости, концентрации внимания

Например, в EEGMAT 36 участников решали задачи на вычитание чисел. Данные размечены по уровню сложности и качеству выполнения ("хорошо справился" / "плохо справился"). Такие наборы используют для создания адаптивных обучающих систем и интерфейсов.

3. Моторное воображение (Motor Imagery)

Типичные датасеты: EEGBCI, BCI Competition IV

Что измеряют: нейронные паттерны при воображении движений

Применение: BCI-интерфейсы, нейропротезирование, реабилитация

Классическая задача: участник воображает движение левой или правой руки, не совершая его физически. Система должна определить намерение по сигналам моторной коры. EEGBCI содержит записи 109 участников с 64 каналами — идеальная отправная точка для экспериментов с BCI.

4. Медицинская диагностика

Типичные датасеты: Bonn Epilepsy Dataset, CHB-MIT Scalp EEG Database

Что измеряют: патологическую активность (эпилептические приступы, нарушения сна)

Применение: автоматическая детекция приступов, предиктивные модели

Bonn Epilepsy Dataset — абсолютная классика. 5 категорий по 100 одноканальных сегментов длиной 23.6 секунды: здоровые испытуемые, межприступные периоды, приступы. На его основе создано большинство Kaggle-проектов по эпилепсии.


Топ-5 датасетов для старта

Для практического знакомства с ЭЭГ-анализом рекомендую начать с этих наборов:

Датасет

Каналы

Участники

Задача

Сложность

Bonn Epilepsy

1

-

Детекция приступов

Feeling Emotions

14

3

Распознавание эмоций

⭐⭐

EEGBCI

64

109

Motor imagery

⭐⭐⭐

DEAP

32

32

Эмоции (мультимодальный)

⭐⭐⭐⭐

CHB-MIT

23

24

Предиктивная эпилептология

⭐⭐⭐⭐⭐


Практика: pipeline обработки ЭЭГ на Python

Теперь разберём полный цикл работы с данными — от сырого сигнала до обученной модели.

Шаг 1: Загрузка данных

Для CSV-файлов всё тривиально:

import pandas as pd

df = pd.read_csv('eeg_data.csv')
print(df.head())
print(f"Размерность: {df.shape}")

Медицинские форматы (EDF, FIF) требуют специализированной библиотеки MNE-Python:

import mne

# Загрузка EDF-файла
raw = mne.io.read_raw_edf('subject1.edf', preload=True)

# Информация о записи
print(raw.info)
print(f"Частота дискретизации: {raw.info['sfreq']} Гц")
print(f"Каналы: {raw.info['ch_names']}")
print(f"Длительность: {raw.times[-1]:.2f} сек")

# Быстрая визуализация
raw.plot(duration=5, n_channels=10, scalings='auto')

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

Шаг 2: Предобработка и фильтрация

ЭЭГ содержит множество помех: сетевой шум (50/60 Гц), артефакты моргания, мышечная активность. Стандартная практика — полосовая фильтрация в диапазоне 1–40 Гц:

# Полосовой фильтр
raw.filter(l_freq=1.0, h_freq=40.0, fir_design='firwin')

# Режекторный фильтр для сетевой наводки (50 Гц)
raw.notch_filter(freqs=50.0)

# Сравнение до/после
raw_orig.plot(start=0, duration=5, title="До фильтрации")
raw.plot(start=0, duration=5, title="После фильтрации")

Для удаления артефактов моргания и движений используют Independent Component Analysis (ICA):

from mne.preprocessing import ICA

# Обучение ICA
ica = ICA(n_components=20, random_state=42)
ica.fit(raw)

# Автоопределение компонент-артефактов
ica.exclude = [0, 1]  # индексы компонент, связанных с морганием
ica.plot_components()

# Применение к данным
raw_clean = ica.apply(raw.copy())

Шаг 3: Извлечение признаков

Классический подход — спектральный анализ. Разделяем сигнал на частотные диапазоны:

  • Дельта (0.5–4 Гц): глубокий сон

  • Тета (4–8 Гц): медитация, сонливость

  • Альфа (8–12 Гц): расслабленное бодрствование

  • Бета (12–30 Гц): активное мышление

  • Гамма (30–100 Гц): концентрация, обработка информации

import numpy as np
from scipy.signal import welch

def extract_band_power(raw, band_freq):
    """Вычисление мощности в заданном диапазоне"""
    sfreq = raw.info['sfreq']
    data, times = raw[:]
    
    # Периодограмма Уэлча
    freqs, psd = welch(data, sfreq, nperseg=int(sfreq * 2))
    
    # Интегрирование по диапазону
    idx = np.logical_and(freqs >= band_freq[0], freqs <= band_freq[1])
    band_power = np.trapz(psd[:, idx], freqs[idx], axis=1)
    
    return band_power

# Извлечение для всех диапазонов
bands = {
    'delta': (0.5, 4),
    'theta': (4, 8),
    'alpha': (8, 12),
    'beta': (12, 30),
    'gamma': (30, 45)
}

features = {}
for band_name, band_range in bands.items():
    features[band_name] = extract_band_power(raw, band_range)

# Сборка в DataFrame
features_df = pd.DataFrame(features)
print(features_df.head())

Альтернативы: Common Spatial Patterns (CSP) для motor imagery задач, статистические характеристики (дисперсия, асимметрия, эксцесс), wavelet-преобразования.

Шаг 4: Обучение модели

Начинаем с простого — Random Forest:

from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import classification_report, confusion_matrix

# Подготовка данных
X = features_df.values
y = labels  # массив меток классов

# Нормализация
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# Разбиение на train/test
X_train, X_test, y_train, y_test = train_test_split(
    X_scaled, y, test_size=0.2, random_state=42, stratify=y
)

# Обучение
clf = RandomForestClassifier(n_estimators=100, max_depth=10, random_state=42)
clf.fit(X_train, y_train)

# Кросс-валидация
cv_scores = cross_val_score(clf, X_train, y_train, cv=5, scoring='accuracy')
print(f"Cross-validation accuracy: {cv_scores.mean():.3f} ± {cv_scores.std():.3f}")

# Оценка на тесте
y_pred = clf.predict(X_test)
print(f"Test accuracy: {clf.score(X_test, y_test):.3f}")
print("\nClassification Report:")
print(classification_report(y_test, y_pred))

Для более сложных задач можно использовать глубокие сети:

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Dropout

# Для LSTM нужен 3D тензор (samples, timesteps, features)
X_reshaped = X_train.reshape((X_train.shape[0], X_train.shape[1], 1))

model = Sequential([
    LSTM(64, return_sequences=True, input_shape=(X_train.shape[1], 1)),
    Dropout(0.3),
    LSTM(32),
    Dropout(0.3),
    Dense(16, activation='relu'),
    Dense(len(np.unique(y)), activation='softmax')
])

model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
history = model.fit(X_reshaped, y_train, epochs=50, batch_size=32, validation_split=0.2, verbose=1)

Шаг 5: Визуализация результатов

Матрица ошибок показывает, какие классы модель путает:

import matplotlib.pyplot as plt
import seaborn as sns

# Матрица ошибок
cm = confusion_matrix(y_test, y_pred)

plt.figure(figsize=(8, 6))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', 
            xticklabels=['Класс 0', 'Класс 1'], 
            yticklabels=['Класс 0', 'Класс 1'])
plt.title('Матрица ошибок классификации')
plt.ylabel('Истинные метки')
plt.xlabel('Предсказанные метки')
plt.tight_layout()
plt.show()

Важность признаков (для Random Forest):

importances = clf.feature_importances_
indices = np.argsort(importances)[::-1]

plt.figure(figsize=(10, 6))
plt.bar(range(len(importances)), importances[indices])
plt.xticks(range(len(importances)), 
           [list(bands.keys())[i] for i in indices], 
           rotation=45)
plt.title('Важность частотных диапазонов')
plt.ylabel('Feature Importance')
plt.tight_layout()
plt.show()

Best practices и типичные ошибки

✅ Рекомендации

  1. Используйте MNE-Python — де-факто стандарт для ЭЭГ-анализа в Python

  2. Всегда визуализируйте — графики выявляют проблемы, невидимые в числах

  3. Начинайте с простого — Random Forest на спектральных признаках часто даёт 85–90% точности

  4. Следите за балансом классов — используйте stratified split и метрики вроде F1-score

  5. Сохраняйте промежуточные результаты — reproducibility критична в науке

❌ Типичные ошибки

  • Игнорирование артефактов — моргания и движения создают амплитуды в сотни раз больше реальной ЭЭГ

  • Неправильная фильтрация — слишком узкая полоса убивает полезный сигнал

  • Data leakage — использование будущих данных для предсказания прошлого (особенно при работе с временными рядами)

  • Переобучение — сложные модели на маленьких датасетах (используйте кросс-валидацию)


Куда двигаться дальше

После освоения базовых техник открывается несколько путей развития:

Участие в соревнованиях

Продвинутые техники

  • Common Spatial Patterns (CSP) для BCI

  • Transfer learning с предобученными сетями

  • Attention mechanisms для выделения значимых временных окон

  • Real-time processing для онлайн-приложений

Реальные приложения

  • Разработка BCI-интерфейсов для людей с ограниченными возможностями

  • Системы мониторинга внимания водителей

  • Адаптивные образовательные платформы

  • Нейромаркетинговые исследования


Заключение

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

Даже простая модель на правильно подготовленных данных способна показывать впечатляющие результаты. Главное — понимать природу сигнала, тщательно проводить предобработку и не забывать про воспроизводимость результатов.

Мозговая активность — это тоже данные. А значит, её можно анализировать, визуализировать и превращать в умные интерфейсы. Экспериментируйте, пробуйте разные подходы — и у вас всё получится!


Полезные ресурсы

GitHub-репозитории:


Материал подготовлен на основе анализа публичных датасетов Kaggle и научных публикаций в области нейроинформатики.

Комментарии (0)