'데이터 분석'에 해당되는 글 14건

  1. Topological Data Analysis (토폴로지 데이터 분석 방법) (6)
  2. 뇌영상 데이터 분석 - Create Brain Mask
  3. 실리콘 밸리에서도 주목받고 있는 토폴로지 데이터 분석
  4. Contrasts in Neuroimaging Data Anlaysis (2)
  5. smoothness estimation in SPM and AFNI (2)
  6. Voxel size determination through the MonteCarlo Simulation in AFNI
  7. [경성현] Topological Data Analysis를 이용한 전국 지방자치단체의 토건예산, 복지예산, 자살률의 관계 분석 (7)
  8. TCI & Functional Modular Organisation 논문 수락 후기 (4)
  9. Data Analysis (1): Neuroimaging Data loading using SPM8 toolbox (11)
  10. 유니코드 변환 파이썬 프로그램 - convert to unicode (python program)

토폴로지 데이터 분석은 다양한 분야에서 거대하고 복잡한 데이터로부터 의미있는 정보를 추출하는데 활용된 사례가 많이 있다. 많은 연구자들이 토폴로지 데이터 분석이 어떻게 작동하는지 원리를 알지 못한체 사용하는 사례가 많이 있기 때문에, 이번 포스팅에서는 토폴로지 분석이 왜 데이터 분석에서 효과적인 방법론인지에 대해 설명하고자 한다.

토폴로지 데이터 분석을 둘러싼 한가지 중요한 메세지는 데이터는 모양Shape을 갖고 있고, 그 모양이 우리에게 새로운 통찰을 줄 수 있다는 것이다. 분석을 통해서 완전히 새로운 메세지가 나타났다고 해도, 사실은 우리가 잘 알고 있는 것을 설명하는 것인 경우가 종종 있다.

토폴로지 데이터 분석에 대한 방법을 이야기 하기 전에 몇가지 서로 다른 형태의 데이터 분포에 대해서 이야기 하고자 한다. 위에 제시된 그림 중 제일 왼쪽에 보여지는 데이터는 직선 모양으로 대표될 수 있다. 이러한 데이터는 보통 선형회귀 분석을 통해서 데이터의 기울기를 찾을 수 있다. Fitting을 통해서 1차방정식의 계수를 구한다면, 데이터에 대해서 충분히 이해했다고 할 수 있을것이다. 두번째로 보여지는 데이터는 세개의 덩어리로 나뉘어진 데이터이다. 이러한 데이터는 1차 선형 방적식으로 설명할수는 없고, 최소 3개의 선형 방정식이 있어야 세개의 덩어리를 구분할 수 있을것이다. 두번째 예제에서는 데이터가 세군데의 서로 다른 곳을 중심으로 클러스터를 이루고 있기 때문에 평면에서 세개의 point cloud가 하나의 직선으로 대표될 수 없음을 쉽게 알 수 있다. 이러한 데이터를 보는 순간 사람들을 모양이 없는 데이터로군! 이라고 생각할 수도 있겠지만, 곧이어 '아! 이 데이터는 세개의 클러스터로 나눌 수 있겠군.' 이라고 생각할 것이다.  

세번째로 원형 모양의 데이터 분포를 생각해 보자. 이 데이터는 가운데 구멍이 뚤려 있는 원형 방정식으로 표현하면 가장 적절할 것이다. 직선 방정식으로 원형 모양의 데이터를 설명하고 싶은 사람은 없을 테니까. 마지막으로 데이터가 Y-모양 처럼 생겼다고 가정하면, 어떻게 할것인가? 이러한 데이터는 직선 방정식으로 표현할 수도 없고, 여러개의 덩어리 형태로 표현하기도 어려울 것이다. 그럼 어떻게 Y-모양 데이터를 설명할 수 있을까? 또는 하나의 방법으로 다양한 형태의 모양을 가진 데이터를 표현할 수 있는 방법은 없을까? 토폴로지 데이터 분석 기법에서 그 해답을 찾을 수 있을 것이다.

토폴로지 데이터 분석은 2007년에 스탠포트 대학교의 계산공학을 전공하는 Gurgeet Singh 박사과정 학생과 위상수학을 전공하는 Gunnar Carlsson 교수에 의해서 방법론이 세상에 처음 소개 되었다 (논문: Topological Methods for the Analysis of High Dimensional Data Sets and 3D Object Recognition). 이후 2011년도에는 스탠포드대학의 Monica Nicolau와 Gunnar Carlsson 교수는 토폴로지 데이터 분석 기법을 이용하여 유방암 환자의 Microarray 데이터를 분석했고, 유방암의 subgroups을 찾아내는데 성공했다 (논문: Topology based data analysis identifies a subgroup of breast cancers with a unique mutational profile and excellent survival).

논문이 소개된 년도를 보면 알겠지만, 수학의 토폴로지가 데이터 분석에 활용되기 시작한것이 2010년 쯔음이고, 데이터로부터 가치를 창출하는 것은 학계와 기업에 많은 관심과 수요가 예상되는 부분이다. 토폴로지 데이터 분석은 기계학습 방법론 측면에서 보면 비지도 기계학습 (unsupervised machine learning)에 해당되고, 보다 구체적으로는 "Partial Clustering"이라고 하는게 더욱 정확할 것이다.

