본문 바로가기
Brain Engineering/MNE Python

[MNE-Python] 선형회귀를 이용하여 EEG 신호에서 안구 운동 제거

by goatlab 2022. 8. 23.
728x90
반응형
SMALL

배경

 

진행 중인 EEG에서 눈의 움직임과 눈 깜박임이 명확하게 보인다. 이러한 안구 인공물은 눈의 앞과 뒤 사이의 전기 쌍극자의 변화에 ​​의해 생성된다. 일반적으로 기록된 EEG에 대한 눈 활동의 영향을 최소화하는 것이 중요하다.

 

안구 인공물을 제거하는 데 사용할 수 있는 두 가지 인기 있는 방법, 즉  (다변량 선형) 회귀를 기반으로 하는 접근 방식과 독립 구성 요소 분석 (ICA)을 기반으로 하는 접근 방식이 있다.

 

가장 단순한 형태의 회귀 기반 접근 은 EEG의 회귀 계수를 추정하기 위해 자발적으로 생성된 안구 인공물을 포함하는 사전 실험 보정 실행의 데이터를 사용했던 Hillyard와 Galambos (1970)로 거슬러 올라간다. 10년 이상 후에 Gratton, Coles, Donchin (1983)은 이 절차를 두 가지 방식으로 개선했다. 첫째, 교정 실행 대신 실험 데이터 (수정해야 하는 동일한 데이터)의 EOG 기록을 사용했습니다. 둘째, 눈의 움직임과 눈 깜박임에 대한 회귀 계수를 별도로 추정했다.

 

오랜 세월에도 불구하고 선형 회귀를 통해 안구 인공물을 제거하는 것은 많은 상황에서 잘 작동하기 때문에 널리 사용되는 접근 방식으로 남아 있다. 그러나 눈 가까이에 배치된 전용 EOG 전극을 사용해야 한다는 점을 명심하는 것이 중요하다. 특히, 기록 세션 중에 EOG 전극이 실패하면 전체 방법이 고장난다. 또한, EOG 전극이 어느 정도의 뇌 활동을 기록할 것이라고 가정하는 것이 합리적이다 (결국, 뇌는 이러한 센서 바로 뒤에 위치). 따라서, 이 방법은 안구 인공물 외에도 뇌 활동을 제거할 가능성이 높다. 긍정적 측면에서 필요한 EEG 전극의 수에는 제한이 없다. 회귀 기반 접근 방식은 단일 채널 EEG 기록도 청소할 수 있다.

 

데이터 전처리

 

이 방법을 시연하기 위해 BNCI Horizon 2020 웹사이트에서 공개적으로 사용 가능한 EEG 데이터 세트를 다운로드한다. 특히, 데이터 세트 001-2014의 참가자 A01T를 사용한다 (이 파일을 다운로드하고 따라 하려면 작업 디렉터리에 저장). 설명에는 세 번째 실행에 보정 안구 움직임이 포함되어 있다고 언급되어 있다. 이를 사용하여 회귀 계수를 추정하고 후속 네 번째 실행에서 EEG 데이터를 수정한다.

 

몇 가지 설정 명령으로 시작합니다.

 

import numpy as np
from scipy.io import loadmat
import mne

mat = loadmat("A01T.mat", simplify_cells=True)

mat.keys()
dict_keys(['__header__', '__version__', '__globals__', 'data'])

 

EEG 데이터는 data키에 목록으로 저장되며, 여기서 각 목록 요소는 실행에 해당한다. 예를 들어, mat["data"][0]는 첫 번째 실행의 데이터를 포함하고 두 번째 실행의 mat["data"][1]에 해당하는 식이다. 각 실행은 사전으로 표시되며 EEG 데이터는 "X"키 아래에 저장된다.

 

보정 실행 (세 번째 실행, 목록 색인 2) 및 실험 실행 (네 번째 실행, 목록 색인 3)의 EEG 데이터에 관심이 있다. 이 데이터는 두 개의 별도 이름으로 저장 eeg1하고 (단위를 변환하기 위해 10 -6eeg2 을 곱함, 마이크로볼트에서 볼트로). 결과적으로 두 개의 NumPy 배열이 생성된다.

 

eeg1 = mat["data"][2]["X"] * 1e-6  # run 3 (calibration)
eeg2 = mat["data"][3]["X"] * 1e-6  # run 4 (experiment)

 

다음 단계는 필요하지 않지만 eeg1 및 MNE 개체 eeg2로 변환한다. Raw 이것은 안구 인공물 제거 전후에 원시 EEG 추적의 플롯을 신속하게 생성할 수 있는 기능을 제공한다.

 

info = mne.create_info(25, 250, ch_types=["eeg"] * 22 + ["eog"] * 3)
raw1 = mne.io.RawArray(eeg1.T, info)
raw2 = mne.io.RawArray(eeg2.T, info)

 

