04wk-16: 타이타닉 / 결측치처리+로지스틱 – 추가해설

Author

최규빈

Published

September 26, 2023

1. 강의영상

2. imports

import numpy as np 
import pandas as pd 
import sklearn.impute
import sklearn.linear_model
import missingno as msno

3. 자료불러오기

- 아래의 코드는 kaggle.json 파일이 셋팅된 codespace 혹은 kaggle.json 파일이 셋팅된 리눅스 컴퓨터가 있는 경우만 사용가능 (이런거 셋팅하는 방법은 대면수업에서..)

!kaggle competitions download -c titanic
!unzip titanic.zip -d ./titanic
df_train = pd.read_csv('titanic/train.csv')
df_test = pd.read_csv('titanic/test.csv')
!rm titanic.zip
!rm -rf titanic/
Downloading titanic.zip to /home/cgb2/Dropbox/07_lectures/2023-09-MP2023/posts
  0%|                                               | 0.00/34.1k [00:00<?, ?B/s]
100%|███████████████████████████████████████| 34.1k/34.1k [00:00<00:00, 408kB/s]
Archive:  titanic.zip
  inflating: ./titanic/gender_submission.csv  
  inflating: ./titanic/test.csv      
  inflating: ./titanic/train.csv     

- 리눅스서버를 사용할 수 없는 경우 download 후 압축풀어서 사용

4. 결측치 확인 및 처리

A. 결측치 체크

- 결측치확인

df_train.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   PassengerId  891 non-null    int64  
 1   Survived     891 non-null    int64  
 2   Pclass       891 non-null    int64  
 3   Name         891 non-null    object 
 4   Sex          891 non-null    object 
 5   Age          714 non-null    float64
 6   SibSp        891 non-null    int64  
 7   Parch        891 non-null    int64  
 8   Ticket       891 non-null    object 
 9   Fare         891 non-null    float64
 10  Cabin        204 non-null    object 
 11  Embarked     889 non-null    object 
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB

B. 시각화

msno.matrix(df_train) 
# msno.bar(df_train) # 큰 의미 X 
# msno.dendrogram(df_train) # 큰 의미 X 
# msno.heatmap(df_train) # 큰 의미 X 

C. 결측치 처리

df_train.select_dtypes(include="number")
PassengerId Survived Pclass Age SibSp Parch Fare
0 1 0 3 22.0 1 0 7.2500
1 2 1 1 38.0 1 0 71.2833
2 3 1 3 26.0 0 0 7.9250
3 4 1 1 35.0 1 0 53.1000
4 5 0 3 35.0 0 0 8.0500
... ... ... ... ... ... ... ...
886 887 0 2 27.0 0 0 13.0000
887 888 1 1 19.0 0 0 30.0000
888 889 0 3 NaN 1 2 23.4500
889 890 1 1 26.0 0 0 30.0000
890 891 0 3 32.0 0 0 7.7500

891 rows × 7 columns

def impute_missing(df):
    df_imputed = df.copy()
    df_num = df.select_dtypes(include="number")
    df_cat = df.select_dtypes(exclude="number")
    df_imputed[df_num.columns] = sklearn.impute.SimpleImputer().fit_transform(df_num) 
    df_imputed[df_cat.columns] = sklearn.impute.SimpleImputer(strategy='most_frequent').fit_transform(df_cat) 
    return df_imputed
impute_missing(df_test)
PassengerId Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 892.0 3.0 Kelly, Mr. James male 34.50000 0.0 0.0 330911 7.8292 B57 B59 B63 B66 Q
1 893.0 3.0 Wilkes, Mrs. James (Ellen Needs) female 47.00000 1.0 0.0 363272 7.0000 B57 B59 B63 B66 S
2 894.0 2.0 Myles, Mr. Thomas Francis male 62.00000 0.0 0.0 240276 9.6875 B57 B59 B63 B66 Q
3 895.0 3.0 Wirz, Mr. Albert male 27.00000 0.0 0.0 315154 8.6625 B57 B59 B63 B66 S
4 896.0 3.0 Hirvonen, Mrs. Alexander (Helga E Lindqvist) female 22.00000 1.0 1.0 3101298 12.2875 B57 B59 B63 B66 S
... ... ... ... ... ... ... ... ... ... ... ...
413 1305.0 3.0 Spector, Mr. Woolf male 30.27259 0.0 0.0 A.5. 3236 8.0500 B57 B59 B63 B66 S
414 1306.0 1.0 Oliva y Ocana, Dona. Fermina female 39.00000 0.0 0.0 PC 17758 108.9000 C105 C
415 1307.0 3.0 Saether, Mr. Simon Sivertsen male 38.50000 0.0 0.0 SOTON/O.Q. 3101262 7.2500 B57 B59 B63 B66 S
416 1308.0 3.0 Ware, Mr. Frederick male 30.27259 0.0 0.0 359309 8.0500 B57 B59 B63 B66 S
417 1309.0 3.0 Peter, Master. Michael J male 30.27259 1.0 1.0 2668 22.3583 B57 B59 B63 B66 C