토폴로지 데이터 분석은 크게 네 단계로 나눌 수 있다. 첫번째는 필터 함수를 구성하는 것이다. 필터 함수의 역할은 고차원의 데이터의 모양을 가장 잘 표현할 수 있도록 데이터를 Projection하기 위함이라고 할 수 있다. 위의 예제 그림에서는 Y축의 좌표값을 return하도록 필터 함수를 구성하면, Y-모양의 데이터 분포의 토폴로지를 가장 잘 추출할 수 있을 것이다. 두번째는 거리 함수를 정의하는 것이다. 고차원의 데이터가 필터함수를 통해서 하나의 값으로 요약되고 나면, 필터 값을 기준으로 데이터를 구획화 하게 되고, 구획화된 데이터 값들 간의 거리를 계산하게 된다. 거리 함수를 정의하는 방법도 여러가지가 있겠지만, 가장 많이 사용되는 거리함수는 유클리디언 거리 함수 있다. 세번째로 클러스터링 방법이다. 필터값에 따라서 데이터를 구획화 하고, 구획화된 데이터 값들 간에 거리를 구하고 나면, 이후에는 데이터 값들간의 거리를 기준으로 클러스터링을 지행하게 된다. 해당 필터 구간내에 몇개의 데이터들이 서로서로 모여 있는지, 아니면 2~3개의 덩어리로 서로 뭉쳐 있는지 등이 클러스터링을 통해서 계산되게 된다. 마지막으로 데이터를 시각화가 필요하다. 데이터 포인트로부터 결과로 생성된 simplicial complex를 그래프의 형태로 표현하고 나면 위의 그림에서 (C)의 형태가 되는데, 그래프에서 각 노드Node는 Cluster이고, 선Edge는 클러스터간의 교집합이 존재함을 표현한다. 마지막으로 노드의 색은 관심있는 값을 표현하게 되는데, 위의 예제에서는 각 노드 내의 데이터 값이 같는 필터 값의 평균을 표현했다. 

토폴로지 데이터 분석은 다양한 분야의 데이터 분석에서 많이 활용되고 있고, 토폴로지 데이터 분석이 각광받고 있는 이유는 기존의 클러스터링 방법으로는 찾지 못하는 "데이터 내의 특이한 subgroups"을 잘 추출하는데 있다. P.Y. Lum은 미국 NBA 농구선수들의 분당 리바운드, 슈팅, 피스, 파울 등의 수치 값들을 이용해서 토폴로지 데이터 분석을 시행했더니, 기존에 잘 알려진 공격형, 수비형 선수를 구분해 냈을 뿐만이 아니라 All star players들도 하나의 subgroup으로 검출해 냈다. 이는 기존의 고전적 비지도학습 방법으로는 확인할 수 없덨던 결과이다 (논문: Extracting insights from the shape of complex data using topology).

마지막으로 토폴로지 데이터 분석이 뇌영상 데이터 분석에도 적용한 연구도 있다. S. Kyeong은 토폴로지 데이터 분석을 뇌영상 데이터 분석에 적용하여 정상군과 환자군을 구분해 내는데 성공했다. 연구 초기의 목표는 토폴로지 데이터 분석으로 주의력결핍/과잉행동 장애 환자의 아형을 구분해 내는 것 이었는데, 실제 데이터 분석에서는 아형을 구분해 내지는 못했다. 연구 결과는 PLoS One에 게제되었다 (논문: A New Approach to Investigate the Association between Brain Functional Connectivity and Disease Characteristics of Attention-Deficit/Hyperactivity Disorder: Topological Neuroimaging Data Analysis). 본 연구는 뇌영상 데이터를 분석하는데 토폴로지 데이터 분석 기법을 처음으로 제기 했다는데 큰 의미가 있다.

신고

MATLAB을 이용하여 뇌영상 데이터를 분석하다 보면, 뇌영역에 해당되는 부분의 마스크Mask를 만들어야 하는 경우가 있습니다. 이러한 경우에는 뇌영상 데이터 분석 - Matlab Index scheme 강의에서 처럼 MATLAB의 index 기능을 이용하면 회색질, 백색질, 뇌척수액 등에 해당되는 뇌 영역을 indices 값을 얻을 수 있고, 각각의 인덱스 값의 합집합을 이용하면 전체 뇌영역에 해당되는 마스크Mask를 얻을 수 있습니다.

위에 그림은 회색질(Grey Matter, GM), 백질(White Matter, WM), 뇌척수액(Cerebro-spinal Fluid, CSF)의 3차원 공간에서의 확률 분포를 보여주고 있습니다. 각각의 영상은 SPM (Statistical Parametric Mapping)을 설치하면 자동으로 설치되는 영상파일 입니다.

이제 다음의 MATLAB 명령어를 통해서 뇌마스크(Brain Mask)를 만들어 보겠습니다. 다음과 같이 한줄씩 MATLAB 명령창(Command Window)에 입력해 보시면서, 각각의 명령어가 의미하는바가 무엇인지 결과를 확인해 보시면 많은 공부가 될것 같습니다. 

