분류 전체보기 (336)

반응형


PBC 데이터를 통한 생존분석


PBC 데이터 다운받을 수 있는 사이트

http://www4.stat.ncsu.edu/~boos/var.select/pbc.html

http://www4.stat.ncsu.edu/~boos/var.select/pbc.dat.txt


이 데이터셋은 mayo clinic에서 수집된 데이터로 일차성 담즙성 간경화증(primary biliary cirrhosis) 환자들의 생존에 대한 데이터입니다. 


데이터 핸들링

library(survival)

data <- read.table("pbc.dat")

# Column rename
colnames(data) <- c('id', 'futime', 'status', 'drug', 'age', 'sex', 'ascites', 'hepato', 'spiders', 'edema', 'bili', 'chol', 'albumin', 'copper', 'alk_phos', 'sgot', 'trig', 
                   'platelet', 'protime', 'stage')

head(data)


id
futime
status
drug
age
sex
ascites
hepato
spiders
edema
bili
chol
albumin
copper
alk_phos
sgot
trig
platelet
protime
stage
1400212146411111.014.52612.601561718.0137.9517219012.24
24500012061710110.01.13024.14547394.8113.528822110.63
31012212559400000.51.41763.48210516.096.105515112.04
41925211999410110.51.82442.54646121.860.639218310.34
51504121391810110.03.42793.53143671.0113.157213610.93
62503222420110100.00.82483.9850944.093.0063.11.03

생존분석 자료의 기본 자료 구성


1. Survival 데이터에서는 time을 나타내는 변수와 event를 나타내는 변수가 있다. 

2. time은 event 까지의 시간을 나타내며, 

3. event 변수는 우리의 관심 event (예를 들어, 사망) 혹은 censoring을 나타낸다. (이는 주로 0, 1로 나타내어진다.)


PBC 데이터에서는  status = 0=alive, 1=liver transplant, 2=dead 인데,  0,1을 중도 절단된 censoring, 2 를 관심 event로 코딩을 해봅시다.

data$status[(data$status == 1)] = 0
data$status[(data$status == 2)] = 1


drug = 1 : 페니실린

drug = 2 : 플라시보이므로 , 해석상의 이점을 얻기 위해

drug = 1 페니실린, drug = 0은 플라시보로 재코딩해줍니다.


data <- data[data$drug != '.', ]
data$drug <- as.character(data$drug)
data$drug[(data$drug == 2)] = 0
data$drug <- factor(data$drug)


1. KM estimation


우선 Survival function을 추정하는 비모수적인 방법으로 많이 쓰이는 Kaplan-Meier analysis 를 해보겠습니다.


# event, censoring 구분
Y = Surv(data$futime, data$status)

# KM estimation
fit = survfit(Y~data$drug)
summary(fit)


우선 Surv라는 함수를 통해 무엇이 time과 event인지를 알려줍니다. 그리고 drug에 따라 생존을 분석할 것이므로 ~data$drug를 입력하면 아래처럼 lifetable을 만들어줍니다.


Call: survfit(formula = Y ~ data$drug)

                data$drug=0 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
   51    154       1    0.994 0.00647        0.981        1.000
   77    153       1    0.987 0.00912        0.969        1.000
  110    152       1    0.981 0.01114        0.959        1.000
  130    151       1    0.974 0.01282        0.949        0.999
  186    150       1    0.968 0.01428        0.940        0.996
  191    149       1    0.961 0.01559        0.931        0.992
  207    148       1    0.955 0.01679        0.922        0.988
  216    147       1    0.948 0.01788        0.914        0.984
  264    146       2    0.935 0.01986        0.897        0.975
  304    144       1    0.929 0.02075        0.889        0.970
  321    143       1    0.922 0.02160        0.881        0.965
  326    142       1    0.916 0.02240        0.873        0.961
  460    141       1    0.909 0.02317        0.865        0.956
  549    140       1    0.903 0.02389        0.857        0.951
  552    139       1    0.896 0.02459        0.849        0.946
  597    138       1    0.890 0.02525        0.841        0.941
  611    137       1    0.883 0.02589        0.834        0.935
  708    136       1    0.877 0.02650        0.826        0.930
  733    135       1    0.870 0.02709        0.819        0.925
  769    134       1    0.864 0.02765        0.811        0.920
  786    133       1    0.857 0.02820        0.804        0.914
  790    131       1    0.851 0.02873        0.796        0.909
  797    130       1    0.844 0.02925        0.789        0.903
  850    128       1    0.837 0.02975        0.781        0.898
  853    127       1    0.831 0.03024        0.774        0.892
  859    126       1    0.824 0.03071        0.766        0.887
  890    125       1    0.818 0.03116        0.759        0.881
  930    124       1    0.811 0.03160        0.751        0.875
  943    123       1    0.804 0.03203        0.744        0.870
  974    122       1    0.798 0.03244        0.737        0.864
 1080    118       1    0.791 0.03286        0.729        0.858
 1165    115       1    0.784 0.03328        0.722        0.852
 1212    114       1    0.777 0.03370        0.714        0.846
 1217    111       1    0.770 0.03411        0.706        0.840
 1356    103       1    0.763 0.03459        0.698        0.834
 1413    101       1    0.755 0.03506        0.690        0.827
 1427     98       1    0.748 0.03554        0.681        0.821
 1444     95       1    0.740 0.03603        0.672        0.814
 1487     93       1    0.732 0.03651        0.664        0.807
 1536     91       1    0.724 0.03698        0.655        0.800
 1786     79       1    0.715 0.03763        0.645        0.792
 1847     76       1    0.705 0.03829        0.634        0.784
 2090     69       1    0.695 0.03908        0.622        0.776
 2419     56       1    0.683 0.04030        0.608        0.766
 2466     53       1    0.670 0.04155        0.593        0.756
 2503     51       1    0.657 0.04276        0.578        0.746
 2769     40       1    0.640 0.04473        0.558        0.734
 2796     38       1    0.623 0.04662        0.538        0.722
 2847     35       1    0.605 0.04857        0.517        0.709
 3090     32       1    0.587 0.05060        0.495        0.695
 3170     29       1    0.566 0.05275        0.472        0.680
 3244     28       1    0.546 0.05460        0.449        0.664
 3358     26       1    0.525 0.05640        0.425        0.648
 3395     24       1    0.503 0.05814        0.401        0.631
 3428     22       1    0.480 0.05983        0.376        0.613
 3445     21       1    0.457 0.06119        0.352        0.595
 3762     15       1    0.427 0.06427        0.318        0.573
 3839     13       1    0.394 0.06719        0.282        0.551
 3853     12       1    0.361 0.06916        0.248        0.526

                data$drug=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
   41    158       1    0.994 0.00631        0.981        1.000
   71    157       1    0.987 0.00889        0.970        1.000
  131    156       1    0.981 0.01086        0.960        1.000
  140    155       1    0.975 0.01250        0.950        0.999
  179    154       1    0.968 0.01393        0.941        0.996
  198    153       1    0.962 0.01521        0.933        0.992
  223    152       1    0.956 0.01637        0.924        0.988
  334    151       1    0.949 0.01744        0.916        0.984
  348    150       1    0.943 0.01844        0.908        0.980
  388    149       1    0.937 0.01937        0.900        0.975
  400    148       1    0.930 0.02025        0.892        0.971
  515    147       1    0.924 0.02108        0.884        0.966
  673    145       1    0.918 0.02187        0.876        0.962
  694    144       1    0.911 0.02263        0.868        0.957
  750    141       1    0.905 0.02337        0.860        0.952
  762    140       1    0.898 0.02408        0.852        0.947
  799    139       1    0.892 0.02476        0.845        0.942
  824    138       1    0.885 0.02541        0.837        0.937
  904    134       1    0.879 0.02607        0.829        0.931
  971    132       1    0.872 0.02671        0.821        0.926
  980    131       1    0.866 0.02732        0.814        0.921
  999    130       1    0.859 0.02791        0.806        0.915
 1000    129       1    0.852 0.02848        0.798        0.910
 1012    128       1    0.846 0.02902        0.791        0.904
 1037    127       1    0.839 0.02955        0.783        0.899
 1077    126       1    0.832 0.03005        0.775        0.893
 1083    125       1    0.826 0.03054        0.768        0.888
 1152    124       1    0.819 0.03101        0.760        0.882
 1170    122       1    0.812 0.03148        0.753        0.876
 1191    121       2    0.799 0.03236        0.738        0.865
 1235    117       1    0.792 0.03279        0.730        0.859
 1297    114       1    0.785 0.03323        0.723        0.853
 1350    111       1    0.778 0.03368        0.715        0.847
 1360    110       1    0.771 0.03411        0.707        0.841
 1434    105       1    0.764 0.03456        0.699        0.834
 1492    100       1    0.756 0.03505        0.690        0.828
 1576     97       1    0.748 0.03554        0.682        0.821
 1657     93       1    0.740 0.03606        0.673        0.814
 1682     92       1    0.732 0.03655        0.664        0.807
 1690     91       2    0.716 0.03748        0.646        0.793
 1741     87       1    0.708 0.03794        0.637        0.786
 1827     82       1    0.699 0.03845        0.628        0.779
 1925     78       1    0.690 0.03899        0.618        0.771
 2055     72       1    0.681 0.03960        0.607        0.763
 2081     71       1    0.671 0.04019        0.597        0.755
 2105     70       1    0.661 0.04074        0.586        0.746
 2224     65       1    0.651 0.04137        0.575        0.738
 2256     63       1    0.641 0.04198        0.564        0.729
 2288     61       1    0.630 0.04259        0.552        0.720
 2297     60       1    0.620 0.04315        0.541        0.710
 2386     54       1    0.608 0.04385        0.528        0.701
 2400     53       1    0.597 0.04450        0.516        0.691
 2540     47       1    0.584 0.04533        0.502        0.680
 2583     42       1    0.570 0.04634        0.486        0.669
 2598     41       1    0.556 0.04725        0.471        0.657
 2689     38       1    0.542 0.04822        0.455        0.645
 3086     28       1    0.522 0.05023        0.433        0.631
 3222     24       1    0.501 0.05264        0.407        0.615
 3282     22       1    0.478 0.05495        0.381        0.599
 3574     18       1    0.451 0.05795        0.351        0.580
 3584     17       1    0.425 0.06032        0.322        0.561
 4079      8       1    0.372 0.07247        0.254        0.545
 4191      7       1    0.319 0.07922        0.196        0.519


