BCI/1주 BCI 기초 다지기

[1주 BCI 기초 다지기] 8일차: SVM, 로지스틱 회귀, EEG 데이터 분류 실습, 운동 상상 데이터 분석

_\oyo/_ 2025. 1. 31. 19:17

8일차: 선형 분류 모델

1. SVM 개념

SVM이란?

SVM은 데이터를 두 클래스(또는 다중 클래스)로 구분하는 초평면(Hyperplane)을 찾는 알고리즘이다.

초평면은 두 클래스 간 거리를 최대화하는 방향으로 위치하며, 선형적으로 분리되지 않는 경우 커널(Kernel) 트릭을 사용하여 고차원 공간에서 선형 분리가 가능하게 한다.

 

https://www.hackerearth.com/blog/developers/simple-tutorial-svm-parameter-tuning-python-r/

SVM의 주요 개념

  • 초평면(Hyperplane)
    • 데이터를 분류하는 경계선(또는 경계면).
    • 초평면의 방정식은 w⋅x+b=0
      https://m.blog.naver.com/tommybee/221790549191
  • 마진(Margin)
    • 초평면과 가장 가까운 데이터 포인트(서포트 벡터) 간 거리.
    • SVM은 이 마진을 최대화하여 분류 성능을 향상시킴.
      https://www.ecopro.ai/entry/%EB%B9%85%EB%B6%84%EA%B8%B0-%EC%8A%A4%ED%84%B0%EB%94%94%EB%AA%A8%EC%9E%84-%EB%B0%9C%ED%91%9C%EC%A4%80%EB%B9%84-20240309-%EC%84%9C%ED%8F%AC%ED%8A%B8%EB%B2%A1%ED%84%B0%EB%A8%B8%EC%8B%A0SVM
  • 서포트 벡터(Support Vector)
    • 초평면 근처에 위치한 데이터 포인트로, 초평면을 정의하는 데 중요한 역할을 함.
  • 커널(Kernel) 트릭
    • 데이터를 고차원 공간으로 매핑하여 비선형 데이터를 선형 분리 가능하게 함.
    • 예: 선형 커널, 다항식 커널, RBF(방사형 기저 함수) 커널.

SVM의 장단점

  • 장점
    • 고차원 데이터에서도 잘 작동.
    • 커널을 사용해 비선형 데이터도 분류 가능.
    • 과적합에 강함.
  • 단점
    • 큰 데이터셋에서는 느릴 수 있음.
    • 다중 클래스 분류에서 직접적으로 확장되지 않아 별도의 기법이 필요함. (One-vs-One 또는 One-ve-Rest 등)

 

2. Logistic Regression 개념

Logistic Regression란?

Logistic Regression은 이름에 "Regression"이 들어가지만, **분류(Classification)**에 사용되는 알고리즘이다.

이진 분류(Binary Classification) 문제를 해결하는 데 적합하며, 데이터를 두 클래스 중 하나로 분류한다.

주요 개념

  • 로지스틱 함수(Logistic Function): Logistic Regression은 로지스틱 함수(또는 시그모이드 함수)를 사용하여 데이터를 0~1 사이의 확률로 매핑.
  • 결정 경계(Decision Boundary):
    • 출력값(확률)이 0.5보다 크면 Class 1, 작으면 Class 0으로 분류.
    • 결정 경계는 선형 함수로 나타남.

Logistic Regression의 손실 함수

Logistic Regression은 크로스 엔트로피 손실(Cross-Entropy Loss)을 최소화하도록 모델을 학습한다.

가중치 w와 절편 b를 초기화하고, 경사 하강법을 사용하여 손실 함수를 최소화하며 최적의 w와 b를 찾음으로써 데이터를 분류한다.

Logistic Regression의 장단점

  • 장점:
    • 구현이 간단하고 해석 가능.
    • 선형 분리 가능 데이터에서 잘 작동.
    • 확률 값 제공(결과 해석에 유용).
  • 단점:
    • 비선형 데이터에 한계(비선형 커널 사용 불가).
    • 고차원 데이터에서는 성능 저하.

 

3. SVM vs Logistic Regression

특성 SVM Logistic Regression
분류 방식 초평면(마진 극대화) 기반 확률(로지스틱 함수) 기반
비선형 데이터 처리 커널 트릭으로 가능 비선형 데이터 처리 제한
다중 클래스 확장 One-vs-One, One-vs-Rest 필요 직접 다중 클래스 확장 가능
계산 복잡도 더 복잡함 상대적으로 간단함

 

4. MATLAB에서의 실습 

EEG 데이터 준비 및 전처리

