👨‍💼

2.6 타이타닉 SAS - 1

 

1. SAS로 해보는 Titanic 데이터 분석

1) 데이터 읽어오기

1-1. 문제 정의하기

이 챕터에서는 SAS로 타이타닉 생존자/사망자 데이터를 분석하게 됩니다. 앞서 Python으로 한 분석을 SAS의 Logistic 모델과 머신러닝 모델을 이용하여 진행하게 됩니다. 간단한 분석을 통해 데이터 확인 / 시각화 / 모델 구축을 진행해보고 Kaggle에 결과를 제출하는 것으로 마무리됩니다.
 

1-2. SAS 프로그램 실행

설치하신 SAS University Edition을 실행시키시면 다음과 같은 화면이 뜨게 됩니다. 여기서 "JupyterLab 시작"을 눌러서 프로그램을 실행시킵니다. 설치 및 실행방법은 앞서 1.2 SAS환경세팅을 참고하시길 바랍니다.
notion imagenotion image

1-3 데이터 가져오기

1) SAS University에 데이터 가져오기
Sas University Jupyter Lab의 왼쪽 창을 보면 현재 3가지 파일이 있어요. 그 중 Titanic 폴더에 분석을 위한 데이터 파일(.csv)이 있고, 현재 작업중인 titanic.ipynb 파일을 볼 수 있습니다.
notion imagenotion image
 
데이터를 불러오게 하기 위해 미리 다운로드 된 파일(2.4 타이타닉 - Python1 참조)을 왼쪽 창에 드래그 하면 옮길 수 있고, 다 옮겨지게 되면 다음과 같습니다.
notion imagenotion image
2) 데이터 불러오기 - Libname 활용
이제 데이터 분석을 위한 라이브러리 지정을 해야하는데 라이브러리 지정은 단순하게 말해 데이터를 불러오거나 저장할 수 있는 폴더를 지정하는 것입니다. %LET 매크로 함수를 활용하여 PATH 변수를 'titanic/' 로 지정합니다. train데이터와 test데이터가 titanic폴더에 들어있기때문에 titanic/ 으로 설정했고, Libname 함수를 사용하여 라이브러리 이름을 TITAN으로 정하고 ""안에 &PATH를 지정하여 작업을 마무리 합니다. * 만약 컴퓨터를 재부팅하거나 SAS를 종료한다면 이 구문부터 다시 실행해야합니다.
/* PATH에 타이타닉 폴더 경로 지정*/ %LET PATH=titanic/; /* LIBNAME TITAN "&PATH";
SAS Connection established. Subprocess id is 4560 34 ods listing close;ods html5 (id=saspy_internal) file=stdout options(bitmap_mode='inline') device=svg style=HTMLBlue; ods 34 ! graphics on / outputfmt=png; NOTE: Writing HTML5(SASPY_INTERNAL) Body file: STDOUT 35 36 /*라이브러리 경로 설정*/ 37 %LET PATH=titanic/; 38 39 LIBNAME TITAN "&PATH"; NOTE: Libref TITAN was successfully assigned as follows: Engine: V9 Physical Name: /media/sf_myfolders/titanic 40 41 ods html5 (id=saspy_internal) close;ods listing;
라이브러리 작업이 성공하면 이제부터 SAS에서 Titanic 폴더를 TITAN이라는 이름으로 사용이 가능합니다. TITAN 안에 있는 데이터 파일을 사용할 수도 있고, 최종 결과물을 저장할 수도 있습니다.

2) CSV 파일 불러오기 - Proc import 활용

SAS는 기본적으로 .sas7bdat만 읽을 수 있습니다. 그렇기 때문에 엑셀, 텍스트 파일은 따로 구문을 써서 데이터를 읽어야 합니다. 그것이 Proc import인데요. SAS와 다른 형식의 데이터를 SAS파일로 불러오는 함수입니다. DATAFILE에는 파일의 위치와 파일명을 적어주고, OUT에는 불러온 파일을 SAS에서 사용할 데이터명, DBMS는 불러올 파일의 확장자명을 입력합니다.
/*PROC IMPORT를 사용하여 CSV파일을 SAS파일로 변경*/ PROC IMPORT DATAFILE = "titanic/train.csv" OUT = TITAN.TRAIN DBMS = CSV; RUN;
NOTE: TITAN.TRAIN data set was successfully created. NOTE: The data set TITAN.TRAIN has 891 observations and 12 variables. NOTE: PROCEDURE IMPORT used (Total process time): real time 0.29 seconds cpu time 0.09 seconds
완료가 되면 다음과 같은 문구가 결과창에 보이게 되고, Titanic 폴더에 train.sas7bdat가 생성됩니다. 이제 이 데이터를 가지고 분석을 진행하면 됩니다.
notion imagenotion image
 