par(mai=c(1,1,1,1))
plot(fit,main="KM Curve", xlab="Time(Week)", ylab=expression(paste(hat(S),"(t)")))

# Log rank test (difference between groups)
log_rank = survdiff(Surv(data$futime, data$status) ~ data$drug, data)
log_rank

결과를 보시면 플라시보와 페니실린 처방군간에 생존률에 큰 차이가 없는 것을 확인할 수 있습니다.


두 군간에 차이가 있는지 검정하는 방법인 log_rank 테스트에서도 p value > 0.05로 두 군간에 차이가 유의하지 않습니다.


Call:
survdiff(formula = Surv(data$futime, data$status) ~ data$drug, 
    data = data)

              N Observed Expected (O-E)^2/E (O-E)^2/V
data$drug=0 154       60     61.8    0.0513     0.102
data$drug=1 158       65     63.2    0.0502     0.102
 

Chisq= 0.1 on 1 degrees of freedom, p= 0.7



2. Cox regression


생존분석을 다변수로 할 때, Cox regression을 주로 활용합니다. 이는 Cox proportional hazard model로 불리기도 합니다.


Cox regression은 다음과 같은 이유로 많이 쓰입니다.


1. 다양한 변수들의 계수와 hazard ratio를 추정하는데 좋다. -> 이를 통해 변수별 생존에 대한 중요도를 비교하기 쉽다.

2. Cox regression은 robust 하다. (참에 매우 근접한 값을 추정해준다.)

3. 계산된 hazard가 양수이기 때문에 타당한 값이다.

4. baseline hazard를 몰라도 회귀계수, hazard ratio를 추정할 수 있다.


Cox regression의 이론적 배경에 대해서는 다음에 기회가 있을 때 다루어보도록 하겠습니다. 


R에서 Cox regression을 수행하는 것은 매우 간단한데, 앞서 정의한 event, time 변수인 Y를 종속변수로 놓고 분석대상인 변수들을 ~ +로 연결하면 됩니다.  

# Cox regression
cox = coxph(Y~data$drug + data$age + data$sex + data$stage + data$edema + data$bili + data$albumin)
summary(cox) 
Call:
coxph(formula = Y ~ data$drug + data$age + data$sex + data$stage + 
    data$edema + data$bili + data$albumin)

  n= 312, number of events= 125 

                   coef  exp(coef)   se(coef)      z Pr(>|z|)    
data$drug1    2.569e-02  1.026e+00  1.855e-01  0.138 0.889882    
data$age      6.736e-05  1.000e+00  2.651e-05  2.541 0.011057 *  
data$sex     -5.940e-01  5.521e-01  2.550e-01 -2.330 0.019832 *  
data$stage1  -2.248e+00  1.056e-01  1.023e+00 -2.197 0.027992 *  
data$stage2  -8.573e-01  4.243e-01  2.950e-01 -2.906 0.003659 ** 
data$stage3  -4.884e-01  6.136e-01  2.186e-01 -2.234 0.025487 *  
data$stage4          NA         NA  0.000e+00     NA       NA    
data$edema    9.740e-01  2.649e+00  3.148e-01  3.095 0.001971 ** 
data$bili     1.263e-01  1.135e+00  1.529e-02  8.263  < 2e-16 ***
data$albumin -9.288e-01  3.950e-01  2.556e-01 -3.634 0.000279 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

             exp(coef) exp(-coef) lower .95 upper .95
data$drug1      1.0260     0.9746   0.71322    1.4760
data$age        1.0001     0.9999   1.00002    1.0001
data$sex        0.5521     1.8112   0.33497    0.9101
data$stage1     0.1056     9.4656   0.01423    0.7844
data$stage2     0.4243     2.3568   0.23801    0.7564
data$stage3     0.6136     1.6296   0.39979    0.9419
data$stage4         NA         NA        NA        NA
data$edema      2.6486     0.3776   1.42921    4.9083
data$bili       1.1347     0.8813   1.10117    1.1692
data$albumin    0.3950     2.5315   0.23936    0.6519