>> % Specify file path >> fn_GM = fullfile(spm('dir'),'tpm', 'grey.nii'); >> fn_WM = fullfile(spm('dir'), 'tpm', 'white.nii'); >> fn_CSF = fullfile(spm('dir'), 'tpm', 'csf.nii'); >> >> % read volume header information >> vo_GM = spm_vol(fn_GM); >> vo_WM = spm_vol(fn_WM); >> vo_CSF = spm_vol(fn_CSF); >> >> % read 3D volume image data >> GM = spm_read_vols(vo_GM); >> WM = spm_read_vols(vo_WM); >> CSF = spm_read_vols(vo_CSF); >> >> % find indices of brain matter mask (idbrainmask) >> idx_gm = find(GM>0.5); % GM mask with Prob(GM>0.5); >> idx_wm = find(WM>0.5); % WM mask with Prob(WM>0.5); >> idx_csf = find(CSF>0.5); % CSF mask with Prob(CSF>0.5); >> >> % Set operation to compute union of two indices >> idbrainmask = union(idx_gm, idx_wm); >> idbrainmask = union(idbrainmask, idx_csf); >> >> % Fill ones for ROI >> IMG = zeros(size(GM)); % create zeros matrix >> IMG(idbrainmask) = 1; >> >> % Write 3D image >> vout = vo_GM; % copy header information >> vout.fname = 'brainmask.nii'; >> spm_write_vol(vout,IMG);

ex1.m

위의 프로그램을 실행하기 위해서는 확률맵(grey.nii, white.nii, csf.nii)이 필요한데, 이 파일들은 위에 설명되어 있듯이 SPM을 설치하고 MATLAB에서 Set Path로 SPM의 경로를 설정해 주어야 접근 가능한 파일들입니다.

신고

Slideshare를 통해서 토폴로지 데이터 분석(Topological Data Analysis, TDA)에 대한 발표 자료를 2014년 4월에 공유했다. 슬라이드 쉐어에서는 나의 슬라이드를 본 사람들이 어떤 경로로 찾아왔는지에 대한 정보와 어느나라 사람들이 주요하게 관심을 갖고 있는지의 여부를 자동으로 분석해주는 기능이 있어서 한번 살펴봤다.

한국 사람중에 나의 슬라이드를 본 사람들은 대부분 얼굴책 등에서 내가 공유한 것을 보고 링크를 타고 온 사람들이라고 생각된다. 하지만 미국이나 독일에서 슬라이드를 본 사람은 분명히 검색을 통해서 나의 토폴로지 데이터 분석 슬라이드를 찾았을 것이다. 또한, 아래 그림 중에서 국가별로 슬라이드를 '본 사람 수'의 그래프에서도 볼 수 있듯이 토폴로지 분석은 미국, 독일, 인도 등 IT 강국에서 큰 관심을 갖고 있는 분야임은 분명한 것 같다.

미국 내에서도 특히 어느 지역의 사람들이 관심을 갖고 있는지 궁금해서 Google Fusion Table의 heat map 기능을 이용해서 지도에 뿌려보니, 실리콘 벨리 지역의 사람들이 토폴로지 데이터 분석에 많은 관심이 있는 것으로 보인다 (아래 그림). 꼭 토폴로지 데이터 분석이 아니더라도, 쌓여있는 데이터에서 의미 있는 정보를 찾아내고 그것으로부터 가치를 부여하는 일은 분명 많은 수요가 있을 것으로 기대된다. 위에 bar-graph는 2014년 4월부터 2015년 3월 18일까지의 누적 수치이고, 아래 heat map은 최근 1달(2015년 2월 19일-3월 18일)간의 정보를 통해서 얻은 결과이다. heat map도 전체 viewer에 대해서 그려고보 싶었는데, slideshare에서는 최근 1달간의 방문자 기록만 raw 데이터 형태로 추출이 가능하다.



신고

SPM 등의 뇌영상 데이터 분석 툴을 이용한 뇌영상 데이터의 분석은 기본적으로 각 복셀의 영상에 할당된 데이터 값을 일반 선형 모델 (General Linear Model, GLM)을 이용하여 모델링하고, 실제 데이터와 모델이 얼마나 잘 맞는지 통계적으로 테스트 하는 것이다. 특정 복셀 $i$에 대해서 $Y_{i} = XB_i + E_i$로 모델링 했을때 $X$는 디자인 행렬이되고, 벡터 $B_i$는 분석을 통해서 추정되는 파라미터이며, $E_i$는 에러를 의미한다. 이때 contrast는 $c'B$를 통해서 계산된다. 뇌영상 데이터에서 $c$는 보통 행벡터(column vector)를 의미하고, $c$를 통해서 다양한 contrasts로 결과를 확인할 수 있다. 

벡터 $c$는 contrasts의 가중치를 의미하고, 확인하고자 하는 대부분의 contrast의 Null hypothesis는 $c'B=0$이다. 구체적으로 contrast 가중치를 구성하는 방법에 대해서 다음의 예를 통해서 설명하고자 한다.

위 그림과 같이 세 그룹에 대한 데이터가 있을때, 가장 먼저 생각해 볼 수 있는 통계 분석은 일원분산분석(Analysis of variance, ANOVA)이고 이때의 contrast는 F-contrast로 세 그룹 중 발생할 수 모든 차이를 보고자 할때는 다음과 같은 방법으로 만들 수 있다.

또는 결과는 동일하지만 다른 방법으로 표현하고 싶다면, 다음과 같은 방법도 가능하다.

이제 각 그룹간 차이를 보고자 한다면, 다음과 같은 방법으로 분석이 가능하다. 하지만 분석의 초점이 ANOVA에서 그룹간 차이가 나는 영역을 찾고 해당 영역 내에서 세 그룹간 값이 어떻게 되는지 통계적으로 분석하는 것이 목표라면, F-contrast의 결과로 나온 영역에 대해서 평균 Beta 값을 추출해서 SPSS 등에서 post-hoc 분석을 진행하는 것이 옳다. MATLAB에서 post-hoc 분석이 가능하다면 말리지는 않겠다. SPM에서 T-contrast는 다음과 같은 방법으로 만들 수 있다.

  • -1    1    0:  spm{T} contrast for sample2 > sample1

  •  1     0   -1:  spm{T} contrast for sample1 > sample3

  •  2   -1   -1:  spm{T} contrast for sample1 > (sample2 + sample3)