2. 데이터 기본 정리 / 분석

1) 데이터 기본 정보 탐색하기 - Proc Content 활용

Proc Content를 활용하여 데이터 셋의 갯수 / 변수 갯수 / 변수 속성 등 데이터의 속성에 대해 확인할 수 있습니다.
/* PROC CONTENT를 활용하여 데이터셋의 구성확인*/ PROC CONTENTS DATA = TITAN.TRAIN; RUN;
실행하게되면 다음과 같은 결과가 나오게 되요.
notion imagenotion image
notion imagenotion image
위 명령어를 사용하여 데이터는 891개의 열과 12개의 칼럼으로 구성되어 있다는 것을 알 수 있습니다. 또한 변수에 대한 Type(숫자형, 문자형), Len(길이), Format/Informat (입출력방식)을 알 수 있습니다.

2) 빈도 확인 - Proc Freq/Tabulate 활용

2-1 1차 빈도표 작성 - Proc Freq

12개의 변수 중 Target의 빈도를 확인해볼게요
Titanic에서 타겟명은 생존여부를 나타내는 Survived인데요. 다음과 같이 실행하면 타겟의 빈도, 비율(%), 누적빈도, 누적비율이 나오게 됩니다.
/* 타겟의 빈도 확인 */ proc freq data=TITAN.train; table Survived; run;
Survived가 0이면 '사망' 1이면 '생존'입니다. 총 342명이 생존하고 약 38%인 것을 알 수 있습니다. 그외의 다른 변수들도 Table에 변수명만 적어주면 다음과 같은 빈도표를 얻을 수 있습니다.
notion imagenotion image
 

2-2. 2차 빈도표 작성 - proc freq

두 변수간 빈도나 비율을 확인할 때는 2차 빈도표를 작성해야 합니다. 다음 코드를 실행하면 2차 빈도표를 얻을 수 있습니다. 1차 빈도표에서 추가된 것은 *에 성별(sex)를 추가하면 됩니다.
결과를 보면 남성보다 여성에 대한 생존률이 2배정도 높다 라는 것을 알 수 있습니다. 영국 신사의 기사도 정신을 옅볼 수 있는 것 같습니다.
proc freq data=Titan.train; table Survived * sex; run;
notion imagenotion image
 

2-3. 2차 빈도표 작성 - proc tabulate

proc freq 와 더불어 proc tabulate를 사용해도 2차 빈도표를 얻을 수 있습니다. 사용 방법은 proc freq와 거의 동일합니다. proc tabulate은 excel의 피벗테이블과 같은 효과를 얻을 수 있습니다.
proc tabulate data = titan.train; class survived sex; table survived all , sex all; run;
옵션에 All을 써야 합계가 나오며, 각 변수마다 지정해줄 수 있습니다. 결과는 Proc Freq와 같습니다.
notion imagenotion image

3) 데이터 시각화 - Proc Sgplot, Box plot 활용

3-1 단일 히스토그램 - Proc Sgplot

SAS에서 Proc sgplot을 사용하여 손쉽게 그래프를 그릴 수 있습니다.
vbar는 가로축의 변수를 설정하는 옵션이고 타겟의 빈도를 확인하기 위해 Survived를 입력합니다. 옆에 datalabel을 입력하면 빈도값이 그래프 위에 뜨게 되고, missing을 입력하면 결측값에 대한 빈도도 확인할 수 있어요. label 구문은 축의 제목을 설정하는데 활용됩니다. 다음과 같은 히스토그램을 얻을 수 있습니다.
proc sgplot data=TITAN.TRAIN; vbar Survived / datalabel missing; label Survived = "Survived"; run;
notion imagenotion image

3-2 누적 히스토그램 - Proc Sgplot

누적 그래프를 그리려면 다음과 같이 단일 히스토그램 문에 pctlevel=group와 group문을 추가하면 됩니다.
title "Survived vs Gender"; proc sgplot data=TITAN.train pctlevel=group; vbar sex / group=Survived stat=percent missing; label Embarked = "Gender of Survived"; run;
다음과 같이 누적 히스토그램을 확인할 수 있습니다. 성별간 생존률이 더 뚜렷하게 보이네요.
notion imagenotion image
 