오늘의 실습에서는 “GigaDB(https://gigadb.org/dataset/view/id/100542/File_page/15)의 sess01_subj36_EEG_MI.mat”를 사용하고자 한다. 해당 데이터는 오른손/왼손을 움켜쥐는 상상을 했을 때의 뇌파를 포함한다.

6일차 실습과 동일하게 아래의 코드를 통해 데이터를 불러온 후 확인해 보면, train과 test 데이터가 포함된 것을 알 수 있다.

load('sess01_subj36_EEG_MI.mat');

이 중 train 구조체 필드를 확인해 보면, 아래와 같이 이전과 동일한 변수들이 포함된 것을 확인할 수 있다.

 

이 중 y_dec, y_logic, y_class는 동일한 정보를 다른 형식으로 표현한 것인데, 오늘 실습에서는 y_dec을 사용할 것이다. class에 나와있는 대로, 1이 오른손 움직임 상상, 2가 왼손 움직임 상상을 의미한다.

EEG 데이터를 준비한 후, y_dec를 사용해 데이터를 class별로 나누어 저장해 보자.

% EEG 데이터 전처리 (CAR 처리)
EEG = EEG_MI_train.x'; % EEG 데이터 (채널 x 시간)
EEG = EEG - repmat(mean(EEG, 1), size(EEG, 1), 1); % 공통 평균 참조(CAR)

% 이벤트 시간 추출
events{1} = EEG_MI_train.t(EEG_MI_train.y_dec == 1); % 오른손 상상
events{2} = EEG_MI_train.t(EEG_MI_train.y_dec == 2); % 왼손 상상

이렇게 y_dec를 사용해 데이터를 클래스별로 나누고 나면, 각 이벤트를 기준으로 에포킹(Epoching)을 진행해야 한다. 에포킹은 이벤트 발생 시점을 기준으로 일정 시간 전후의 데이터를 추출하는 과정으로, 오늘 실습에서는 -1초부터 +4초까지의 데이터를 추출하여 뇌파 신호를 분석 가능하도록 전처리할 것이다.

 

에포킹은 아래의 코드로 진행할 수 있다.

% 에포킹 (Window: -1초 ~ +4초)
sf = EEG_MI_train.fs; % 샘플링 주파수
wnd_size = [-1 4]; % 윈도우 크기 (초)
for i = 1:length(events)
    for tr = 1:length(events{i})
        start_idx = round(events{i}(tr) + wnd_size(1)*sf);
        end_idx = round(events{i}(tr) + wnd_size(2)*sf);
        e_EEG{class_idx}(:, :, trial_idx) = EEG_data(:, start_idx:end_idx);
    end
end

다음으로, 지금까지 배운 Band-pass Filtering 및 파워 계산을 진행해 보자.

% 주파수 대역 및 시간 설정
bpf = [8 26]; % 주파수 대역 (8~26 Hz)
dur = ([0 4] - wnd_size(1)) * sf; % 특징 추출 시간 (0~4초)

% 필터링 및 신호 파워 계산
for i = 1:length(events)
    for ch = 1:size(e_EEG{i}, 1)
        for tr = 1:size(e_EEG{i}, 3)
            fil_EEG{i}(ch, :, tr) = bandpass(e_EEG{i}(ch, dur(1):dur(2), tr), bpf, sf); % Band-pass Filtering
            P{i}(ch, tr) = mean(fil_EEG{i}(ch, :, tr).^2); % Power 계산
        end
    end
end

% 데이터를 하나의 행렬로 결합 (X: 데이터, Y: 레이블)
X_train = [P{1}'; P{2}']; % 오른손과 왼손 데이터를 결합
Y_train = [zeros(size(P{1}, 2), 1); ones(size(P{2}, 2), 1)]; % 레이블 생성 (0: 오른손, 1: 왼손)

이제 생성한 train 데이터로 SVM 모델을 학습시키고, test 데이터를 생성 후 예측해 볼 것이다.

% SVM 모델 학습
SVMModel = fitcsvm(X_train, Y_train, 'KernelScale', 'auto', 'Standardize', true);

test 데이터도 동일하게 전처리 후 예측하면 끝이다.

% 테스트 데이터 준비 및 전처리
EEG_test = EEG_MI_test.x'; % 테스트 EEG 데이터
EEG_test = EEG_test - repmat(mean(EEG_test, 1), size(EEG_test, 1), 1); % CAR 처리

% 테스트 이벤트 추출 및 에포킹
events_test{1} = EEG_MI_test.t(EEG_MI_test.y_dec == 1); % 오른손
events_test{2} = EEG_MI_test.t(EEG_MI_test.y_dec == 2); % 왼손
for i = 1:length(events_test)
    for tr = 1:length(events_test{i})
        e_EEG_test{i}(:, :, tr) = EEG_test(:, round(events_test{i}(tr) + wnd_size(1)*sf):round(events_test{i}(tr) + wnd_size(2)*sf));
    end
end

% 테스트 데이터 필터링 및 파워 계산
for i = 1:length(events_test)
    for ch = 1:size(e_EEG_test{i}, 1)
        for tr = 1:size(e_EEG_test{i}, 3)
            fil_EEG_test{i}(ch, :, tr) = bandpass(e_EEG_test{i}(ch, dur(1):dur(2), tr), bpf, sf); % Band-pass Filtering
            P_test{i}(ch, tr) = mean(fil_EEG_test{i}(ch, :, tr).^2); % Power 계산
        end
    end
end

% 테스트 데이터를 하나의 행렬로 결합
X_test = [P_test{1}'; P_test{2}'];
Y_test = [zeros(size(P_test{1}, 2), 1); ones(size(P_test{2}, 2), 1)];

% SVM 모델을 사용한 예측
Y_pred = predict(SVMModel, X_test);

% 정확도 계산
accuracy = mean(Y_pred == Y_test) * 100;
disp(['SVM 분류 정확도: ', num2str(accuracy), '%']);

Logistic Regression 모델의 경우 이미 데이터셋을 준비했으니 바로 학습할 수 있다.

% Logistic Regression 모델 학습
LogisticModel = fitclinear(X_train, Y_train, 'Learner', 'logistic');

% Logistic Regression 모델을 사용한 예측
Y_pred_log = predict(LogisticModel, X_test);

% 정확도 계산
accuracy_log = mean(Y_pred_log == Y_test) * 100;
disp(['Logistic Regression 분류 정확도: ', num2str(accuracy_log), '%']);