이제 confounding effect를 제어한 후에 그룹간 차이를 비교하는 분석을 생각해 보자. 이러한 분석을 공변량분석 (Analysis of Covariance, ANCOVA) 이라 불린다. 다음과 같은 데이터가 있다고 가정해 보자.


이제 공변량(covariate1)의 효과를 제거한 후에 두 그룹간의 차이를 비교하는 F-contrast를 생각해 보다. 다음과 같은 spm{F} contrast를 통해서 sample1과 sample2 간의 값의 차이를 비교할 수 있다.



신고

Smoothness estimation은 MonteCarlo simulation을 위해서 반드시 필요한 과정입니다.

SPM으로 영상 데이터를 분석했다면, SPM.mat 파일의 Field 값을 확인함으로써 smoothness를 확인할 수 있습니다.

>>load SPM; % SPM 결과 파일이 저장된 폴더에서 실행 >>M = SPM.xVol.M; % 변환행렬 정보를 가져옴 >>VOX = abs(diag(M)); % 대각행렬 정보가 볼셀 사이즈 >>FWHM = SPM.xVol.FWHM; % FWHM in voxel unit >>FWHMmm = FWHM.*VOX(1:3)'; % FWHM in mm unit >>disp(FWHMmm); 

SPM에서 Gaussian random field theory를 기반으로 smoothness를 estimation하고, 이것은 spm_est_smoothness을 통해서 계산됩니다. 

위의 과정을 통해서 확인한 FWHMmm 정보는 AFNI의 3dFWHMx의 명령어를 통해서 estimation한 smoothness와 완전히 동일하지는 않지만, 비슷한 수준의 값이 나와야 합니다. AFNI가 설치되어 있다면 다음과 같이 실행해 보세요. 

~>3dFWHMx -mask mask.hdr -input ResMS.hdr % SPM 결과 파일이 저장된 폴더에서 실행

여기서 얻은 smoothness를 기반으로 MonteCarlo simulation을 시행하면, 이것이 AlphaSim-corrected p-value가 됩니다.

관련 글은 다음의 링크에서도 확인이 가능합니다.
https://www.jiscmail.ac.uk/cgi-bin/webadmin?A2=spm;bb3ad6d.1308

신고

뇌영상을 이용한 뇌과학 연구는 대부분 다음과 같은 질문에 답하는 것이다.

  • 3차원의 뇌에 어떤 영역이 활성화 되었는지?  
  • 특정 영역의 시계열 데이터와 상관성이 높게 나오는 뇌영역은 어디인지? 

생물정보학에서 다루는 Microarray 데이터도 마찬가지 이지만, 뇌영상 데이터도 multiple comparison에서 발생하는 false positive를 조절하는 방법에 대해서다양한 해법들이 있다. 가령, false discovery rate (FDR) 또는 family-wire error rate (FWE) 등이 전통적으로 가장 많이 이용되어 왔던 multiple comparison correction 방법들이다. 

뇌영상 데이터는 특정 복셀에서 통계적으로 유의미한 차이를 보인다고 했을때 "아, 이 볼셀에서 통계적으로 유의미 하니까 해당 영역이 중요하겠네!" 라고 생각하면 안된다. 뇌는 인접한 뇌영역들 같이 비슷한 역할을 하는 뉴런들이 있어서 특정 복셀 1개만 통계적으로 유의미한 차이를 보이고, 인접한 영역에 있는 복셀들에서도 비슷한 양상이 보여야 한다. 전문 용어로 차이가 나는 영역 덩어리 (continuous voxel size)가 얼만큼 큰지?의 여부에 따라서 해당 영역이 false positive인지를 판별해야 한다. 최근 뇌영상 연구에서는 multiple comparison correction을 하지 않은 분석 결과는 좋은 저널에 출판하기 어려울 것이다. 

뇌영상 연구의 Multiple comparison에서 중요한 것은 다음의 두가지 질문일 것이다.

  • 각 복셀에서의 통계적 유의미성이 어느정도로 해야 하는지? (보통 뇌영상(fMRI or MRI) 분석에서는 p<0.005 or p<0.001을 많이 사용) 
  • 해당 threshold에서 덩어리져 있는 영역-덩어리를 찾아야 할텐데, 덩어리(or continuous voxel size)의 크기는 얼만큼이 적당한지?  