mne.create_info는 데이터 (25)의 채널 수, 샘플링 주파수 (250Hz) 및 채널 유형 (처음 22개 채널은 EEG이고 마지막 3개 채널은 EOG)을 설정하는 인수이다. MNE는 행의 채널과 열의 샘플을 기대하기 때문에 배열을 전치해야 한다.

 

회귀 계수 추정

 

이제 EEG에 대한 안구 인공물의 영향을 제거하기 위해 회귀 계수를 추정할 준비가 되었다. 3개의 monopolar EOG 채널 EOG1, EOG2 및 EOG3을 2개의 bipolar 채널로 변환하는 것이 좋다. 이에 대한 한 가지 방법은 양극성 유도 EOG1–EOG2 및 EOG3–EOG2를 생성하는 적절한 매트릭스와 monopolar EOG 신호를 곱하는 것이다. 4개의 monopolar EOG 채널 (일반적인 EOG 기록 설정이기도 함)이 있는 경우 각각 수평 및 수직 bipolar 채널로 변환할 수 있다.

 

bip = np.array([[1, -1, 0], [0, -1, 1]])
raw1_eog = bip @ raw1[22:, :][0]
raw2_eog = bip @ raw2[22:, :][0]

 

이 변환은 실행 raw1과 raw2을 개별적으로 모두 수행한다. 또한, raw 객체를 인덱싱하면 요청된 데이터 및 관련 시간 값이 포함된 튜플이 반환된다. 데이터만 필요하고 [0]을 반환된 튜플의 첫 번째 항목만 선택한다.

 

더 짧은 표기법을 위해 두 실행 모두의 EEG 신호 (처음 22개 채널)에 대해 별도의 이름도 만든다.

 

raw1_eeg = raw1[:22, :][0]
raw2_eeg = raw2[:22, :][0]

 

이제 선형 회귀 계수를 얻기 위해 일반 최소 제곱을 수행한다. 실제로 모든 EEG 채널을 동시에 해결한다 (즉, 여러 종속 변수 또는 응답 변수가 있음). 또한, EOG 채널의 형태로 여러 독립 변수 또는 예측 변수가 있다. 이러한 모델은 때때로 다변량 (둘 이상의 응답 변수) 다중 (둘 이상의 예측 변수) 회귀 모델이라고 한다.

 

응답 변수 (EEG 신호)를 다음과 같이 표시하면 Y, 예측 변수 (EOG 신호)는 X, 그리고 회귀 계수는 B이다. 선형 모델을 다음과 같이 작성할 수 있다.

 

 

그런 다음 최소 제곱해를 계산할 수 있다.

 

 

Python 코드에서 이것은 다음과 같다 (채널이 행에 있기 때문에 신호를 전치해야 하는 반면 등식은 열에 있다고 가정).

 

b = np.linalg.inv(raw1_eog @ raw1_eog.T) @ raw1_eog @ raw1_eeg.T
 

@ 연산자는 행렬의 내적을 계산한다. 또는, 수치적으로 더 안정적인 방법인 np.linalg.solve을 사용하여 회귀 계수를 계산할 수 있다.

 

b = np.linalg.solve(raw1_eog @ raw1_eog.T, raw1_eog @ raw1_eeg.T)

b.shape
(2, 22)

 

이것은 2개의 EOG 채널 (예측자)과 22개의 EEG 채널 (응답)이 있기 때문에 의미가 있다.

 

이제 새로운 데이터에서 안구 인공물을 제거하기 위해 해야 할 일은 측정된 EEG에서 추정된 EOG 영향을 빼는 것이다. raw3이 수정된 데이터를 저장할 새 개체를 만든다.

 

eeg_corrected = (raw2_eeg.T - raw2_eog.T @ b).T
raw3 = raw2.copy()
raw3._data[:22, :] = eeg_corrected

 

시각화

 

방법이 효과가 있었는지 보기위해 먼저, raw2에서 눈에 띄는 안구 활동이 있는 원본 데이터의 한 부분을 플로팅한다. 이 시각화를 위해 동시에 볼 수 있는 채널 수를 25로, 플롯의 시작을 초로 53, 지속 시간을 5초로 설정한다.

 

raw2.plot(n_channels=25, start=53, duration=5, block=True, title="Before")

 

raw3은 수정된 데이터에 대해 동일한 플롯을 생성한다.

 
raw3.plot(n_channels=25, start=53, duration=5, block=True, title="After")

 

자세히 보면 이 방법으로 해당 시간 세그먼트에서 명확하게 볼 수 있는 안구 인공물을 성공적으로 제거했다.

 

https://cbrnr.github.io/posts/removing-eog-regression/

 

Removing eye activity from EEG signals via regression

EEG signals often contain eye activity (movement and/or blinks), which usually needs to be removed before performing EEG analysis. In this post, I show how to get rid of ocular artifacts using a regression-based approach.

cbrnr.github.io

 

728x90
반응형
LIST