418 rows × 11 columns

2023-10-24 추가해설

결측치 처리가 별로임: 사실 타이타닉 자료의 경우 위와 같이 train/test를 독립된 데이터세트로 보고 결측치를 처리하는 것 보다 모듈19-MinMaxScaler에서 소개한 것 처럼 train에서 fit한 imputer를 test에서 .transform()하는 것이 훨씬 자연스럽다. 다만 이 예제를 설명하는 단계에서는 train/test를 독립된 데이터세트로 보고 전처리를 할 경우 생기는 비상식을 이해하기 어려워 위와 같은 방식으로 진행했음.

5. 분석

A. 자료의 정리

{c:len(set(df_train[c])) for c in df_train.select_dtypes(include="object").columns}
{'Name': 891, 'Sex': 2, 'Ticket': 681, 'Cabin': 148, 'Embarked': 4}
X = pd.get_dummies(impute_missing(df_train).drop(['Survived','Name','Ticket','Cabin'],axis=1))
y = impute_missing(df_train)[['Survived']]
2023-10-24 추가해설

너무 많은 범주: Name, Ticket, Cabin은 너무 많은 범주를 포함하고 있으므로 제외한다고 설명했다. 그런데 사실

  1. 이름에는 혼인여부에 대한 정보가 포함될 수도 있어서 버리기 아깝다.
  2. 범주가 너무 많다면 통째로 변수를 제거하는 것 보다, 공통범주로 묶어서 처리하는 방법도 고려할 수 있다.

는 점에서 다른 분석방법을 고려할 수도 있다.

2023-10-24 추가해설

PassengerId: 사실 PassengerId불필요한 정보이고 (PassengerId 와 y는 corr이 없음) 있어봤자 오버핏만 유발하므로 제외하는게 좋다. 단지 이 시점에서는 “불필요한 변수를 제거하지 않으면 왜 오버피팅 현상이 발생하는가?” 를 설명할 수 없어서 남겨두었던 것.

B. predictor 생성

predictr = sklearn.linear_model.LogisticRegression()

C. 학습

predictr.fit(X,y)
/home/cgb2/anaconda3/envs/ag/lib/python3.10/site-packages/sklearn/utils/validation.py:1143: DataConversionWarning: A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().
  y = column_or_1d(y, warn=True)
/home/cgb2/anaconda3/envs/ag/lib/python3.10/site-packages/sklearn/linear_model/_logistic.py:458: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.