위의 질문은 MonteCarlo (MC) simulation을 통해서 할 수 있는데, SPM with REST toolbox와 AFNI의 AlphaSim을 통해서 시뮬레이션이 가능하다. MC simulation을 위해서는 여러가지 파라미터가 필요한데, 각각의 파라미터의 이름은 프로그램마다 조금씩 다르지만, 대략적으로 다음과 같은 의미를 가진다고 할 수 있다.

  • mask: MC simulation을 하는 voxel size, image dimension, and brain boundary 등의 정보를 담고 있음.
  • rmm: 얼만큼 떨어져 있는 복셀을 인접한 복셀로 볼 것인지? 볼셀의 중심과 중심의 거리
  • NN: nearest neighbor를 어떻게 정의할 것인지?  가령, 각각의 볼셀이 6면체로 되어 있는데 복셀의 face가 붙어 있는 것을 연결된 복셀로 볼 것인지? edge가 붙어 있는 것을 연속적으로 연결된 복셀로 볼것인지? 아니면 corner가 붙어 있는 것을 연속적으로 연결된 볼셀로 볼 것인지? 의 여부를 결정할 수 있다.
  • FWHM: 이것은 결과 데이터의 smoothness를 의미함. 단순히 smoothing kernel의 FWHM 값을 입력하면 안되고, AFNI나 SPM의 smoothness estimation 방법을 통해서 계산한 결과 값을 입력해야 한다. smoothness estimation을 다룬 포스팅을 확인하기.



신고

Topological Data Analysis 방법에 대해 궁금한 사항은 Slideshare를 통해서 공개된 자료를 참고해 주시면 되고, 여러 논문들에서도 방법을 확인하실 수 있습니다. 뉴스타파는 제가 제일 신뢰하는 언론이기에 뉴스타파 홈페이지를 자주 방문하곤 합니다. 전국 242개 지방자치단체 토건예산, 복지예산, 자살률 자료가 공개 된지는 두어달 전이지만, 그동안 그냥 눈팅만 하다가 이제야 데이터를 직접 분석해 보기로 했습니다. Topological Data Analysis (이하 TDA)는 데이터 간의 거리 정보를 이용하여 데이터 간에 관계를 분석하는 기법으로 순수 수학인 '위상수학'에 뿌리를 두고 있습니다. 

데이터 분석을 위해서 사용한 데이터는 2009년 복지예산과 토건예산의 비율, 2012년 복지예산과 토건예산의 비율, 그리고 2012년 10만명당 자살자수(연령표준화) 데이터를 이용하여 242x3 의 크기를 갖는 데이터를 구성했고, 각 컬럼 단위로 데이터를 표준화 해서 사용했습니다. 표준화 한 후에는 자살률에 대한 효과를 극명하게 관찰하기 위해서 자살률 데이터에 x2를 하여 분석을 진행했습니다. TDA를 위해서는 거리 함수와 필터 함수가 필요한데, 거리는 각 데이터와 데이터 간의 L2-distance로 정의했고 필터 함수는 L-infinity eccentricity로 정의했습니다. 아래 그림에서 각 노드의 색깔은 필터 값을 의미합니다.

분석의 결과로 그래프가 생성되는데, 각 그래프의 노드에는 필터 값이 비슷하면서 거리가 가까운 데이터들이 몰려 있습니다. 가령 Group1에는 광주(북구), 전북(본청), 대구(북구) 가 비슷한 거리를 갖는 것으로 분석 되었는데, 아래 그림에서 볼 수 있듯이 Group1에 들어 있는 지방자치 단체의 경우에 자살률이 낮고, 2009년과 2012년의 복지예산이 토건예산보다 4배 이상 많은 것으로 나타났습니다. Group2도 자살률이 낮지만, 결과로 생성된 Topology에서는 Group1과는 다른 위치에 있습니다. 데이터를 자세히 살펴보니, Group2의 경우에는 2009년과 2012년에 모두 복지예산이 토건예산보다 많은 것은 물론이고, 3년 사이에 복지예산/토건예산의 비율이 거의 2배 이상 증가 했음을 알 수 있었습니다. Group2에 속한 지방자치 단체로는 서울(노원구), 대구(달서구), 대전(서구) 가 있습니다.


복지예산과 토건예산의 비율이 자살률과 관련이 있다는 것은 Group3의 결과를 보면 알 수 있는데요, Group3의 경우에는 자살률은 Group1과 Group2에 속한 지방자치단체보다 자살률이 2배로 높게 나타났지만, 2009년과 2012년의 복지예산과 토건예산의 비율이 자살률이 낮은 그룹에 비해서 현격하게 줄어들어 있음을 알 수 있었습니다. Group3에 포함된 지방자치단체로는 강원(홍천과 양양), 충북(단양), 전북(장수), 전남(함평), 경남(함양)이 있습니다.



Group4에 포함되어 있는 지방자치단체의 경우에는 인구 10만명당 자살률이 약 30명 정도 이고, 위의 그래프를 보면 복지예산의 비율을 점점 높여 가려는 노력을 기울이고 있다고 볼 수 있습니다.

이번 데이터 분석을 진행하면서 TDA를 통해 데이터의 insight를 찾을 수 있음에 대한 더욱 큰 확신이 들었고, 실제로 복지예산과 토건예산의 비율이 자살률과 크게 관련 있다는 결과를 지방자치단체장님들께서 인지하시어 전국 각지에 좋은 복지 정책들이 제공되었으면 좋겠다. 그래서 떠나고 싶은 나라. 살기 싫은 나라. 가 아니고, 내가 국가로부터 받은 (복지 등) 혜택을 어떻게 다 보상해야 할까? 를 고민하는 국민이 늘어나는 나라가 되었으면 좋겠다. Group1,2와 Group3에 속한 지방자치단체장의 정당 구성까지 살펴보고 싶었는데, 그렇게 하면 거의 논문 수준이 될꺼 같아서 여기까지만!