Concordance= 0.839  (se = 0.029 )
Rsquare= 0.427   (max possible= 0.983 )
Likelihood ratio test= 174  on 9 df,   p=<2e-16
Wald test            = 186.2  on 9 df,   p=<2e-16
Score (logrank) test = 287  on 9 df,   p=<2e-16


그러면 이렇게 회귀계수와 회귀 계수의 exponential을 돌려주게 됩니다. Cox regression이 좋은 점은 회귀계수에 exponential을 취했을 때, 해당 변수가 1단위 증가했을 때의 hazard ratio가 됩니다. 예를 들어, age의 경우, 다른 변수들을 보정하고, 1살 증가했을 때, hazard가 1.0001배 증가한다. 라고 볼 수 있습니다. sex의 경우, 다른 모든 변수를 보정했을 때, 남자에 비해 여자가 hazard가 0.55 배라고 볼 수 있습니다 (이 데이터에서 0=male, 1=female로 코딩이 되어있기 때문에). p-value를 보면 어떠한 변수가 생존에 영향을 크게 끼치는 지를 비교해볼 수 있습니다.  



반응형

'Tools > R' 카테고리의 다른 글

R igraph 설치 오류 해결  (0) 2018.12.28
R Default library path 바꾸기  (2) 2018.12.28
Jupyter notebook에서 R을 이용하기 (IRkernel)  (6) 2018.10.05
R 패키지 설치시 gfortran 컴파일 오류  (0) 2018.07.06
R 유명한 패키지 정리  (0) 2018.03.19
반응형

Jupyter notebook 에서 R을 이용하기


데이터 분석을 할 때, PythonR을 동시에 이용하시는 분들이 많습니다.

저 같은 경우도 머신러닝, 딥러닝 등을 할 때는 Python을, 데이터 처리, 가공, 통계분석을 할 때는 R을 선호하는데요. 이 경우 Jupyter notebook 등의 Python 개발 환경과 R studio 를 번갈아가면서 이용해야해서 불편한 점이 많았습니다. 


본 포스팅에서는 Jupyter notebook이라는 하나의 개발 환경에서 R과 Python을 같이 이용할 수 있게 해주는 IRkernel을 설치하는 것을 포스팅해보았습니다.


IRkernel을 이용하면 Jupyter notebook에서도 현재 컴퓨터에 설치된 R 커널을 이용할 수 있게 해줍니다.

IRkernel은 R 커널을 Jupyter notebook에서 이용할 수 있게 해주는 패키지입니다. 

https://github.com/IRkernel/IRkernel


우선 당연히 선행적으로 Jupyter가 설치되어있어야하며,


주의할 점은 conda 가상환경 쓰시는 분들은

이걸 jupyter notebook이 설치된 conda 가상환경을 키고 IRkernel 설치를 진행하여야합니다.


먼저 devtools를 설치합니다.

install.packages('devtools')


다음 devtools를 이용해 IRkernel을 설치합니다.


devtools::install_github('IRkernel/IRkernel')

# or devtools::install_local('IRkernel-master.tar.gz')

IRkernel::installspec()  # to register the kernel in the current R installation



이렇게 R kernel이 생기게 됩니다.



저는 R version 3.5.1을 이용중이었는데 동일한 버전을 Jupyter notebook에서도 이용할 수 있습니다.


---- 추가 (2020-09-28)

conda install r-irkernel

위 conda 커맨드로 anaconda 가상환경 밑에 R 과 IRKernel 을 동시에 설치할 수도 있습니다. 


특정 R 버전에 설치하기 위해서는 아래 참고 (2020-10-16 추가)

http://salvatoregiorgi.com/blog/2018/10/16/installing-an-older-version-of-r-in-a-conda-environment/

반응형
반응형


주피터 nbextension 설치


우선 가상환경을 쓰시는 분들은 가상환경을 activate하시기 바랍니다.


source activate [가상환경이름]


pip install jupyter_nbextensions_configurator jupyter_contrib_nbextensions

jupyter contrib nbextension install --user

jupyter nbextensions_configurator enable --user


위 커맨드를 입력하시면 nbextension이 설치됩니다. 원래는 Clusters 옆에 nbextension 탭이 생기게 됩니다.



저의 경우에는 왜 인지는 모르겠지만 자동으로 nbextension 탭이 안 생겼는데

[아이피]:[포트]/nbextensions 로 들어가니까 아래처럼 nbextension 메뉴를 볼 수 있었습니다. 


메뉴에서 사용 가능한 extension 들이 나와있고, 클릭을 통해 enable/disable을 할 수 있습니다.

처음 사용하실 때는 각각의 모듈들을 설치하셔야 합니다.


주피터 테마 설치


주피터 테마

https://github.com/dunovank/jupyter-themes


마찬가지로 가상환경 activate 후에


pip install jupyterthemes


커맨드 옵션은 아래와 같습니다.


jt  [-h] [-l] [-t THEME] [-f MONOFONT] [-fs MONOSIZE] [-nf NBFONT]

    [-nfs NBFONTSIZE] [-tf TCFONT] [-tfs TCFONTSIZE] [-dfs DFFONTSIZE]

    [-m MARGINS] [-cursw CURSORWIDTH] [-cursc CURSORCOLOR] [-vim]

    [-cellw CELLWIDTH] [-lineh LINEHEIGHT] [-altp] [-altmd] [-altout]

    [-P] [-T] [-N] [-r] [-dfonts]


jt -l 로 적용가능한 테마들을 볼 수 있습니다.


저의 경우에는 onedork 테마가 마음에 들어서


jt -t onedork -fs 95 -tfs 11 -nfs 115 -cellw 70% -T

이러한 옵션으로 사용중인데, 폰트 사이즈도 적절하고 화면이 주피터 노트북 default보다 조금 넓은 정도여서 편리하게 사용하고 있습니다.


각각의 옵션이 무엇을 뜻하는지에 대한 설명은

https://github.com/dunovank/jupyter-themes 을 참조하시면 됩니다.


또 테마를 설치한 후, output화면에서 왼쪽이 약간 잘려 나오는 문제가 있었는데

~/.jupyter/custom/custom.css 에서

div.output_area {
display: -webkit-box;
padding-left: 20px;
}

를 추가하여 해결하였습니다. 위 파일을 수정하면 jupyter notebook의 css 설정을 직접 바꾸어 자신만의 테마를 만들어 볼 수도 있습니다.


반응형
반응형

 

데이터과학이란 무엇인가?

 

데이터 과학이란 무엇인가? 사실 모든 학문, 산업 분야에서 "데이터" 는 필수적이다. 그런데 왜 "데이터" 과학이라는 이름을 따로 붙이는 걸까? 거기에 Science라니. 보통 Science라는 것은 새로운 지식을 찾는 활동, 즉, New finding에 대한 것을 Science라 한다. 하지만 데이터 과학에서 주로하는 것은 데이터를 처리하고 클리닝 하여 저장하고는 것, 즉 무언가를 개선 시키는 활동인 Engineering에 그치는 것 아닌가? 

 