3-3 박스플롯 - Box plot

SAS에서는 박스플롯을 그리기전 데이터를 정렬해야 합니다. 데이터 정렬은 Proc sort를 활용해서 정렬할 수 있고, proc Box Plot을 활용하면 Boxplot 그래프를 그릴 수 있습니다.
/* 박스플롯을 그리기전 정렬 후 BoxPlot을 그린다.*/ proc sort data=Titan.train out=sorted; by Survived descending Age; run; title ‘Box Plot for Age vs Survived’; proc boxplot data=sorted; plot Age*Survived; run;
생존을 한 승객들의 연령대가 대체적으로 낮음을 볼 수 있습니다.
notion imagenotion image

4) 기초 통계량 분석

4-1 기초 통계량 분석하기 - Proc Means

각 변수에 대한 기초 통계량을 확인하기위해 Proc MEANS를 사용하면 됩니다. N Nmiss mean등 확인하고 싶은 통계량을 차례대로 입력하면 됩니다.
proc means data=TITAN.train N Nmiss mean std min P1 P5 P10 P25 P50 P75 P90 P95 P99 max; run;
대부분의 변수들이 결측값이 없고, Age만 결측값이 존재하는 등 기초 통계량을 확인할 수 있습니다.
notion imagenotion image
만약 그룹별 통계량을 확인하고 싶으면 Class문을 추가하면 되고 다음과 같이 실행하면 됩니다.
proc means data=TITAN.train N Nmiss mean std min P1 P5 P10 P25 P50 P75 P90 P95 P99 max; class survived; run;
notion imagenotion image
 

4-2 빈도 확인하기 - Proc Freq

아까 1차/2차 빈도표를 만들때 Proc Freq를 사용해 보았는데요. Proc Freq를 사용하여 모델을 만들기 전에 타겟에 대한 빈도를 확인함으로 어떤 값을 넣었을때 모델이 잘 적합이 될지 판단을 해보고, 변수에 어떤 값들이 있는지도 확인해봐요.
proc freq data=TITAN.train nlevels; tables Survived; tables Sex; tables Pclass; tables SibSp; tables Parch; tables Embarked; tables Cabin; run;
다음과 같이 변수별 빈도를 확인할 수 있습니다. 여기서는 전체 변수 빈도 현황과 Survived, Sex를 예시로 넣었습니다.
notion imagenotion image
빈도 확인하기에서 Age, Embarked, Cabin등에서 결측값을 확인했습니다. 이 결측값을 가진 값에 대해 제거할 수도 있고, 평균값 같은 대체값으로 대신 채워넣을 수도 있습니다. 다음장인 모델 구축에서 처리하도록 하고 이번 장은 마치도록 하겠습니다. 이번 분석에서는 Cabin은 사용하지 않을 예정입니다. Age와 Embarked에 대해 전처리를 수행하보고 모델을 구축해봅시다.
 

3. Titanic 생존자 예측 모델 구축

1) 분석데이터 구축

1-1 데이터 채워넣기 - Age 변수

모델 구축을 하기 위해서 빈도 분석시 발견했던 결측값들을 먼저 채워넣어야 합니다. 결측값을 어떻게 처리하냐에 따라 모델의 결과가 천차만별이 될 수 있기 때문에 통계량들을 살펴보면서 어떻게 데이터를 채워넣어야 할지 고민해야합니다. 데이터 전처리시 주의해야할 것은 원 데이터가 변형될 수 있다는 점인데, 그것을 방지하기 위해 새로운 데이터셋을 만들고, 원데이터는 보존하는 것이 좋습니다.
결측값을 가진 변수 중 Age에 대해 값을 채워 넣어 볼텐데, 데이터를 채워넣는 방법 중의 하나는 If 문을 사용하여 채워넣을 수 있습니다.
값을 채워넣기 전에 어떤 값을 채워넣을지를 고민해봐야하는데요. 이번 분석에서는 티켓 클래스에 대한 나이에 대한 평균값을 채워넣도록 하겠습니다.
If 문은 If 조건 then 결과/처리로 끝나게 됩니다. 밑에서 보실 코드를 한글로 해석하게 되면 다음과 같습니다.
if age='.' and Pclass = 1 then age = 38; 만약에 age가 Null 값이고 Pclass가 1이면 age를 38으로 채워넣을거야 else if age = '.' and Pclass = 2 then age = 30; 근데 만약에 age가 Null값인건 동일한데 Pclass가 2면 age를 30로 채울꺼고 else if age = '.' and Pclass = 3 then age = 25; 또 다르게 age는 Null이지만 Pclass가 3이면 age는 25로 변경할거야ㅇ
평균값을 확인해보기 위한 코드는 위에서 보았던 Proc tabulate를 사용해보겠습니다.
proc tabulate data=titan.train; class Pclass; var Age; table Pclass*age*mean; run;
 