여담으로 국가수리과학연구소에서 3년간 근무하면서 얻은 가장 큰 수확은 인성의 뇌신경 상관성 연구 논문을 출판한 것이고, 두번째로 큰 수확은 Topological Data Analysis에 대한 수학적 이론과 방법을 터득하여 실제 데이터 분석에 활용할 수 있는 수준이 되었다는 것이다. 아직 해결하지 못한 부분은 필터 함수를 2차원으로 적용하는 방법인데... 음, 올해 안에 해결할 수 있도록 해야지.


작성자: 데이터과학자 경성현



신고

뇌과학 분야에서 출판한 첫 논문이기에 꼭 후기를 남기고 싶었다. 
물리학 분야에서 첫 논문이 출판되었을때 후기를 썼던 것 처럼... 

논문의 Manuscript가 대략적으로 완성된 시점은 2012년 12월 쯤으로 기억한다. 데이터 획득부터, 뇌영상 데이터의 분석, 그리고 논문 작성의 전체 과정에 직접 참여했기 때문에 나에게 의미가 더욱 각별하게 느껴지는 논문이다. 이번 연구는 "기질Temperament에 따라서 뇌네트워크의 연결성이 다르게 나타나고 그로 인해서 서로 다른 모듈 구조를 갖는다"는 것을 주요 결과로 하고 있으며, 논문 초안의 제목은 <Functional and morphometric neural mechanism underlying personality differences: Introverts vs. Extraverts> 으로 정했다. 인성의 외향성은 기질의 위험회피 척도와 자극추구 척도로 구분하는 것이 무리일 수도 있다는 것은 어느정도 예상했고, 특히 성격심리학자들이 보기에는 완전 엉터리로 들릴 수도 있겠다는 생각도 했다. 그리고 이러한 나의 생각은 여러 관련 분야의 선생님들께 조언을 구하는 과정에서도 가장 많이 질문 받고 또 진지하게 토론했던 부분이었다. 뭐, 처음이니까 부족한 부분이 있기 마련이고 부족한 부분은 저널 리뷰어들의 질문에 답을 하는 과정에서 보충 될 수 있지 않을까? 라는 생각에 여러 선생님들께 조언 받은것은 따로 정리는 해 두었지만, 처음 논문을 투고 할때는 보완하지 않았다. 

논문을 투고하기 전에 연구 결과의 해석과 결과의 타당성에 대해 전문가들의 조언을 듣고 싶었다. 처음 논문을 준비할때 공동 저자로 참여한 연구자들은 대부분 물리/공학을 기반으로 뇌과학을 연구했던 분들이었기 때문에, 논문의 특성상 심리학이나 정신의학 분야에서 뇌과학을 연구하고 있는 분들의 조언이 꼭 필요하다고 생각했다. 제일 먼저 찾은 곳은 성신여대 심리학과에 계신 K교수님과 여러 대학원생 선생님들이었다. 발표를 듣고 난 후에 대부분 "선생님들의 반응은 방법론과 결과에 대해서는 재미있으나, 기질 및 성격 검사(Temperament and Character Inventory, TCI)에서 측정된 위험회피(Harm Avoidance, HA) 척도와 자극추구(Novelty Seeking, NS) 척도로 내성적인 성향의 사람과 외향적인 성향의 사람을 구분하는 것은 위험한것 같다. 이미 성격심리학자들이 내성/외향을 구분하기 위해 개발한 성격검사지가 있는데, 그것을 사용하지 않고 연구자 임의로 내성과 외향을 정의하는 것은 많은 reviewer들에게 공격 받을 것이다." 라는 조언을 해 주셨다. 이후에 고려대학교 심리학과와 연세대학교 정신건강의학과를 연달아 찾아다니며 발표를 했고 조언을 구했으며, 세부적인 측면에서는 차이가 있었지만 큰 맥락에서는 대부분 비슷한 조언을 해 주셨다. 위험회피 척도와 자극추구 척도가 음의 상관관계에 있고 이들 두개의 척도로 그룹을 나누었다면, 그룹지어진 결과 그대로 'high HA and low NS' 그룹과 'low HA and high NS' 그룹으로 나누는 것이 더 설득력 있는 연구결과가 될꺼라는 조언이 지배적이었다.

여러 선생님들께서 조언해주셨던  부분에 대해서 저널 리뷰어에게도 비슷한 조언을 받았고, 어떤 부분이 부족한지 어느정도는 미리 알고 있었기에 내용을 보충하는데 큰 어려움이 있거나 많은 시간이 들지는 않았다. 하지만 연구 논문의 서론 부분이나 토의Discussion을 작성하는 과정에서 심리학자나 정신의학 분야를 전공하신 선생님들의 적극적인 도움 없이는 논리에 헛점이 발생할 수도 있겠다는 생각에 정신과 의사 선생님을 공동 저자로 섭외했고 도움을 받았다. 그러나, 처음 초안을 너무 허술하게 잡았기 때문에 부족한 부분이 많을 수 밖에 없었기 때문에 두번이나 논문 게재를 거절 당했다. 그래도 우여곡절 끝에 Brain Research라는 저널에서 논문 게재를 허락 받았으니 얼마나 다행인지 모른다. NeuroImage에 투고했던 논문을 수정/보완하여 Brain Research에 재투고 했었는데 NeuroImage와 Brain Research 모두 NPRC consortium에 멤버로 들어있는 저널들이었기 때문에 서로 Reviewer's comments를 공유해줬고, 논문 수락 process도 빨랐던것 같다. 초기에 논문 제출할때와는 달리 최종적으로 수락된 논문의 제목은 <Functional network organizations of two contrasting temperament groups in dimensions of novelty seeking and harm avoidance> 이다.