Increase the number of iterations (max_iter) or scale the data as shown in:
    https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
    https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
  n_iter_i = _check_optimize_result(
LogisticRegression()
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.

D. 예측

predictr.predict(X)
array([0., 1., 1., 1., 0., 0., 0., 0., 1., 1., 1., 1., 0., 0., 1., 1., 0.,
       0., 1., 1., 0., 0., 1., 0., 0., 0., 0., 0., 1., 0., 0., 1., 1., 0.,
       0., 0., 0., 0., 1., 1., 0., 1., 0., 1., 1., 0., 0., 1., 0., 1., 0.,
       0., 1., 1., 0., 0., 1., 0., 1., 0., 0., 1., 0., 0., 0., 0., 1., 0.,
       0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 1., 0., 1.,
       0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 1., 0.,
       0., 0., 0., 0., 1., 0., 0., 1., 0., 1., 0., 1., 1., 0., 0., 0., 1.,
       0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0.,
       1., 0., 0., 0., 1., 1., 1., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0.,
       0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0.,
       0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 1., 0., 1.,
       0., 0., 0., 1., 0., 1., 0., 1., 1., 0., 0., 1., 1., 0., 0., 0., 0.,
       0., 1., 0., 0., 1., 0., 0., 1., 0., 0., 0., 1., 1., 0., 1., 0., 0.,
       0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 1.,
       0., 0., 1., 1., 0., 0., 0., 0., 1., 1., 0., 0., 0., 1., 0., 0., 1.,
       1., 1., 1., 1., 1., 0., 0., 0., 0., 1., 0., 0., 0., 1., 1., 0., 0.,
       1., 0., 1., 1., 1., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
       1., 1., 1., 0., 1., 0., 0., 0., 1., 0., 1., 1., 0., 0., 1., 0., 0.,
       1., 1., 0., 1., 1., 1., 1., 0., 0., 1., 1., 0., 1., 1., 0., 0., 1.,
       1., 0., 1., 0., 1., 1., 1., 1., 0., 0., 0., 1., 0., 0., 1., 0., 0.,
       0., 1., 0., 0., 0., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 1.,
       1., 1., 1., 0., 0., 1., 0., 0., 0., 1., 1., 1., 1., 0., 0., 0., 1.,
       1., 1., 1., 1., 0., 0., 1., 1., 0., 1., 0., 0., 0., 1., 0., 1., 0.,
       0., 0., 1., 1., 0., 1., 0., 0., 1., 0., 0., 1., 0., 1., 0., 0., 0.,
       0., 0., 0., 0., 1., 0., 0., 1., 1., 1., 0., 1., 0., 0., 0., 1., 0.,
       0., 1., 1., 0., 0., 0., 1., 1., 0., 0., 1., 1., 1., 0., 0., 1., 0.,
       0., 1., 0., 0., 1., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1.,
       0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 1., 1., 1., 0.,
       0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 0., 0., 0.,
       0., 0., 0., 1., 0., 1., 0., 0., 1., 1., 1., 1., 1., 1., 0., 0., 0.,
       0., 0., 0., 1., 0., 0., 1., 0., 1., 0., 1., 0., 0., 1., 0., 0., 1.,
       1., 0., 0., 1., 0., 0., 1., 1., 1., 0., 1., 0., 1., 1., 0., 0., 0.,
       0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 1., 0., 1., 1., 1., 1., 0.,
       0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 1., 0., 1., 0., 0., 1., 1.,
       1., 0., 1., 1., 0., 0., 0., 1., 0., 0., 0., 0., 0., 1., 0., 1., 0.,
       0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 1., 1., 0., 0.,
       1., 0., 0., 1., 0., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0.,
       0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 1., 1., 0., 1., 0.,
       0., 0., 0., 1., 0., 1., 0., 1., 1., 0., 0., 1., 0., 0., 0., 0., 0.,
       0., 0., 0., 0., 0., 0., 1., 1., 0., 0., 0., 0., 0., 0., 1., 0., 1.,
       1., 1., 0., 0., 0., 0., 0., 0., 0., 1., 0., 1., 0., 0., 0., 0., 0.,
       1., 0., 0., 1., 0., 1., 0., 0., 0., 1., 0., 1., 0., 1., 0., 0., 0.,
       0., 0., 1., 1., 0., 0., 1., 0., 0., 0., 0., 0., 1., 1., 0., 1., 1.,
       0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1.,
       0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0.,
       1., 0., 1., 0., 0., 0., 0., 1., 0., 1., 0., 0., 1., 0., 1., 1., 1.,
       0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 0.,
       1., 0., 1., 0., 0., 0., 0., 0., 1., 0., 1., 0., 0., 0., 0., 0., 0.,
       1., 0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 0., 0., 1., 1., 0., 0.,
       0., 0., 1., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 1.,
       0., 0., 1., 1., 1., 1., 1., 0., 1., 0., 0., 0., 1., 0., 0., 1., 1.,
       0., 0., 0., 0., 1., 0., 0., 1., 1., 0., 0., 0., 1., 1., 0., 1., 0.,
       0., 1., 0., 1., 1., 0., 0.])

E. 평가

predictr.score(X,y)
0.8024691358024691

6. HW

위와 동일한 방식으로 test.csv에서의 생존여부를 예측하고 kaggle에 제출

#!kaggle competitions submit -c titanic -f submission.csv -m "Message"