notion imagenotion image
평균값은 소수점으로 나오지만 실제 나이는 소수점이 없으므로 반올림을 적용해보도록 합시다. 티켓 1등급의 평균 연령은 38세, 2등급은 30세, 3등급은 25세 입니다. 아무래도 티켓 등급은 연령대별로 나뉘어 진것을 단편적으로 알 수 있습니다. 이 결과를 적용해봅시다.
/* Age 결측값을 채워넣기 */ data Titan.train2; set Titan.train; if age='.' and Pclass = 1 then age = 38; else if age = '.' and Pclass = 2 then age = 30; else if age = '.' and Pclass = 3 then age = 25; run;
NOTE: There were 891 observations read from the data set TITAN.TRAIN. NOTE: The data set TITAN.TRAIN2 has 891 observations and 12 variables. NOTE: DATA statement used (Total process time): real time 0.02 seconds cpu time 0.00 seconds
Titan.train2라는 새로운 데이터셋이 생겼습니다. 주의 해야 할 것은 전처리를 했다면 Test 데이터에도 동일한 과정을 적용해야 한다는 것입니다.
notion imagenotion image
Age의 결측값이 잘 대체되었는지 확인할 수 있습니다.
proc means data=TITAN.train2 N Nmiss; run;
notion imagenotion image
 

1-2 데이터 채워넣기 - Embarked 변수

이번에는 Embarked 변수의 결측치를 채워넣도록 하겠습니다. Embarked 변수는 결측치가 2개이므로 가장 많은 'S'를 넣도록 하겠습니다.
data Titan.train2; set Titan.train2; if Embarked='' then Embarked = 'S'; run;
notion imagenotion image
기존 2개의 결측치가 대체 된 것을 볼 수 있습니다.
 

2) 베이스라인 모델 구축

2-1 베이스라인 모델 만들기 - 로지스트 회귀모형

드디어 모델을 구축할 준비가 끝났습니다. 베이스라인 모델은 로지스틱 회귀모형이고 타겟변수가 두가지 값으로 되어있을때(이진형) 가장 기본적으로 사용되는 분류/예측모형입니다. * 기준이 되는 모델(baseline model)로 사용하기 위해서 성능의 기준이 되는 모델을 베이스라인 모델(baseline model) 이라고 합니다.
Class에 사용할 변수들을 모두 넣고, model에는 타겟변수 = 목적변수 1 목적변수 2 목적변수 3 ... 와 같이 작성합니다. Selection에는 stepwise를 사용합니다. forward 방법과 backward방법의 문제점을 개선한 방법으로 변수를 추가하고 제거하는 과정을 반복하여 최종 모형을 선택하는 방법입니다.
store는 train_logistic이라는 이름으로 모델을 저장합니다. 향후 테스트 데이터를 검증하고 예측값을 확인하기 위한 Proc PLM을 사용하려면 Store을 꼭 사용해야 합니다.
정상적으로 실행되면 다음과 같은 결과창을 확인할 수 있습니다. 본 모델에서는 Cabin, Name, PaaengerID, Ticket 변수는 제외한 모델입니다.
 
proc logistic data= Titan.train2; class Embarked Parch Pclass Sex SibSp Survived; model Survived(event='1') = Age Fare Embarked Parch Pclass Sex SibSp / selection=stepwise expb stb lackfit; output out = temp p=new; store train_logistic; run;
 
notion imagenotion image
범주형 변수는 다음과 같이 적합됩니다.
notion imagenotion image
Step0부터 SAS에서 StepWise 방식에 따라 변수를 넣었다가 빼는 작업을 반복합니다.
notion imagenotion image
 
이번 분석에서는 Step4까지 실행됩니다.
 
notion imagenotion image
분석에 사용된 변수들은 총 4개로 Sex Pclass Age SliSp이고, 모두 유의수준 0.05이하로 모델에 사용하기 적절합니다.
notion imagenotion image
SAS의 장점 중의 하나는 로지스틱 회귀분석의 범주형 변수에 대해 더미변수를 생성할 필요가 없다는 점인데, 여기서 Class에 있는 모든 범주 변수를 선언하여 더미화 시킬수 있숩니다.
 