연구 결과는 International Workshop in NeuroDynamics 2014 (July 14-17 2014, Castro-Urdiales, Spain) 학회에서 처음으로 소개되었고, 발표 자료는 Slideshare를 통해 공개했다. 뭐든 처음이 가장 어렵다고 한다. 내게도 이번 연구가 뇌과학 분야에서는 처음으로 출판하는 논문이었기에 많은 시행착오가 있었다. 하지만 이번 논문 게재를 바탕으로 현재 진행중인 ADHD 환자의 Topology와 뇌네트워크 분석관련 연구도 잘 정리해서 논문으로 완성하는 날을 생각하번 벌써부터 가슴이 뛴다.

이 글을 통해서 공동저자로서 함께 결과를 내주신 여러 선생님들과 도움을 주신 모든 분들께 다시한번 감사인사를 드립니다. ^.^


작성자: 뇌과학자 경성현

신고

일반적인 데이터 분석에 관련된 기술을 포스팅하고 싶었지만, 데이터 분석은 data specific한 부분들이 있기 때문에 일반적인 데이터 분석 및 시각화 기법에 대한 강의는 어려울것 같고, 뇌영상 데이터와 트위터 데이터 수집 및 분석과 관련된 포스팅을 연재하고자 합니다.

일단 뇌영상 데이터 분석 기법으로 강의를 시작하는 이유는 최근 5년 동안 제가 연구해온 분야로 expert까지는 아니어도 intermediate 이상의 실력은 된다고 생각하고 있기에, 지금까지 습득한 노하우를 관련 분야에 계신 분들께 나누고 싶은 생각이 들었습니다.

뇌영상 분석에 사용되는 툴은 여러가지가 있지만, 보통은 MATLAB 기반의 SPM8, linux 기반에서 작동하는 AFNI 또는 FSL 등이 가장 많이 이용되고 있습니다.어떤 소프트웨어가 가장 좋은가? 라는 질문의 대한 답은... 내가 사용하기 편한 소프트웨어. 가 아닐까? 생각됩니다. 우수한 프로그램은 고성능의 알고리즘으로 무장하여 계산속도를 극대화 하는 것도 중요하지만, 사용자가 얼마나 편하게 접근할 수 있는가?에도 많은 노력을 기울여야 한다고 생각합니다.

필자는 MATLAB이 사용하기 편하고, engineering 기반이 아닌 사람들과 소통하기에 (뇌연구는 심리학, 정신의학, 물리학, 통계학, 전자공학, 의공학 등 다양한 전공을 가진 연구자들이 있기 때문에 공동연구와 연구자들간의 소통이 중요함) 가장 적합한 프로그램이라 생각하고, MATLAB을 사용하기 시작했습니다. 앞으로 'Data Analysis (for neuroscientist)'라는 주제로 한글 인터넷 강좌를 연재하고, MATLAB 뿐만이 아니라 python 및 linux script에 대한 내용도 다룰 예정입니다. 뇌영상 데이터를 연구 재료로 사용하고 계신 연구자들 중에서, GUI 환경의 분석에서 벗어나고자 하시는 분들께 조금이라도 도움이 되었으면 좋겠네요^^ 오늘은 그 첫번째 강좌로 "Data loading and writing using SPM8 toolbox"에 대한 강의를 하고자 합니다.

SPM8은 프로그래밍을 잘 몰라도 사용할 수 있는 막강한 GUI환경을 제공합니다. 이 GUI를 이용하면 뇌영상 데이터(fMRI, EEG, PET 등)의 전처리를 수행할 수 있습니다. 물론 GUI를 사용하지 않고, MATLAB command line을 통해서 더욱 편리하게 전처리를 할 수도 있지만, 그러기 위해서는 프로그래밍에 대한 기초 지식이 있어야 해요. 하지만 겁먹을 필요는 없고요, 앞으로 하나하나 배워나가면 됩니다.

일단 MATLAB에서 SPM8의 툴발스를 이용하여 뇌영상 데이터를 불러들이고, 또 어떤 연산 결과를 새로운 이름의 영상으로 저장하고자 한다면,

(1) SPM8 toolbox를 다운로드 받아야 합니다.

(2) 예제로 사용할 뇌영상 데이터가 필요합니다. 데이터가 없다면 SPM 홈페이지에 있는 auditory fMRI data를 사용하실 수 있습니다. (MoAEpilot.zip)


이제 다운로드 받은 영상 데이터를 matrix 형태로 불러들이기 위해서는 MATLAB을 실행시키고, 다음과 같이 명령어를 순서대로 입력하면 됩니다.

>addpath /Users/skyeong/spm8; % spm8에서 제공하는 모든 함수를 어떠한 경로에서도 사용할 수 있도록 설정. >data_path = '/Users/skyeong/Downloads/MoAEpilot/fM00223' ; % fMRI 데이터 위치의 절대경로 >fns = spm_select('FPList',fullfile(data_path),'^fM.*\.img$'); % 파일 이름이 fM으로 시작하고, 확장자가 .img인 모든 파일을 선택. >vs = spm_vol(fns); % 뇌영상의 header 정보 불러오기. >IMG = spm_read_vols(vs); % 뇌영상 데이터를 matrix 형태로 불러오기.

vs 변수에는 뇌영상 데이터의 header 정보가 저장되어 있습니다. 다음과 같이 MATLAB command line에서  vs(1) 이라고 입력하면, 첫번째 뇌영상 볼륨의 정보를 볼 수 있어요. 

