GSR 신호로 데이터를 뽑으면 두 가지를 알 수 있습니다.
하나는 Tonic 한 성분으로 느린 변화의 기저선 신호로 저주파 성분입니다.
하나는 Phasic한 성분으로 스트레스 반응을 나타내는 고주파 성분이 있습니다.
이때 어떤 방법을 통해서 Tonic, Phasic 한 성분을 뽑아내고 분석 가능한지 조사했습니다.
$ git clone https://github.com/ledalab/ledalab.git
우선은 위 명령어를 git bash 에 넣어서 해당 프로젝트를 복사합니다.
복사된 프로젝트의 구성은 다음과 같습니다.
여기서 Leadlab 파일을 실행하면 소프트웨어가 실행됩니다.
소프트웨어는 다음과 같은 구조를 가지고 있습니다.
이제 이곳에 사용할 GSR 데이터 예제를 하나 다운로드 하겠습니다.
WESAD (Wearable Stress and Affect Detection) 에는 GSR 신호가 있으며,
스트레스를 받았을 때와 받지 않았을 때를 기록한 데이터가 존재합니다.
WESDA 다음의 데이터셋 페이지를 접속하면
데이터의 설명과 다운로드가 가능합니다.
데이터의 설명란에 첨부된 그림을 확인하면 다음과 같습니다.
스트레스를 받은 구간, 받지 않은 구간이 나타나 있습니다.
데이터를 다운로드 이후 압축을 해제하면 위와 같은 구성을 가지고 있습니다.
특정한 SX 디렉토리 내부 구성은 다음과 같습니다.
여기에서 SX_E4_Data 내부에 데이터가 존재합니다.
다음의 데이터들 중에서 “EDA” 라는 이름의 CSV 파일이 GSR 데이터입니다.
이를 활용하여 소프트웨어에 import를 하겠습니다.
다만, Leadlab 소프트웨어는 샘플링이 4Hz으로 고정이 되어 있습니다.
또한 시간 벡터가 없어서, 시간 벡터를 추가하는 작업을 해줬습니다.
변형한 데이터를 import 했더니 이런 데이터가 나타납니다.
총 6400초 가량 되는 데이터입니다.
상단에는 Analysis 라는 버튼이 있습니다.
여기서 선택할 수 있는 옵션이 2가지 있습니다.
CDA, DDA 분석 기법으로 총 2가지인데요.
우선은 “CDA” 알고리즘 분석 결과를 보겠습니다.
총 5개의 섹션으로 구분되어 나타나는 것을 볼 수 있습니다.
각 섹션의 설명은 다음과 같습니다.
첫 번째 섹션 : 원본 GSR 데이터를 그대로 표시합니다.
두 번째 섹션 : 파란색으로 Phasic 반응을 분리하고 남은 Tonic Component 만을 보여주고 있습니다.
세 번째 섹션 : Tonic 성분을 제외하고 Phasic 성분만을 보여줍니다.
네 번째 섹션 : Phasic 반응의 임펄스 모델로, 각 피크는 SCR를 의미합니다. 여기서 진폭이 큰 구간이 스트레스 구간, 진폭이 작은 구간을 평온한 구간으로 볼 수 있습니다.
다섯 번째 섹션 : Tonic 성분과 Phasic 성분을 합성하여 원본 GSR 데이터를 재구성한 값입니다.
하단의 설정 값은, 다음과 같은 의미를 가집니다.
τ (tau1, tau2):
감쇠 시간 상수로 Phasic 반응의 지속 시간을 결정합니다.
일반적으로 1~3초 사이로 설정되며, τ 값이 작을수록 빠르게 감쇠하는 피크로 모델링됩니다.
Smooth-Win:
GSR 데이터를 부드럽게 하는 Gaussian 윈도우의 폭을 나타냅니다.
Sig Peak:
Phasic 피크 감지를 위한 임계값입니다. 값이 낮을수록 더 작은 피크도 감지됩니다.
이번에는 DDA 알고리즘을 적용하여 분석한 화면입니다.
섹션의 설명은 마찬가지입니다.
그렇다면 해당 소프트웨어에서 Tonic, Phasic Feature을 분석하기 위해 사용한 알고리즘에 대해 분석하겠습니다.
Leadlab 소프트웨어는 CDA (Continuous Decomposition Analysis), DDA (Discrete Decomposition Analysis) 라는 2가지의 분석 방법으로 GSR 의 Phasic, Tonic Feature을 추출하는 것이 가능합니다.
이 두 알고리즘의 차이를 정리하면 다음과 같습니다.
| 특징 | CDA (Continuous) | DDA (Discrete) |
|---|---|---|
| 방식 | 연속적으로 Tonic과 Phasic을 모델링 | 불연속적으로 Phasic 피크를 감지 |
| Tonic 성분 | 감쇠 함수 기반의 기저선 추출 | 저주파 필터링을 통해 기저선 추출 |
| Phasic 성분 | 감쇠 함수로 연속적인 반응 모델링 | 개별 이벤트(피크) 감지 |
| 계산 복잡도 | 상대적으로 높음 | 낮음 |
| 정확도 | 높은 정확도로 세부 모델링 | 개별 반응은 명확하지만 세부 모델링 부족 |
| 적용 사례 | 정교한 분석, 연속적 SCR 반응이 중요한 경우 | 빠르고 단순한 피크 감지가 필요한 경우 |
각각의 알고리즘이 어떤 식으로 데이터에 작동이 되는지 CDA 와 DDA로 나누어 보겠습니다.
time = data.time; % 시간 벡터
conductance = data.conductance; % GSR 값 (Skin Conductance)
samplingrate = 4; %
Ledalab은 GSR 데이터를 시간 벡터와 **Conductance (GSR 값)**로 분리된 MAT 구조체에서 읽어옵니다.
기본 샘플링 레이트는 4Hz를 사용합니다.
WESDA GSR 데이터셋도 4Hz를 사용합니다.
tonic = smooth(conductance, smoothWin, 'gaussian'); % Gaussian 윈도우로 부드럽게 처리
Tonic 성분은 GSR 신호의 느리게 변화하는 기저선입니다. 이는 감쇠 함수를 사용하여 추출됩니다.
smoothWin은 부드럽게 만드는 윈도우의 폭으로, Ledalab GUI에서 설정할 수 있습니다.
위 그림에서 빨간색 성분을 Tonic으로 지정하는 것입니다.
세부적인 변화가 제거가 되고, 느리게 변화하는 기저선만 남습니다.
원본 신호에서 노이즈와 빠른 피크를 제거하고 부드럽게 변화하는 값만을 담습니다.
tau1 = 1;
tau2 = 3.75;
phasic_driver = deconvolve(conductance - tonic, tau1, tau2, samplingrate);
기본적으로 설정된 tau1, tau2의 값입니다.
또한 기본 겂에서 tonic 값을 감산한 배열을 사용합니다.
여기서 tau1, tau2를 통해서 감쇠함수를 생성합니다.
y(t) 가 tonic 성분이 제거된 데이터이고, h(t) 는 감쇠함수입니다.
이를 이용하여 위와 같이 역 컨볼루션을 수행합니다.
이를 통해 원본 데이터와 같은 길이의 Phasic_driver 벡터를 생성합니다.
SCR 피크의 감지란, 신경 활동에 의해서 갑작스러운 신호가 증가 후 감쇠하는 패턴을 잡아내는 부분입니다.
이때 GSR 신호의 중첩된 반응이 문제가 됩니다.
GSR 신호에서 SCR 피크가 발생하면, 각 피크의 영향이 시간적으로 중첩됩니다.
새로운 SCR 반응이 시작되기 전에, 이전 반응이 완전히 감쇠하지 않는 상태로 남아 있습니다.
이 때문에 역컨볼루션을 통해서 임펄스를 구하는 것입니다.
Phasic Driver 의 특정 time의 값이 클수록, 해당 시간의 SCR 반응이 강하게 발생했다는 정보를 담습니다.
reconstructed = tonic + convolve(phasic_driver, tau1, tau2, samplingrate);
error = sum((conductance - reconstructed).^2);
Phasic Driver 의 강도를 통해서 감쇠 함수와 컨볼루션하여 연속적인 Phasic 성분을 만듭니다.
이 성분을 Tonic 성분과 더하여 원본 신호를 재구성합니다.
tonic = smooth(conductance, smoothWin, 'lowess'); % 저주파 필터링
phasic_candidate = conductance - tonic; % 잔여 신호 계산
DDA는 Tonic 성분을 저주파 필터를 통해서 결정합니다.
예시 데이터를 통해서 시각화 하면 다음과 같습니다.
앞선 CDA 알고리즘과의 차이점은 해당 알고리즘은 Low-Pass-Filter를 사용하는 것입니다.
[pks, locs] = findpeaks(phasic_candidate, 'MinPeakHeight', threshold);
pks 에는 감지된 피크의 값을 담습니다.
locs에는 해당 피크의 index를 담습니다.
threshold를 받고, 해당 값보다 더 큰 경우에만 peak를 지정하는 것이 “MinPeakHeight” 방식입니다.
events = struct();
events.amplitude = pks; % 피크 진폭
events.time = time(locs); % 피크 발생 시간
events.duration = calculate_duration(phasic_candidate, locs); % 지속 시간
events 라는 struct를 생성합니다.
amplitude 에는 피크의 값이 담깁니다.
time 에는 그 시간이 담깁니다.
Peak to Peak 의 시간을 duration 내부에 담습니다.
시각화를 하면 다음과 같을 것이며, 여기에서 빨간색 점으로 표시되는 Peak 간의 간격이 duration으로 측정됩니다.
reconstructed = tonic + sum_events(events, time);
error = sum((conductance - reconstructed).^2);
실제 time 축에 맞춰서 Peak들을 tonic 성분에 더해줌으로써 원본 데이터를 재구성합니다.
GSR 데이터의 Phasic 과 Tonic 신호를 분석하기 위해 사용하는 방법과
소프트웨어에 대해 분석을 마칩니다.