본문 바로가기

Hello MLop/ML

MLop_ML_로지스틱회귀_타이타닉 생존자 예측

20221108

21일차

 


오늘의 분석은 로지스틱 회귀분석이다.

다뤄볼 데이터는 kaggle에서 가져온 Titanic 데이터를 활용해 보았다.

 

앞서 한 선형회귀 분석의 보험료 측정에서는 어떤 요인이 결과에 영향을 미칠까의 문제였다.

즉, 쉽게 말하면 선형 회귀 분석은 결과에 요인이 영향을 미치냐 안미치냐 의 문제다.

 

로지스틱 회귀 분석결과가 1아니면 0이다.

즉, 죽거나 살거나, 가거나 멈추거나, 결과가 두 가지로 정해져 있다.

이러한 결과들을 요인이 결정하는데 영향을 미치느냐 마느냐다.

 

그렇다면 통계학적 용어를 대입해보면

결과종속변수(y, f(x), ...)로 대입해보고

요인독립변수(x, ax+b,...)로 대입해 보자.

 

선형 회귀분석독립변수가 종속변수의 값에 영향을 얼마나 끼치는지 분석하는것이고

로지스틱 회귀분석독립변수가 종속변수가 1과 0이 되는것에 얼마나 영향을 끼치는지 분석하는 것이다.

 

그래서 타이타닉 자료생존률(죽었냐 살았냐, 1과 0으로 나타낼 수 있는)에 다른 요인들이 영향을 미쳤냐

라는 분석이기 때문에 로지스틱 회귀분석에 타당 한것이고

 

보험료 예측보험료(변할 수 있는 값, 1과 0같은 딱 떨어지지 않는 시시때때로 변하는)가 다른 요인들 때문에

올랐냐 떨어졌냐 오르는데 영향을 줬냐 떨어지는데 영향을 줬냐라는 분석이기 때문에 선형회귀분석에 타당하다.

 

(인생 처음 통계학적 지식을 문과생 이면서 비전공자인 내가 이해한 최고의 쉬운 설명이다.)

 


그럼 어떤 상황에서, 즉 어떤 데이터가 왔을때 내가 어떤 분석을 해야하는지 알았다

나머지는 쉽다.

 

바로 가보자.

 

 

데이터 확인

 


✨ 가장 먼저 해야 할 기본 순서

 

info 확인   ⭐

 Column 확인 (변수 확인)

 Non-Null Count 확인

 Dtype 확인 ( object가 섞여 있는지)

 


 

 

종속변수(생존 여부)

독립변수(생존 여부를 제외한 나머지)

 

설정 완료.

 


✔ 통계 정보 출력 .describe()

 

통계 정보 출력 또한 중요하다.

 

예를 들어 운임요금(Fare) 컬럼의 최소부터 최대까지 격차가 매우 크다.

이는 최대 요금이 다른 요금에 비해서 이상하게 수치가 크다는것을 알 수있고

다시 말하면 이상치가 존재한다는 것을 알 수 있다.

(나이 Age 컬럼 또한 같은 case)

 

.describe에 include=['O'] (알파벳 O) 를 주면

Object 컬럼만 describe해주는데 uniquetop, freq가 출력된다

 


✔ 상관관계 출력

 

.corr() 은 각 컬럼과 컬럼간의 상관관계를 수치로 나타낸다.

 

위의 주석처럼 0~1 사이의 수치를 보고

얼마나 상관관계가 있는지 알 수 있다.

 


이를 히트맵(heatmap)으로 한눈에 알아보기 쉽게 만들 수 있다.

히트맵을 출력하기 위해 matplotlibseaborn을 import해주고

 

위의 코드를 간단히 설명해 보자면

 

snsheatmap만들건데

 

heatmap의 데이터train.corr()로 하고 cmap(heatmap color)coolwarm으로vmin(범주의 최소값)-1vmax(범주의 최대값)1

annot(각 색상별 수치 표시) = True

 

이 결과 우리는 시각적으로 데이터의 상관 관계를 이해하는데 도움을 받는다.

 


✨ 데이터 전처리 하기

 

이제 상관도까지 봤겠다.

데이터를 사용하기 위해 전처리를 해보자.

 

보통 먼저 결측치를 어떻게 해결할까 고민 한다.

 

결측치를 해결하는 방식은 상황에 따라 아주 다양하다.

 

우선 채우는것과 버리는것으로 나눈다.

 

결측치를 버리는 경우는 보통 컬럼내의 데이터의 비중이 

상당 수 차지한다고 생각되면 이걸 의미있게 채울것인지 버릴것인지 체크해 봐야한다.

 

만약 내가 원하는 결과를 도출하기 위해 결측치가 많은 컬럼이 도움이 되지 않으면

컬럼 자체를 삭제하는 경우가 있다.


채우는 경우는 결측치차지하는 비중과는 관계 없이 중점을 둬야하는 부분은

내가 원하는 결과를 도출하기 위한 컬럼이라고 선택받은 것이니

최대한 효과를 낼 수 있는 결측치 값을 구해서 채워주는게 합리적이다.

 


이제 결측치가 있는 데이터를 봐보자.

 

 

 

df.isnull().sum()을 통해 각 컬럼별로 결측치가 몇 개 있는지 위에서 확인해 보았다.

현재 'Age', 'Cabin', 'Embarked' 에서 결측치가 발견 되고 있다.

 

 


 

'Embarked' 컬럼의 경우 결측치가 2개로 결측치 개수가 가장 적은 컬럼이다.

이 경우 여러 방법이 있겠지만

 

.unique()를 사용해 가장 많은 value값을 확인

가장 많은 value값 .fillna("")채워준다.

 