>vs(1) ans = fname: '/Users/skyeong/Downloads/MoAEpilot/fM00223/fM00223_004.img' dim: [64 64 64] mat: [4x4 double] pinfo: [3x1 double] dt: [4 1] n: [1 1] descrip: 'SPM compatible' private: [1x1 nifti]

여기서 fname은 첫번째 볼륨vs(1)이 위치한 full file path를 의미하고, dim은 뇌영상 데이터의 dimension정보, dt(=data type)는 뇌영상 데이터의 저장 형태입니다. 보통 프로그래밍 언어에서는 boolean, integer, float 에 따라서 데이터를 저장하는 용량이 다른데, [4 1]은 복셀 하나에 저장되는 숫자가 4 bytes로 표현된다는 의미이고, 보통 4 bytes 이면 양의 정수를 표현하기에 적합하다고 생각하면 됩니다. 만약 어떤 연산의 결과가 소수점을 동반한다면 vs(1).dt=[16 1]로 설정해야 하고, 이렇게 하면 한 복셀당 16 bytes의 용량이 필요하기 때문에, 4 bytes로 저장될때보다 뇌영상 데이터의 용량이 4배로 늘어나게 되요. data type이  높다고 좋은것은 아니고, 계산결과가 소수형인지, 양의 정수형인지, 음의 정수를 포함하는지를 잘 판단하여 설정하는 것이 하드디스크의 용량을 적게 사용할 수 있는 노하우입니다. MATLAB의 Numeric Types에 대해서는 MathWorks의 홈페이지를 참고하면 자세히 알아볼 수 있어요.

이제 IMG 변수에 담긴 숫자들은 뭘 의미하는지 알아 볼까요? IMG변수에는 뇌의 활동에 따른 BOLD signal이 숫자의 형태로 각 볼셀에 저장되어 있습니다.

>size(IMG) ans = 64 64 64 96

MATLAB command line에 size(IMG)를 입력하면 IMG 변수가 4차원 형태로 되어 있음을 알 수 있다. 처음 3개 숫자는 x, y, z 축의 복셀 숫자를 의미하고, 네번째 숫자인 96은 시간축 정보를 의미합니다. 즉, 실험을 통해서 96개의 volumes을 획득한 것이고, 만약 repetition time (TR)이 2초 였다면, 96x2 sec = 192 sec 동안 fMRI 영상을 획득한 셈이겠죠? 

이제 첫번째 볼륨vs(1)의 intensity 값의 분표를 MATLAB의 hist() 함수를 이용하여 확인해 볼께요.

>figure; >data = IMG(:,:,:,1); % 첫번째 volume의 intensity 정보를 data라는 변수에 저장. >hist(data(:)); % 모든 복셀의 intensity 값의 분포를 확인. >figure; >hist(data(:),100); % 모든 볼셀의 intensity 값의 100개의 bins으로 나눠서 분포를 확인.


강좌를 올리는게 쉽지는 않네요, 몇줄 안되는 코드이지만 프로그래밍은 직접 실습해보는게 중요합니다. 관심 있으신 분들은, 꼭 집접 확인해 보시길. 다음 강좌에서는 MATLAB을 이용한 regression analysis, bandpass filtering, network analysis 등을 소개할 예정입니다. 질문은 다른 분들도 함께 공유할 수 있도록 블로그나 패이스북의 덧글로 부탁드립니다.

신고

파이썬에서 한글을 다루다 보면, 인코딩에 대한 이슈를 그냥 지나칠 수 없다. 파이썬의 장점은 methods의 입력 데이터 형식을 지정하지 않아도 된다는 것이다.

C/C++에 익숙했던 분들은 아주 생소하게 느껴질 수 있는 부분이다.

가령 덧셈 함수를 만든다고 하면,

def sum(a,b):
    return a+b

로 간단하게 할 수 있다. 여기서 a, b는 정수, 실수 모두 가능하게 된다. 

하지만, a와 b가 리스트list 또는 사전dict 형태의 데이터라면 어떻게 처리해야 할까?

리스트 형식의 데이터라면, 각 i 번째 element끼리 더해서 결과를 반환하도록 하면되고,

사전 형식의 데이터라면, 같은 key 값을 갖는 데이터끼리 더해서 결과를 반환하도록 하면 될 것이다.


이제 원래 이슈로 돌아가서, 입력 데이터가 string, list, dict 중 어느 것이 든지 상관없이 데이터 값을 unicode로 변환하는 프로그램을 만들어 보자.

instance라는 함수를 통해서, 데이터가 string의 instance인지,

아니면, mutable sequence (i.e. list)의 instance인지,

아니면  mutable mapping (i.e. dict)의 instance인지.. 판단할 수 있다.

from collections import MutableMapping
from collections import MutableSequence

def convert_to_unicode(data, encoding='utf-8'):
    if isinstance(data, basestring):
        if not isinstance(data, unicode):
            return unicode(data, encoding)
        else:
            return data.encode(encoding)

    elif isinstance(data, MutableSequence):
        # list-like object                                                                   
        unidata = list()
        for item in data:
            unidataList = convert_to_unicode(item)
            unidata.append(unidataList)
        return unidata

    elif isinstance(data, MutableMapping):
        # dict-like object                                                                   
        unidata = dict()
        for key, value in data.items():
            unidata.update([(key, convert_to_unicode(value))])
        return unidata

    else:
        return data


신고