데이터 과학자는 통계학자보다 컴퓨터를 잘하고, 컴퓨터과학자보다 통계학을 잘하는 사람이라는 우스갯 소리가 있다. 물론 어느 정도 맞는 부분이 있지만 데이터 과학은 단지 어떤 학문 분야들의 중간에 있는 것이 아니라 기존 학문들에서 다루지 않는 부분을 다루기도 한다. 데이터 과학의 정의, 기존 학문과의 차별점에 대해 짚어보자. 

 

최근 떠오르는 학문 분야들에 대한 농담

 

Data science의 정의

 

The term “data science” describes expertise associated with taking (usually large) data sets and annotating, cleaning, organizing, storing, and analyzing them for the purposes of extracting knowledge. It merges the disciplines of statistics, computer science, and computational engineering.

 

데이터과학이란 보통 큰 데이터셋에 대해 어노테이션, 클리닝, 핸들링, 저장, 분석을 하여 그로부터 유용한 지식을 추출하는 것을 말한다. 이는 Informatics와 비슷하다. Informatics 란 정보학으로 모든 데이터를 처리 분석하여 유용한 정보를 얻는 것이다.

 

Informatics와 Data science의 차이점은 무엇인가?

 

간단하게 말해 Data science는 "빅데이터시대"에 정의된 학문 분야로서 기존에 보기 힘든 정도의 큰 데이터를 다룬다는 특징이 있다. 데이터 과학자는 컴퓨터 메모리에 올라가지 않는 규모의 큰 데이터를 다루며 이를 위한 기술적인 지식이 필요하다. 이전에는 Informatics를 위해서 컴퓨터 프로그래머를 고용하여 해결하였다고 한다. 하지만 데이터 과학은 단순히 "프로그래밍" 으로 해결할 수 없는 많은 부분을 포함하고 있다. Informatics와 Data science의 여집합은 바로 이 부분에서 나온다. 또한 Data science는 단순 프로그래밍이 아니라 해당 분야의 지식에 대한 깊은 이해를 기본 가정으로 한다. 즉, 이를 다시 한 번 정리해보자.

 

Informatics와 Data science의 차이점

 

 

1. 데이터과학자는 컴퓨터 메모리에 올라가지 않는 수준의 빅데이터를 다룬다.

2. 데이터과학자는 메타데이터 및 large-scale annotation이 필요하며, 데이터의 noise가 어디에서 발생되었는지에 대해 설명할 수 있어야 한다. 이는 도메인에 대한 이해를 필요로 하며 단지 데이터를 정리하고 가공하는 것과는 다르다.

3. 이러한 빅데이터를 분석할 수 있는 방법론인 머신러닝, 딥러닝 등을 이해하고 이를 해당 분야의 데이터에 적용시켜 유용한 가치를 찾는다.

 

 
최근 많은 학교 교육 및 직업 교육에서 domain-free 데이터과학을 가르친다. 금융, 헬스, 생물 어떤 분야에도 통용할 수 있는 데이터 처리 기술이다. 물론 그것은 데이터 과학을 시작할 수 있는 "기초 단계"로서 유용하다. 하지만 단지 domain-free 데이터 과학만을 배우면 단지 데이터를 가공하고 매니지하는 사람에 그쳐버릴 수도 있다. (협업자의 엄청난 도움이 없다면) 하지만 domain에 대한 specific knowledge가 있으면 그 분야에 전문가이면서 데이터를 직접 처리하고 가공, 분석 할 수 있는 사람이 될 수 있다.  

 

데이터과학자에게 도메인 지식이 필수적인 이유는 다음과 같이 정리해볼 수 있다. 

 

1. 데이터에 무언가 문제가 생겼을 때,이를 해결하기 위해 필요하다.
2. 데이터의 annotation을 하기 위해서는 도메인 지식이 필요하다.
3. 문제를 찾고 이를 해결하기 위해서는 도메인 지식이 필수적이다.
 
 

 

빅데이터 시대의 대표적인 분석 방법론, 머신러닝

 
 
좋은 데이터 과학자란, 기존 Informatics 방법론으로는 다루기 힘든 수준의 복잡한 빅데이터를 다루며, 충분한 도메인 지식을 바탕으로 해당 분야의 데이터를 스스로의 계획을 통해 처리, 가공을 하며, 메타 데이터 annotation을 직접하며, 해당 분야의 문제를 찾고 이를 해결할 수 있는 사람이다.  어떤 도메인을 깊게 공부하고 그 데이터에 대해 즉각적으로 이해하고 데이터를 어떻게 처리하고 굴려서 분석할지를 정하는 데에 좋은 결정력을 갖고 있는 사람이다. 어떤 한 분야의 domain 지식을 가질 때 그 분야의 문제를 찾고, 직접 데이터를 처리하고 적절한 분석 방법을 통해 분석하여 해결할 수 있는 사람이 된다. 
Biomedical Data science 를 예로 들어보자.

 

Biomedical science 분야는 Bio와 medical이 합쳐진 분야이다. 즉, 생물학과 의학이 합쳐진 분야로 생물학, 의학 분야의 "과학적 발견"을 주로 population health에 응용하는 응용학문이다. 이러한 Biomedical 분야는 데이터를 통해서 무언가를 할 수 있다. 따라서 Biomedical 분야를 연구하려면 기본적으로 데이터를 가공하고, 클리닝하고, 분석할 수 있어야한다. 그러면 Biomedical data science라는 용어는 왜 존재하는가? 

 

Biomedical 분야의 데이터를 다음 세 가지로 크게 나눌 수 있다.

 

1. DNA 시퀀싱 데이터 (NGS 데이터)

2. 센서 데이터 (심박수, electrocardiogram signal 등)

3. Electronic health record (개인의 건강 임상 정보)

 

이러한 종류의 데이터는 소위 말하는 4v(Volume, Variety, Velocity, Value)를 만족하는 "빅데이터" 이다. 이러한 정보를 가공하고 분석하기 위해서는 특별한 skill set이 필요하다. NGS 데이터를 예로 들어보자. NGS는 새로운 인간 DNA의 시퀀싱 방법으로 massive parallele sequencing이라고 하는 특별한 시퀀싱 방법을 통해 인간 DNA 서열을 "추측"한다. 이 기술의 상당한 발전이 이루어져 정확도는 상당히 높지만, 중요한 것은 뚝딱하고 ATCG로 이루어진 DNA의 서열이 나오지 않는다는 것이다. 또 DNA 서열은 30억개 정도가 되기 때문에 한 글자당 4비트라고 놓고 계산을 하더라도 1GB 이상의 크기이며, 실제 NGS 분석에서 나오는 Raw 데이터는 1인당 200GB에 이른다. (참고)  따라서 이러한 특별한 종류의 NGS 데이터를 통해 인간 DNA 서열을 조립하고, 이곳에서 변이(variant)를 탐색하고 질병과의 연관성을 분석하는 것은 상당한 도메인 지식을 필요로 한다. Biomedical data science란 이러한 종류의 데이터를 직접 가공, 클리닝하여 이를 분석하고 유용한 지식을 탐색하는 활동이라고 할 수 있다. 

 

Reference

[1] What is Biomedical Data Science and Do We Need an Annual Review of It ? - Annual review of biomedical data science, 2018

반응형
반응형