'Age'컬럼의 경우 총 177개의 결측치가 있는데

우선 이 컬럼이 내가 구하려는 생존영향을 미쳤는가에 중요한 컬럼인지 확인한다.

 

나이라는것은 타이타닉호 침몰의 환경특성상 삶과 죽음에 영향을 끼친다고 판단해서

(= * 도메인 지식)

 

우린 이 컬럼을 살리기로 결정하고 결측치 또한 채워야 겠다고 결정해야 한다.

 


그 다음의 문제는

 

그럼 177개의 비어있는 나이를 어떻게 넣어야 비어있지 않은 것처럼 느껴질까의 고민을 해봐야 한다.

 

이번에는 name에서 힌트를 얻었는데

현재 'Name'컬럼의 value값들을 보면 시대 특성상 이름안에 경칭(Mr,Ms,Master...)이 들어있다.

 

그럼 이제 경칭별 나이 평균을 구해서 결측치경칭별로 채워주면 좋겠다라는 생각을 하게 된다.

* 평균을 구하는 경우는 나이가 특정값으로 되면 안되기 때문이다.


 

위의 코드를 풀이하자면

새로운 컬럼 'Title'을 만들건데, values

'Name'컬럼의 values에서 문자열에서(str) .extract(추출)하겠다.

어떤조건? '([A-Za-z] +)\.'조건으로

 

str.extract()메서드에서 ()안의 조건특수문자가 일반적인 파이썬에서의 의미로 해석되지 않는데

위의 '([A-Za-z] +)\.'를 차근차근 뜯어서 보면

 

대상이 되는 문자열 '' 에서 추출하려는 대상은

([A-Za-z] # 대문자에서 소문자로 끝나고 # 1번 이상 반복되는것들 ) \. # .으로 끝나는

것들을 추출하겠다는 것이다.

 

그래서 예를 들어

Braund, Mr. Owen Harris 라는 이름이 왔을때

위 조건에 해당되는 MR만 추출되는것이다.

 

* \.이 ()안에 없기 때문에 .전의 값만 추출됨


이 결과 출력은

위와 같이 되고 아래 코드에서 value_counts()를 해줬기에 갯수가 출력되는 것이다.

 

하지만 10개 이하인 경칭들은 Title의 values에서 미미한 영향을 끼치므로

개수가 많기도 하고 하니 통합을 해주면 좋다.

 


그럼 10개 이하인 경칭들을 빼보자.

 

rarelist라는 변수에 리스트를 생성하고

반복문을 돌려서 만약(if) 들어오는 Title의 value가 10개보다 작으면

valuerarelist에 추가하는 것이다.

 

그 결과 rarelist는 위와 같이 10개 이하였던 경칭만 저장 된다.

 


그럼 마지막으로 Title(경칭 Column)values =

Title values에서 rarelist에 있는 값('Mme', 'Sir', 'Don'...)들은 'Rare'replace(대체하다) 을 해주면

 

Title 컬럼의 values는 위와 같이 Rare가 추가되어 통합 된것을 확인할 수 있다.

 


그럼 이것들을 바탕으로 Title별 Age의 값들의 평균title_age_mean이라는 변수에 저장해 주면

위와 같이 각 경칭별 평균 나이가 나온다.


그럼 이제 반복문을 통해 결측치를 채워보자.

 

위 반복문 코드의 해석은

v (= 들어가는 값)는 'Title' values의 .unique()로 하고

 

차례대로 .loc(행 조회)했을때

 

'Age'컬럼에서 value결측치 이면서 'Title'컬럼의 valuev인 것을

title_age_mean[  v (= 'Title'values.unique() )  ]로 바꿔준다.

 


 

 

이제 전체 데이터의 결측치 개수를 조회하면

'Cabin' 컬럼만 결측치가 남아있는데

사실 'Cabin'컬럼은 생존률과 상관이 많이 없으므로 컬럼 삭제를 진행해 주었다.

 

 


 

컬럼 삭제를 하는김에 결과를 도출하는데 불필요하다고 생각되는 모든 컬럼을 삭제한 상황이다.

 

 


 

결측치 처리가 끝난 후

 

데이터 타입이 object로 되어있는 범주형 변수들을

.get_dummies메서드를 이용해 가변수로 만들어 준다.

 

* 수치로 비교해야 하기 때문

 


로지스틱 회귀 함수를 임포트해주고

 

model이라는 변수에 로지스택회귀함수를 저장해준다.

 

그리고 앞 포스팅에서 봤던시험셋, 테스트셋을 분리해준다.

 


pred = model(로지스택회귀함수).predict(X_test) # X_test를 예측한다

 


accuracy_score를 이용해서 y_test, pred의 정확도를 구하면

 

타이타닉 데이터종속변수독립변수로지스틱 회귀함수로 학습시켰을때

생존률에 대한 변수들이 결과를 예측하는 정도는 0.7988....으로 결과를 도출해 낸것을 확인할 수 있다.

 

* .coef는 기울기이며 상관계수인데

 

값이 -일 경우 해당 독립 변수는 종속변수와 반비례 관계이고

값이 +일 경우 해당 독립 변수는 종속변수와 비례 관계이다.

 

 

'Hello MLop > ML' 카테고리의 다른 글

MLop_ML_RandomForest_중고차 가격 예측  (0) 2022.11.15
MLop_ML_DecisionTree_급여 예측 분류  (0) 2022.11.13
MLop_ML_NaiveBayes_SMS 스팸 수집  (0) 2022.11.12
MLop_ML_KNN_WineData  (0) 2022.11.10
MLop_ML_선형회귀_보험료 예측  (0) 2022.11.07