이제 베이스라인 모델이 만들어졌습니다. 지금까지 고생하셨습니다. 이제 해당 모델이 얼마나 잘 만들어졌는지 Test 데이터를 적합시켜 확인해봅시다.
 

2-2 결과 확인 - Test 데이터 불러오기

분석 모델이 얼마나 잘 구축되었는지 확인하기 위해 앞에서 사용했던 Proc Import를 사용하여 Test.csv 파일을 불러옵니다.
PROC IMPORT DATAFILE = "titanic/test.csv" OUT = Titan.test DBMS = CSV; RUN;
NOTE: TITAN.TEST data set was successfully created. NOTE: The data set TITAN.TEST has 418 observations and 11 variables. NOTE: PROCEDURE IMPORT used (Total process time): real time 0.09 seconds cpu time 0.06 seconds
notion imagenotion image
Test 데이터는 보통 Target변수가 존재하지 않으므로 기존 Train 데이터에서 Target을 제외한 11개의 변수가 있는 것을 확인할 수 있습니다.

2-3 모델 적합 - 테스트 데이터 만들어진 모델에 적합하기

Proc plm을 사용하여 앞에서 만들었던 모델을 테스트 데이터를 적합합니다. 먼저 train_logistic을 source로 합니다. score data에는 검증 데이터인 Titan.test를 지정하고, Out으로는 Titan.test_scored로 지정합니다.
proc plm source=train_logistic; score data=Titan.test out=Titan.test_scored predicted=p / ilink; run;
수행을 하면 다음과 같이 잘 적합된것을 확인할 수 있다.
notion imagenotion image

2-4 Kaggle에 제출하기 위한 데이터셋 구축

지금까지는 생존을 할 확률 가능성을 구한 것이지 생존/사망 여부를 구한 것이 아닙니다.
Kaggle에 제출하기 위해서는 결과값이 생존(1)또는 사망(0)으로 제출해야하므 한번 더 작업이 필요합니다. Predict 값은 0부터 1까지의 숫자로 구성되어있는데, 여기서 P값을 얼마 이상으로 구분하느냐에 따라 결과가 완전 달라질 수 있습니다. Predict 값에 대한 기준은 직접 정해야 하며, 본 분석에서는 0.5 이상을 생존으로 정의하였습니다.
모든 작업을 마친후 캐글에 제출하기 위해 proc export를 사용하여 제출 파일인 Result.csv를 생성한다. 해당 작업을 마치면 제출하기 위한 최종 데이터셋은 다음과 같습니다.
 
notion imagenotion image
notion imagenotion image
 
마지막으로 생성된 Result.csv 파일을 제출하기 위해 Result.csv에 오른쪽 마우스 클릭하여 Download를 클릭하여 파일을 저장합니다.
notion imagenotion image

2-5 Kaggle에 데이터 제출

Kaggle에 접속하여 타이타닉 대회의 Submit Prediction을 클릭한 후
Step 1 Upload submisstion File에 화살표 그림에 생성한 Result.csv를 드래그하여 제출한다. 정상적으로 제출되면 Result.csv 옆에 체크표시가 뜨게 됩니다.
notion imagenotion image
 
Step 2에 간단한게 분석에 대해 Comment를 작성한 후 하단에 Make Submission을 클릭하여 제출을 마무리 한다.
notion imagenotion image
 

4. 결론

notion imagenotion image
 
제출한 후에는 결과값을 바로 확인할 수 있. 초기 모델의 예측결과는 Score-0.76555으로 76.5%의 정확도를 기록하였습니다. 베이스라인치고는 괜찮은 결과를 얻었습니다.
지금까지 SAS를 활용한 Kaggle 분석을 간단하게 수행해보았는데요.
현재 버전 기준으로 SAS University에서 사용할 수 있는 모델이 회귀 모형인 제한점이 있지만 그래도 Python과 R에 익숙하지 않은 SAS 유저들이 Kaggle에 입문하기에는 좋은 기회라고 생각합니다.
정확도를 높이기 위해 머신러닝 모델을 이용한 분석을 조금 더 진행해보고자 합니다. 미리 말씀드리면 SAS University 버전은 머신러닝 모델을 지원하지 않기 때문에 SAS Base(SAS 9.4)가 필요하다는 점을 말씀드립니다.