벅슨의 역설 (Berkson's Paradox)


벅슨의 역설은 병원 기반 데이터로 case-control 연구를 할 때 발생하는 현상으로 1946년 Joseph Berkson이 보고한 역설입니다. 


벅슨의 역설이 생기는 이유


A와 B 둘다 있는 사람이나, A와 B 둘다 없는 사람이 연구 대상에서 제외되었을 때, A-B 간의 가짜 관계가 생깁니다. 벅슨의 역설을 병원 기반 데이터로 보여줄 때는 주로, A, B 둘다 없는 사람이 연구 대상에서 제외되었기 때문에 발생합니다. 



간단한 예


이 예를 통해 전혀 상관 없어보이는 두 가지 질병, 인플루엔자와 맹장염의 가짜 연관성(spurious association)이 어떻게 생기는지를 보입니다. (이미지 출처)


우선, 병원에 입원한 환자가 100명이라고 했을 때 다음과 같이 가정합니다.


1. 전체 인구집단에서 인플루엔자의 유병률은 10% 이다.

2. 병원에 온 사람 중 인플루엔자로 입원한 사람은 30%이다.

3. 병원에 온 사람 중 맹장염으로 입원한 사람은 10%이다. 

4. 인플루엔자와 맹장염은 독립적이다. 즉, 맹장염으로 입원한 사람중 10%가 인플루엔자를 가졌다고 가정. (맹장염의 유병률이 매우 낮다고 가정) 




(파란색=인플루엔자, 빨간색=맹장염, 검은색=기타, 빨간색+파란색=인플루엔자, 맹장염을 동시에 가진 사람)


이 상황에서 인플루엔자 따른 맹장염의 발생 양상을 파악하기 위해, 인플루엔자를 가진사람과 안 가진 사람으로 나뉘어 맹장염에 걸린 사람을 나눠봅니다. 총 30명의 인플루엔자를 가진 사람 중  1명이 맹장염에 걸렸습니다. 총 70명의 인플루엔자를 안 가진 사람중 9명이 맹장염에 걸렸습니다. 



위 노란박스는 70명의 인플루엔자를 안 가진 사람 중 9명이 맹장염에 걸린 상황을 나타냅니다.


이 때, 인플루엔자를 기준으로 한 맹장염의 상대위험도는 (1/30)/(9/70) = 0.004 로 인플루엔자가 맹장염에 보호적인 효과가 있는 것으로 나옵니다. 이 때, 이런 가짜 연관성이 생긴 이유는 병원 데이터의 특성 때문입니다. 즉, 인플루엔자와 맹장염이 둘 다 없는 사람이 일반 인구집단과 비교하여 더 적기 때문에, 인플루엔자가 없는 사람 중 맹장염에 걸린 사람이 9/70 = 12% 로 과추정되었습니다. 


참고

http://www.statisticshowto.com/berksons-paradox-definition/

반응형
반응형


로지스틱 회귀분석


로지스틱 회귀분석은 반응변수가 1 또는 0인 이진형 변수에서 쓰이는 회귀분석 방법입니다. 종속변수에 로짓변환을 실시하기 때문에 로지스틱 회귀분석이라고 불립니다. 로지스틱 회귀분석의 좋은점은 우선 계수가 Log Odds ratio가 되기 때문에 해석이 매우 편리하고, case-control과 같이 반응 변수에 따라 샘플링된 데이터에 대해서 편의(bias)가 없는 타당한 계수 추정치를 계산할 수 있다는 것입니다. 이 부분에 초점을 맞추어 로지스틱 회귀분석에 대해 간단히 정리해보려고합니다. 



1. 로지스틱 회귀분석의 원리


반응변수(y)가 1/0인 상황에서 마치 선형 회귀분석처럼 아래의 식에서 계수를 추정한다고 해봅시다. 


$$ y = \beta_0 + \beta X $$


로지스틱 회귀분석에서는 보통 우리가 예측하고자 하는 y의 "예측값"이 P[Y=1] 이라는 믿음을 갖는데, 그러면, y의 예측값은 0-1사이로 고정이 되어야합니다. 하지만 위 식의 경우 특정 X 값에서는 y의 예측값이 0-1 사이로 고정되는 것이 아니라 0보다 작아질 수도 있고, 1보다 커질 수도 있습니다. 


즉, 좌변의 범위는 0-1이며 우변의 범위는 마이너스 무한대에서 플러스 무한대의 값을 갖게됩니다. 이를 해결하기 위해 로지스틱 회귀분석에서는 반응 변수 대한 로짓 변환을 실시합니다. 로짓변환은 y를 log(y/1-y)로 만드는 함수적 변환을 말합니다.



우변을 0-1 사이로 변환하기


$$ P(y=1) = \frac {1} {(1+e^{-(\beta_0 + \beta X)})} $$



이 함수를 시그모이드 함수라고 부릅니다. y의 값이 0-1 사이로 고정됩니다. 이것이 왜 로짓변환이냐고 할 수 있지만 아래의 식을 보면 이해할 수 있습니다.



좌변을 마이너스 무한대에서 플러스 무한대로 변환하기


$$ \log(\frac{P(y=1)}{1-P(y=1)}) = \log(\frac{P(y=1)}{P(y=0)}) = \beta_0 + \beta X $$



이것이 y에 로짓변환을 한 식입니다. 위 두식은 모양만 다르지 결국 풀어서 보면 같은 식입니다. 보통 머신러닝 쪽에서는 위의 식을, 통계학에서는 아래식을 더 좋아하는 것 같아 보입니다. 위의 식이 더 이해하기 쉽지만, 아래 식은 해석이 좋은 특징이 있습니다.


왜냐하면 좌변이 X가 주어진 상황에서 로그 오즈(log odds)가 되기 때문입니다.  즉, 로지스틱 회귀분석은의 계수 추정은 독립변수 X에 대한 선형 회귀식을 X가 주어졌을 때의 반응 변수 Y의 로그 오즈에 적합시킨다." 라고 할 수 있습니다. 



2. 계수의 해석


로지스틱 회귀분석에서 계수에 exponential을 취하면, 해당 변수가 한 단위 증가했을 때, OR 이 됩니다.


$$ \log(\frac{P(y=1| x_1)}{P(y=0 | x_1)}) = \beta_0 + \beta_1 x_1 $$

$$ \log(\frac{P(y=1| x_1 + 1)}{P(y=0 | x_1 + 1)}) = \beta_0 + \beta_1 (x_1 +1) $$


이 때, 아래 식에서 위 식을 빼면, $$ \beta_1 $$ 만 남고, $$ \beta_1 = \log(\frac{P(y=1| x_1 + 1)}{P(y=0 | x_1 + 1)}) -\log(\frac{P(y=1| x_1)}{P(y=0 | x_1)}) $$ 가 됩니다. 


$$ \exp(\beta_1) = \frac{\frac{P(y=1| x_1 + 1)}{P(y=0 | x_1 + 1)}}{\frac{P(y=1| x_1)}{P(y=0 | x_1)}} $$

양변에 exponential을 취해주고, 로그함수의 성질에 의해 exponential된 계수는 X가 X+1이 됐을 때, 오즈의 비율 즉, 오즈 Ratio가 됩니다 (OR). 



3. Case-Control 연구에서 로지스틱 회귀분석의 계수 추정은 편의가 없다.


case-control 연구는 인구집단에서 case와 control을 샘플링해서 이를 대상으로 질병의 원인이 되거나 연관성이 있는 요인을 원인을 찾는 연구입니다. 예를 들어 전체 인구집단 중에 유병률이 0.001 밖에 되지 않는 질병이 있다면, 전체 인구 집단을 대상으로 연구를 수행하면 질병에 걸린 사람(case)를 연구에 포함하기가 매우힘들어지겠죠. 따라서 case-control study에서는 질병이 있는 사람들을 더 많이 샘플링을 해서 case와 control의 비율을 최대 1:1 까지 맞춥니다. 그렇다면 이 연구용 집단은 전체 모집단과는 특성이 다르게 됩니다. 따라서 많은 수치가 잘못된 계산값을 내놓게 됩니다. 예를 들어 상대위험도(Relative Risk)의 경우 참값과 다른 값이 나오게 됩니다.


이상적으로 case-control 연구는 case, control 여부에 따라서만 샘플링이 결정되어야 합니다. 로지스틱 회귀분석이 좋은 한 가지 이유는 이 가정이 맞은 경우, 편의가 없는 계수 추정치를 추정하게 됩니다. 편의가 없다는 말은 연구 집단에서 구한 계수의 기댓값이 전체 인구집단에서 구할 수 있는 계수의 "참값" 이라는 것입니다. 


왜 이렇게 되는 것인지 살펴보겠습니다. 샘플링된 데이터에서 X가 주어졌을 때, Y의 오즈는 아래와 같이 나타낼 수 있습니다. P의 아래첨자는 각각 population, sample을 나타냅니다. 이 때, 파이(y=1|x)는 case 샘플에 포함될 확률입니다. 파이(y=0|x)도 마찬가지입니다. 


$$ \frac{P_s(y=1| x)}{P_s(y=0 | x)} = \frac{\pi(y=1|x)}{\pi(y=0|x)} \frac{P_p(y=1| x)}{P_p(y=0| x)} $$


근데 샘플링이 잘 되었다면 이론적으로 y=1인 샘플에 포함될 확률은 x와 독립적입니다. 따라서 파이(y=1|x)와 파이(y=0|x)는 상수이기 때문에 아래와 같이 쓸 수 있습니다. 

$$ \frac{P_s(y=1| x)}{P_s(y=0 | x)} = K \frac{P_p(y=1| x)}{P_p(y=0| x)} $$


$$ K \frac{P_p(y=1| x)}{P_p(y=0| x)} = K \exp(\beta_0 + \beta_1 x) = \exp(\beta_0' + \beta_1 x)$$


따라서, 샘플링 결과에 따라 계수의 추정량에는 영향이 없고 오직 절편만 바뀐다는 것을 알 수 있습니다.

반응형
반응형

가비아 도메인과 구글앱엔진 연동


구글앱엔진으로 구축한 웹 어플리케이션은 따로 설정하지 않으면 [프로젝트명].appspot.com으로 웹에서 접근할 수 있게 됩니다. 하지만 맞춤 도메인을 통해 개인이 소유한 도메인을 연결시킬 수 있습니다. 예를 들어, 가비아에서 도메인을 구입한 뒤 구글앱엔진으로 구축한 웹 애플리케이션에 연결시킬 수 있습니다. 가장 먼저 할 일은 물론 가비아에서 도메인을 구입하여야 하는 것입니다. 가비아에서 도메인을 구입하였고, 구글앱엔진으로 구축하여 appspot으로 돌아가는 웹 애플리케이션이 있다는 가정하에 아래 과정을 진행하면 됩니다.


구글앱엔진 설정


왼쪽 대시보드 설정 - 맞춤 도메인 - 새 맞춤 도메인 추가



그러면 이렇게 해당 도메인의 DNS 구성에 TXT 기록을 추가하라고 나옵니다. 이 화면에서 멈춰놓고 가비아 홈페이지에 접속하여 이 기록을 추가하여야합니다.



가비아 설정


가비아 홈페이지 - DNS 설정 - 레코드 추가



여기서 호스트에는 @를 하고 값/위치에 위에 구글에서 알려준 TXT 기록을 입력한 후 저장을 누릅니다. (호스트에 반드시 @를 쓰셔야합니다. 다른 걸 쓰면 안됩니다..)

다음에 구글앱엔진으로 돌아와 확인을 누르면 도메인에 대한 소유권이 확인됩니다. 여기까지 되었으면 해당 도메인이 본인 거라는 것을 구글이 확인한 것입니다. 이제 그 도메인으로 접속할 수 있으려면 A레코드를 추가해야하는데 위 과정을 진행하면 앱엔진 대시보드 상에 다음과 화면이 나오게 됩니다. 여기에서 "데이터" 란에 표시된 IP 주소를 가비아에 입력해주어야합니다.



아까의 가비아 DNS 설정 화면으로 돌아와서 레코드 추가에서 타입을 A, 호스트는 @그리고 값에는 위의 IP 주소를 넣으면 설정이 완료됩니다. 그러면 해당 도메인으로 구글 앱 엔진에 접속할 수 있게 됩니다.




하위 도메인 설정 방법 


구글 앱엔진에서 하위 도메인(www를 예로 들음)을 추가한 후에, 가비아에서 1. 레코드 추가-타입 CNAME  2. 호스트 - www, 3. 값 - 구글앱엔진 대시보드 상의 "데이터" (저의 경우에는 ghs.googlehosted.com 을 입력하였습니다.) 를 입력한 후 저장하면 www.domain.com 으로도 구글 웹앤진을 접속할 수 있습니다.



반응형
반응형

Python으로 하는 탐색적 자료 분석 (Exploratory Data Analysis)


Python을 통해 탐색적 자료분석을 할 때, 무엇을 해야하고, 순서는 어떻게 해야하는지 막막한 경우가 많은데요. 탐색적 자료분석의 기본은 바로 변수 별로 분포를 그려보는 것이겠죠. 수치형 데이터의 경우는 히스토그램을, 명목형 데이터의 경우는 빈도표를 통해 데이터의 분포를 살펴보게 됩니다. 본 포스팅에서는 파이썬을 통해 탐색적 자료 분석을 하는 방법을 유명한 데이터셋인 타이타닉 데이터를 통하여 차근차근 알아보겠습니다. 


titanic.csv



기본적인 탐색적 자료 분석의 순서는 아래와 같이 정리해보았습니다. 


1. 데이터를 임포트하여 메모리에 올린다.

2. 데이터의 모양을 확인 한다.

3. 데이터의 타입을 확인한다.

4. 데이터의 Null 값을 체크한다. 

5. 종속변수의 분포를 살펴본다.

6. 독립변수 - 명목형 변수의 분포를 살펴본다. 

7. 독립변수 - 수치형 변수의 분포를 살펴본다. 

8. 수치형, 명목형 변수간의 관계를 파악한다. 


1. 데이터를 임포트한다.


아래와 같이 패키지와 데이터를 임포트합니다. numpy, pandas, matplotlib, seaborn은 이 4가지의 패키지는 파이썬을 통한 EDA에서 거의 필수적으로 사용하는 라이브러리입니다.


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
 
titanic = pd.read_csv("titanic.csv")


2. 데이터의 모양을 확인한다. 


titanic.head()

PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarked
0103Braund, Mr. Owen Harrismale22.010A/5 211717.2500NaNS
1211Cumings, Mrs. John Bradley (Florence Briggs Th...female38.010PC 1759971.2833C85C
2313Heikkinen, Miss. Lainafemale26.000STON/O2. 31012827.9250NaNS
3411Futrelle, Mrs. Jacques Heath (Lily May Peel)female35.01011380353.1000C123S
4503Allen, Mr. William Henrymale35.0003734508.0500NaNS



3. 데이터의 타입을 체크한다.


titanic.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
PassengerId    891 non-null int64
Survived       891 non-null int64
Pclass         891 non-null int64
Name           891 non-null object
Sex            891 non-null object
Age            891 non-null float64
SibSp          891 non-null int64
Parch          891 non-null int64
Ticket         891 non-null object
Fare           891 non-null float64
Cabin          204 non-null object
Embarked       889 non-null object
dtypes: float64(2), int64(5), object(5)
memory usage: 83.6+ KB


데이터의 타입을 체크하는 이유는 해당 변수의 타입을 제대로 맞추어주기 위해서입니다. 범주형 변수의 경우 object 또는 string, 수치형 변수의 경우 int64 혹은 float 64로 맞추어주면 됩니다. 범주형 변수의 경우 값이 문자열로 들어가 있으면 알아서 object 타입이 되지만, 만약의 숫자로된 범주형 변수의 경우 int64 등으로 잘못 타입이 들어가 있는 경우가 있습니다.  


위 데이터의 경우 Survived와 PClass 변수가 범주형 int64로 잘못 되어있으므로 형변환을 합니다.


titanic['Survived'] = titanic['Survived'].astype(object)
titanic['Pclass'] = titanic['Pclass'].astype(object)


4. 데이터의 Null 값을 체크한다. 


Null Check도 매우 중요한 작업 중 하나입니다. 단순히 Tutorial이나 학습을 위해 제작된 데이터셋이아닌 현실의 데이터셋의 경우, 많은 부분이 Null 인 경우가 많습니다. 따라서 이 Null 값을 어떻게 처리하느냐가 매우 중요합니다. 


titanic.isnull().sum()

PassengerId      0
Survived         0
Pclass           0
Name             0
Sex              0
Age              0
SibSp            0
Parch            0
Ticket           0
Fare             0
Cabin          687
Embarked         2
dtype: int64



Cabin 변수가  687 행이 missing이고 Embarked가 2개의 행이 missing인 것을 확인하였습니다.


Null 값이 있는 경우, 크게 그 값을 빼고 하는지, 혹은 결측치를 대치하는지 2개의 방법으로 나눌 수 있습니다. 각각의 방법에 대한 이름이 다르긴한데 보통 첫 번째 방법을 complete data analysis, 두 번째 방법을 Imputation이라고 이름 붙입니다. 


missing_df = titanic.isnull().sum().reset_index()
missing_df.columns = ['column', 'count']
missing_df['ratio'] = missing_df['count'] / titanic.shape[0]
missing_df.loc[missing_df['ratio'] != 0]

columncountratio
10Cabin6870.771044
11Embarked20.002245


위 명령어를 통해 전체의 몇 %가 missing 인지를 확인할 수 있습니다. 




5. 종속변수 체크


titanic['Survived'].value_counts().plot(kind='bar') plt.show()


기본적으로 종속변수의 분포를 살펴봅니다. 종속변수란 다른 변수들의 관계를 주로 추론하고, 최종적으로는 예측하고자 하는 변수입니다. 



6. 명목형 변수의 분포 살펴보기

 


단변수 탐색


category_feature = [ col for col in titanic.columns if titanic[col].dtypes == "object"]
category_feature
['Survived', 'Pclass', 'Name', 'Sex', 'Ticket', 'Cabin', 'Embarked']

앞에서 명목형 변수의 형을 object로 모두 변경했기 때문에 이처럼 컬럼 중에서 object 타입을 가진 컬럼만 뽑아서 명목형 변수의 리스트를 만듭니다. 이 때, 데이터의 기본키(인덱스), 종속변수 등을 제외하고 분석하는 것이 좋습니다. 



category_feature = list(set(category_feature) - set(['PassengerId','Survived']))
category_feature
  ['Cabin', 'Embarked', 'Ticket', 'Sex', 'Name', 'Pclass']



다음으로는 그래프를 통해 명목형 변수의 분포를 살펴보는 것입니다. 


for col in categorical_feature: titanic[col].value_counts().plot(kind='bar') plt.title(col) plt.show()




이렇게 살펴봄으로써 명목형 변수를 어떻게 다룰지를 판단할 수 있습니다. 예를 들어, 카테고리수가 너무 많고, 종속변수와 별로 관련이 없어보이는 독립 변수들은 빼고 분석하는 것이 나을 수도 있습니다.



이변수 탐색



sex_df = titanic.groupby(['Sex','Survived'])['Survived'].count().unstack('Survived')
sex_df.plot(kind='bar', figsize=(20,10))
plt.title('Sex')
plt.show()


성별-생존의 관계 파악처럼 두 변수의 관계를 파악하기 위해서는 위와 같이 확인할 수 있습니다.


7. 수치형 변수의 분포 살펴보기


단변수 탐색


단변수 탐색은 seaborn 패키지의 distplot 함수를 이용하면 매우 편합니다.


우선 이와 같이 전체 변수 중에서 범주형 변수와 기타 인덱스 변수, 종속변수들을 제외하고 수치형 변수만 골라냅니다.

numerical_feature = list(set(titanic.columns) - set(category_feature) - set(['PassengerId','Survived']))
numerical_feature = np.sort(numerical_feature)
numerical_feature

변수별로 for문을 돌면서 distplot을 그립니다


for col in numerical_feature:
    sns.distplot(titanic.loc[titanic[col].notnull(), col])
    plt.title(col)
    plt.show()


이변수, 삼변수 탐색


seaborn 패키지의 pairplot을 통해 종속변수를 포함한 3개의 변수를 한 번에 볼 수 있도록 플로팅합니다.


sns.pairplot(titanic[list(numerical_feature) + ['Survived']], hue='Survived', 
             x_vars=numerical_feature, y_vars=numerical_feature)
plt.show()



pairplot은 어러 변수의 관계를 한 번에 파악할 수 있으며,  hue 파라미터를 통해 종속변수를 지정함으로써 세 변수의 관계를 파악할 수 있습니다.



8. 수치형, 명목형 변수 간의 관계 탐색


앞서서 수치형-수치형  간의 관계, 그리고 명목형-명목형 간의 관계에 종속변수까지 포함해서 보았습니다. 이 번에는 수치형-명목형 간의 관계를 파악해 보는 것입니다. 예를 들어, 성별, 나이, 생존여부 3개의 변수를 동시에 탐색하고 싶을 수 있습니다. 이 경우에 명목형 변수에 따라 수치형변수의 boxplot을 그려봄으로써 대략적인 데이터의 형태를 살펴볼 수 있습니다. 


unique_list = titanic['Sex'].unique()
 
for col in numerical_feature:
    plt.figure(figsize=(12,6))
    sns.boxplot(x='Sex', y=col, hue='Survived', data=titanic.dropna())
    plt.title("Sex - {}".format(col))
    plt.show()


반응형
반응형

SAS Base 시험 절차



1. 학생의 경우 50% 할인을 받을 수 있는 Voucher 획득


2018년 8월 기준, SAS Base 시험 비용은 무려 180달러인데... Voucher를 쓰면 90달러로 절반의 할인을 받을 수 있습니다. 메일은 certification@sas.com 로 보내시면 되며, 한국의 대학생인데 Voucher를 받고 싶다고 내용을 한 후, 재학증명서를 첨부하면 1-2일 후에 메일 답장이 옵니다. 재학증명서는 본인의 학교 홈페이지에서 출력 후, 스캔을 해서 pdf 파일로 만들면 됩니다. 이 때 스캐너를 사용하셔서 스캔을 하셔도 되지만, CamScanner와 같은 어플을 사용해서 스캔해도 상관 없습니다. (저도 Camscanncer 이용했습니다.) 가끔 학생증으로도 학생임을 확인해서 Voucher를 주는 경우도 있지만 하지만 확실한 건 영어로 된 재학증명서입니다. 


2. 피어슨뷰 회원 가입 후 시험 신청하기


http://www.pearsonvue.com/sas


이 곳에서 피어슨 뷰 회원가입을 합니다. 회원 가입 시, 영문이름을 여권 등 신분증의 영어이름과 같게 해야합니다.



이 곳에서 SAS Base를 선택하고, 시험장, 시험 시간을 선택합니다. 또한 받은 Voucher를 꼭 입력합니다.



카드 정보를 기입하고 결제를 하면 위와 같이 결제 화면이 나옵니다. 학생은 이렇게 90불 할인을 받을 수 있습니다.




이런식으로 본인의 시험 스케쥴을 조회할 수 있습니다. 정해진 시간과 장소에 시험 장소에 가서 시험을 보면 됩니다. 



3. 공부하기


공부에 도움되는 것들


Cram bible

http://sinpong.tistory.com/notice/2


온라인 테스트

https://www.analyticsexam.com/sample-questions/sas-base-programmer-a00-211-certification-exam-sample-questions

http://biexamacademy.com/sas-base-certification-question-4/


SAS Solution Korea
https://www.youtube.com/channel/UC3qc20GAUtUvKfdh76-1uqw

온라인 테스트는 최종정리용으로 대충 보시고 Cram bible을 위주로 공부하면 합격에는 문제가 없을 것 같습니다. SAS Solution Korea 유투브 채널이 잘 모르는 문제를 해결 할 수 있어 정말 좋습니다. 

4. 후기



준비 기간 : 1주 정도 (Cram bible, 유투브 SAS Solution Korea 채널로 공부)


국회의사당역 근처에있는 미르헨지 교육 센터에서 시험을 보고 합격하였습니다. Cram bible에서 못 본 문제도 많긴 했는데 Cram bible에 나온 문제만 다 맞히면 웬만하면 합격 가능할 것 같다고 생각하였습니다. 덤프에 없던 문제 중 기억나는게 Compress 함수 관련된 문제가 나왔었습니다. 인자로 입력된 문자를 제거해주는 함수 같아서 그렇게 정답을 냈었습니다. 자격증 하나 따서 기분은 좋지만 학생할인 50% 받아도 시험 비용이 90달러라는게 압박이네요. ㅎㅎ 90달러 안아까우면서 SAS 좀 하시는 분은 가볍게 따보는 것 괜찮은 것 같습니다.

반응형
반응형


2018 한국 PyCon Tutorial 후기


뒤 늦게 한국 Pycon이 시작된다는 것을 알아서 등록 기간을 놓쳐 본 이벤트라고 할 수 있는 Conference는 놓쳤지만 아쉬운 마음에 Tutorial이라도 들어보기로 했다. Kaggle 관련한 Tutorial 이었는데, 최근 많이 사용되어지는 데이터 분석 (EDA, Feature enginerring, 모델링) 관련한 팁을 얻고자 하는 마음이었다. 장소는 삼성역 코엑스 센터였다. "Dive into diversity" 라는 문구가 행사의 슬로건인듯 했다.   



장소 : 삼성역 코엑스 2F 그랜드볼룸




튜토리얼 후기 


데이터 분석 관련하여 최근 많이 활용되는 방법들에 대한 유용한 정보들을 많이 얻었다. 특히, Feature Engineering 부분에서는 Label encoding, one hot encoding이나 모델에서 importance를 계산해서 차원을 축소하는 등의 기본적인 것을 제외하면 아는 것이 많이 없었는데, 최근 Kaggle에서 많이 쓰이는 방법들을 알 수 있어 좋았다. 예를 들어, frequency encoding, mean encoding 등이었다. 원래 값을 통해 새로운 feature를 생성하는 것이 성능을 높일 수 있다는 것이 신기했다. 


Feature Engineering은 크게, Tree 기반 모델이냐, Tree 기반 모델이 아니냐에 따라 그 방법이 달라진다. 특히 Tree 기반의 모델의 경우 categorial feature를 encoding 할 때, frequency encoding, label encoding 등을 사용한다. 하지만 label encoding 같은 경우, 타겟값과 전혀 상관 없는 값이 코딩되는 것이기 때문에 성능이 안 좋을 수 있다. 반면, frequency encoding 은 타겟값과 관련있는 값이 인코딩 되기 때문에 더 좋다고 할 수 있다. 반면 neural network의 경우, one hot encoding을 주로 하게 된다. 다만 one hot encoding은 차원이 커지는 문제가 존재한다. 특히 categorical feature를 제거하냐 안하냐를 선택할 때는 주로 feature에 따른 타겟값의 분포를 보고 선택한다. 카테고리에 따른 타겟값의 분포에 차이가 없다면 그 feature는 없어도 무방할 것이다. 특히 mean encoding의 경우 feature와 타겟값이 관련을 갖게 만들면서, 차원도 높이지 않는다는 두마리 토끼를 잡을 수 있는 방법이었다. 그래서 최근 많이 사용되는 categorical 변수의 feature encoding 방법이라고 한다.


또한 Kaggle에서는 Cross-validation이 매우 중요하다는 것을 깨달았다. cross-validation 이 잘못된다면, 모델의 성능을 잘못평가하는 것이 되어버리기 때문에 좋은 성적을 얻기 힘들다. 핵심은 validation set과 test set에서 변수들의 값의 분포를 동일하게 해야한다는 것이다. 그렇지 않다면 validation set에서 성능이 높더라도 test set에서의 성능을 보장하기 어렵다. 


머신러닝 관련한 부분에서는 역시 lightgbm, catboost, xgboost 등의 gradient boosting tree 계열의 알고리즘이 많이 사용된다고 하며, 좋은 성적을 낸 사람들은 대부분 stacking을 활용한다. stacking 같은 ensemble 알고리즘이 좋은 이유는 성능이 0.7짜리인 3개의 모델을 결합함으로써 0.8 이상의 성능을 갖는 모델을 만들 수 있다는 것이다. stacking을 어떻게 하느냐에 따라 leader board에서의 등수가 좌우되는 것 같았다.  


아래 코세라 강의에 Kaggle 관련한 많은 팁들이 있는듯하다. 

https://www.coursera.org/learn/competitive-data-science


반응형