GDG 스터디 Section.05

노은서·2024년 10월 15일

✅Section05. 전통적 머신러닝 - 지도 학습 모델 part2

📌로지스틱 회귀 (Logistic Regression) 알고리즘 설명

🏷️Logistic Regression(로지스틱 회귀)

= 회귀라고 이름이 붙은 것 중에서 유일하게 분류 문제

  • 선형회귀를 분류 문제에 적용 가능 ? --> (O) 하지만, 0.5 경계 부분이 애매해서 정확한 분류 결과 보장X

--> 선형 회귀 라인은 0.5 경계 부분이 차이가 얼마 안 나지만 0,1로 분류됨 --> 애매함 --> 확률값을 반환할 수 없을까 ? & 미분가능한 함수였으면 함 --> Sigmoid 함수를 사용해서 0~1 값으로 확률값을 반환해줌.

🏷️ Sigmoid 함수(=Logistic 함수)

= 선형 회귀의 결과 값을 기반으로 시그모이드 함수를 사용하면 0~1 사이의 확률값으로 변환이 됨!

  • 시그모이드 함수 공식에서 z값(logit)은 선형회귀의 결과값(wx+b)

    ⭐ 이전에 선형회귀 라인과 다르게 0.5 부근에서 급격히 변화

🏷️ Logistic Regression classifier

1. 로지스틱 회귀는 이진 분류 문제를 해결하는 가장 단순한 분류기
2. 구현이 간단하고 모든 분류 문제의 기초로 널리 사용됨
3. 로지스틱 회귀에서 사용하는 개념은 딥러닝의 분류 문제에도 적용됨

  • 딥러닝에서 마지막 층에서 사용하는 활성화 함수로 시그모이드 함수를 쓰는 경우가 많음, 로지스틱 회귀의 기본 아이디어와 같음
    4. 독립변수와 종속변수 간의 관계를 찾아내고 평가함
  • 계산된 선형 결합을 시그모이드 함수로 변환해, 데이터가 특정 클래스에 속할 확률을 평가함.
    5. sklearn.linear_model.LogisticRegression(solver='lbfgs')
  • 사이킷런 라이브러리에서 LogisticRegression 클래스를 사용해 모델 구현 가능.
  • solver='lbfgs'는 최적화 알고리즘을 의미 (디폴트값 ,손실 함수를 최소화하는데 사용됨)

📌 실습)Logistic Regression을 이용한 이진분류

✔️ 성별 소득 data에 따라 특정 구매자의 구매하지 여부를 예측

🏷️ 라이브러리 선언

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, precision_score, recall_score 
from sklearn.metrics import confusion_matrix, f1_score, roc_curve, roc_auc_score
import seaborn as sns

🏷️ 데이터셋 로드, 내용 확인

df = pd.read_csv("datasets/Social_Network_Ads.csv")
df.head()
df.tail(20) # 뒤쪽에서 20개를 볼 수 있음.
  • 정답 데이터의 분포 확인 --> 2 : 1 (데이터 불균형이 심한 편은 아님)
df["Purchased"].value_counts() 

🏷️ 필요한 변수 추출(Age, EstimatedSalary를 변수로 선택)

  • 두 개의 숫자 컬럼만 선택해서 지도학습
    ⚠️ df.iloc 이용해서 인덱싱
    ⚠️ astype("float32") : 머신러닝의 입력으로 줄 떄 일반적으로 float 타입으로 주는게 좋음
# 두 개의 변수만 인덱싱 (데이터프레임에 인덱스를 가지고 슬라이싱을 해야함)
# iloc 인덱스로 로케이션 하겠다고 해서 iloc
# row 전부다, 그리고 인덱스 2,3번만 추출하겠다, 슬라이싱 하겠다.
X = df.iloc[:,[2,3]].values.astype("float32") # 머신러닝의 입력 float 타입
y = df.iloc[:,4].values.astype("float32")
X.shape, y.shape 
  • 실행결과 : ((400, 2), (400,))

🏷️ 훈련/테스트셋 분리

# 4:1 비율로 나누기!!
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2,random_state=0)!
X_train.shape, X_test.shape, y_train.shape, y_test.shape
# 400개의 데이터가 320,80개로 잘 나눠졌음
  • 실행결과 : ((320, 2), (80, 2), (320,), (80,))

🏷️ 피처 스케일링

⚠️train data로 fit하고, test data는 train data의 분포에 맞춰 transform
⚠️ 훈련 데이터 : fit & transform 둘 다 해줌
⚠️ 테스트 데이터 : transform만 해줌!!

sc = StandardScaler()
X_train = sc.fit_transform(X_train) # fit,transform 두 단계를 한번에 합친거임. 
X_test = sc.transform(X_test) # X_test는 transform만 해야함. 

🏷️ 모델 훈련(학습)

lr_clf = LogisticRegression() # 그냥 디폴트 값 사용
lr_clf.fit(X_train,y_train)

🏷️ 결과 예측

⚠️ predict() - X_test를 이용해 예측된 class 반환
⚠️ predict_proba() - X_test를 이용해 class당 확률값 반환

y_pred = lr_clf.predict(X_test)
y_pred # 0,1 반환 

y_pred_proba = lr_clf.predict_proba(X_test)
y_pred_proba # 확률값 반환

🏷️ 평가지표 accuracy, precision, recall

⚠️ threshold를 높여주면 precision은 내려가고 recall은 올라감 --> 목적에 맞게 정하기!

accuracy_score(y_test,y_pred) # 일단 맞춘거는 92.5% 맞춤

# 우리가 맞췄다고 한 것 중에서 우리가 이제 truetrue로 잘 맞추느냐
precision_score(y_test,y_pred) # 물건을 살 사람을 살 사람으로 잘 맞추느냐 --> 94%

recall_score(y_test,y_pred) # 전체 true 중에서 우리가 얼마를 놓치지 않고 다 포함했느냐
# precision score가 94인데 recall은 72임 --> 우리가 놓친 케이스가 많다는 것.

🏷️ 혼동 행렬을 이용한 모델 평가

cm = confusion_matrix(y_test, y_pred)
cm
ax = sns.heatmap(cm,annot=True, fmt='d') # annot=True, 박스 안에 숫자 설정
ax.set_title('Confusion Matrix')
ax.set_ylabel('True')
ax.set_xlabel('Predicted')

🏷️ ROC_AUC 곡선 시각화

⚠️ 성능을 비교할 때, 여러 개의 분류기 중에서 커브의 면적이 가장 넓은 모델을 선택 --> 최상의 모델

  • roc_curve(y_true, y_score)

  • fpr - false positive rates, tpr - true positive rates

y_proba = lr_clf.predict_proba(X_test)
y_scores = y_proba[:,1]
y_scores   # 1일 확률이 몇 %인지 그 값을 알려줌 

# 실제로 변수를 3개 반환하는데, 우리는 2개만 쓰니깐 (_) 언더바 써준다.
fpr,tpr,_ = roc_curve(y_test,y_scores) 
auc = roc_auc_score(y_test,y_scores)

# 시각화
plt.plot(fpr,tpr,label="auc = {:.2f}".format(auc))
plt.xlabel("False Positive Rate")
plt.ylabel("True Positive Rate")
plt.title("ROC_AUC curve")
plt.legend()

📌 앙상블 학습(Ensemble Learning)

앙상블 학습이란 ?
= 다수의 약한 학습기(weak learner)를 조합(Ensemble)하여 더 높은 성능 추출

  • Bagging(Bootstrap Aggregating)에 의해서 분산이 줄어든다.
  • Boosting에 의해서 편향이 줄어든다.

📌 앙상블 학습 알고리즘 설명 - Bagging

= 훈련 샘플의 서브셋을 무작위로 추출하여 여러 개의 분류기를 독립적으로 훈련시키는 방법
- Bootstrap : 중복을 허용하는 랜덤 샘플링 방법 (=복원 추출)
ex) b개의 독립적인 훈련 세트에서 나온 결과(=예측값)을 평균하면,
--> 분산 : σ^2 / b 로 감소
--> 평균 유지
- Aggregating(다수결 원칙)
= 여러 분류기의 예측 결과를 구해 다수결의 원칙에 따라 최종 분류 결과를 결정하는 방식
- Random Forest가 대표적인 배깅 방법

🏷️Bootstrapping(복원추출)

📢 복원추출 과정

  1. 100개의 훈련 데이터에서 10개의 샘플을 뽑는다 --> Sample 1
  2. 샘플1에서 뽑아낸 10개의 데이터를 다시 원위치 (중복 허용O)
  3. 다시 100개의 데이터에서 10개를 샘플을 뽑는다 --> Sample 2
  4. 위의 과정을 반복해 총 6개의 샘플을 뽑아 6개의 결정트리 모델을 만든다 (서로 다른 데이터로 만들어진 모델이므로 6개는 다 다른 모델임)
  5. 6개의 모델 예측 결과를 다수결 투표로 결합하여 최종 예측을 도출한다.
  6. Bagging 과정을 통해 만들어진 최종 모델은 Bagging Tree로 이걸 랜덤 포레스트라고도 부른다.

🏷️ Bagging Tree 알고리즘

1단계) 훈련 데이터에서 랜덤 샘플링해 X_b, y_b를 고른다
2단계) X_b, y_b를 이용하여 IS3 알고리즘으로 결정트리 구성
3단계) B개의 트리가 만들어질 때까지 1,2단계 반복
4단계) B개의 모든 트리를 이용해 분류를 한 후, 다수결 원칙으로 투표
5단계) 편향을 유지하며 분산을 줄인다
배깅은 랜덤 샘플잉에 의해 모델 훈련을 하므로 편향(=모델의 복잡도)가 커지지 않으면서 분산을 줄일 수 있는 특징이 있음!!

🏷️ Random Forest

배깅트리 --> 랜덤포레스트로 발전

  • bootstrapping에 의한 복원추출 + 속성의 랜덤 선택 --> 독립적인 트리 구성

    📢 순수 배깅 트리 VS 랜덤포레스트

    ✔️ 배깅 트리 : 각 트리에서 전체 속성을 사용해 트리를 학습
    ✔️ 랜덤 포레스트 : 각 트리에서 전체 속성 중 일부만 속성(=피처)를 랜덤하게 선택함 --> 일반화 성능을 높임

ex) 3개의 결정 트리(Classifier 1,2,3)가 각각 서로 다른 결정 경계를 학습하고, 3개 결정 트리의 예측 결과를 다수결 투표로 결합해 최종 랜덤 포레스트 모델이 생성됨

🏷️ Random Forest 알고리즘

  • 결정 트리에 포함될 피처들을 랜덤하게 선정
    --> 매우 강한 피처가 모든 트리에 항상 포함되는 것을 막는 방법
    --> 더 랜덤하고 독립적인 트리들을 생성 가능
  • 트리 기반 모델이므로 화이트 박스 특징 유지
  • 높은 예측 성능을 보임
  • 병렬적으로 생성 가능 --> 속도가 빠름
  • 각 트리는 매우 깊게 생성됨 --> 인위적인 가지치기를 하지 않지만, 앙상블을 하면 편향,분산이 낮아진다. (각각의 결정 트리가 과적합이 되더라도, 앙상블을 하면 최종적인 랜덤 포레스트 모델은 편향, 분산이 낮음)

📌 앙상블 학습 알고리즘 설명 - Boosting

🏷️부스팅(Boosting)이란 ?

= 잘못 분류된 데이터에 더 높은 가중치를 부여해 다음 번 모델의 샘플링에 포함될 확률을 높이는 것

  • 다수의 weak learner를 훈련시켜 다수결 투표를 한다는 점은 배깅과 동일함.
  • 대표적인 모델 : AdaBoost, Gradient Boost(scikit-learn에 GBM 내장 --> 느림), XGBoost (GBM과 비슷하지만 별도로 설치, 정확도가 높은 대표적인 부스팅 모델)

🏷️Gradient Boost 알고리즘

  • Weak Learner : 랜덤 초이스보다 약간 더 나은 성능 모델 (결정트리사용)
  • 기존의 약한 학습기가 생성한 잔차(=residual error)를 감소시키는 추가 트리를 더 이상의 감소 효과가 없을 때까지 생성한다.
  • 경사하강법에 의해 손실함수(ex.MSE)를 최적화함

📢 Gradient Boost 과정

1단계) 첫 번째 트리에서는 X,y(=정답)를 입력으로 줘서 잔차 r1을 생성함
2단계) 입력을 (데이터, 이전 트리에서 생성한 잔차) --> 즉, (X,r)으로 받는다
3단계) 이전 트리에서 발생한 잔차를 다음 트리에서 보정을 하고, 잔차가 거의 0이 될 때까지 2,3단계 과정 반복
4단계) 학습을 진행할수록 오차가 줄어들고 만약 잔차가 0에 가까워졌다면, 트리들의 결괏값을 더하게 되면 Y값을 알 수 있음.

🏷️ (참고) AdaBoost (Adaptive Boosting)

= 데이터를 부스팅 하는 방법 (이 전에 잘못 분류됐던 데이터의 가중치를 더 높여서 다음엔 반드시 그 데이터가 뽑히도록 함)

  • 처음에는 굉장히 간단한 모델로 구성 (=stump)
    --> 이 전 stump에서 잘못 분류한 데이터들이 다음 샘플링에 포함되도록 가중치를 높임
  • 각 3개의 트리에서 나온 경계를 합쳐서 결정경계가 혼합된 분류기를 얻을 수 있음

📌 앙상블 학습 알고리즘 설명 - Gradient Boost 예시

ex) Gradient Boost for Regression

📌 실습) 앙상블 학습 - RandomForest & GradientBoost

✔️ RandomForest

🏷️ 라이브러리 선언

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import confusion_matrix, f1_score, accuracy_score

df = pd.read_csv("datasets/Social_Network_Ads.csv")
df.head()

🏷️ 피처 추출

X = df.iloc[:,[2,3]].values.astype("float32")
y = df.iloc[:,4].values
X.shape, y.shape
  • 실행 결과 : ((400, 2), (400,))

🏷️ 훈련/테스트셋 분리

X_train, X_test, y_train,  y_test = train_test_split(X, y , test_size = 0.2, random_state = 0)
X_train.shape, X_test.shape , y_train.shape, y_test.shape
  • 실행 결과 : ((320, 2), (80, 2), (320,), (80,))

🏷️ 피처 스케일링

sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)

🏷️ rf 객체 생성, 모델 훈련

⚠️n_estimators : 나무를 몇 개를 만들건지 설정하는 파라미터

#랜덤 포레스트는 랜덤이니깐 random_state을 맞춰준다. 
rf = RandomForestClassifier(n_estimators = 10, random_state = 0) 

rf.fit(X_train, y_train)

🏷️ 결과 예측

y_pred = rf.predict(X_test)

accuracy_score(y_test, y_pred) # 정확도 92%

✔️ Gradient Boost

앞 과정은 랜덤 포레스트와 동일

🏷️ gb 객체 생성, 모델 훈련

⚠️ min_samples_split : node 분리에 필요한 최소 sample 수 => overfitting 방지
⚠️ max_depth : tree 깊이 조절 => overfitting 방지
⚠️ learning_rate : 각 tree 의 기여도 조정, n_estimators 와 trade-off

from sklearn.ensemble import GradientBoostingClassifier
gb = GradientBoostingClassifier(learning_rate = 0.1, n_estimators = 500, max_depth = 5)
gb.fit(X_train, y_train)

🏷️ 결과 예측

y_pred = gb.predict(X_test)
accuracy_score(y_test, y_pred)

✔️ 시각화

🏷️ cmap 생성

from matplotlib.colors import ListedColormap
# 진한 빨강색, 진한 초록색
cmap_bold = ListedColormap(['#FF0000','#00FF00']) # '#'이라는 건 16진수를 의미. FF00-->그러면 레드가 멕시멈이고 
# RGB 그린,블루는 0 이런걸 하나 놓고, 두 번째로는 그린을 최대로 놓고, 빨강,파란을 00으로 설정
# 연한 빨강색, 연한 초록색
cmap_light = ListedColormap(['#FFAAAA','#AAFFAA']) # 빨강을 제외하고 AA를 해주면 연한 붉은색이 나옴.  

🏷️ X축, Y축 최소,최대 범위 설정

  • `X_test[:, 0] : X_test의 첫 번째 특성(열)
  • X_test[:, 1] : X_test의 두 번째 특성(열)
    ⚠️ 각 특징의 최소,최대를 계산 후, 범위를 넓혀서 시각화를 해주기 위해 각각 1을 빼고, 더한다
x1_min, x1_max = X_test[:, 0].min() - 1, X_test[:, 0].max() + 1       
x2_min, x2_max = X_test[:, 1].min() - 1, X_test[:, 1].max() + 1  

🏷️ meshgrid로 가상 데이터 X1,X2 생성

⚠️np.arange(x1_min, x1_max, 0.1) : x1_min ~ x1_max까지 0.1 간격으로 숫자 생성
⚠️np.meshgrid( , ) : 괄호 안의 숫자들을 모두 조합하여 평면에 격자 모양의 좌표 생성

X1, X2 = np.meshgrid(np.arange(x1_min, x1_max, 0.1), 
                     np.arange(x2_min, x2_max, 0.1))

🏷️ 2차원 데이터을 1차원으로 펼쳐주기

⚠️ .ravel() : 2차원 배열을 1차원으로 펼쳐줌

X1.ravel()
X2.ravel()

🏷️ X1,X2를 결합해 모델에 입력할 데이터 XX 만들기

⚠️ np.column_stack : 1차원으로 바뀐 X1,X2를 열 단위로 결합해, 각 행이 하나의 죄표쌍을 갖는 2차원 배열 XX를 생성 --> 모델에 입력할 데이터

XX = np.column_stack([X1.ravel(), X2.ravel()])

🏷️ 모델 예측 수행

XX에 대해 예측한 클래스 0,1(=구매 여부)를 반환

Y_rf = np.array(rf.predict(XX))
Y_gb = np.array(gb.predict(XX))

🏷️ OOP 형식으로 시각화 해주기

⚠️ 점들은 데이터 포인트로, 모델이 학습한 데이터.
⚠️ 모델 예측을 통해 만들어진 결정 경계(=색깔로 구분)가 실제 데이터 포인트를 잘 구분했는지 시각화

// 하나의 행에 두 개의 열,양옆에 두 개를 그리니깐 OP 형식으로 시각화하기
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4), sharey=True)

# Random Forest
# x축, y축, 색깔까지 총 3차원으로 줄거임!
ax1.pcolormesh(X1, X2, Y_rf.reshape(X1.shape), cmap=cmap_light, shading='auto') 
# 실제 우리 데이터가 여기 어디에 속하는지 그려보자. 
for i in range(2):
    ax1.scatter(X_test[y_test == i, 0], X_test[y_test == i,1], color=cmap_bold(i), label=i, s = 30, edgecolor='k')
ax1.set_title("Random Forest")
ax1.legend()
// 생성된 결정경계를 보고 이제 수정을 할 수 있음 --> 나무를 좀 고쳐서 데이터가 잘 분류될 수 있도록

# Gradient Boost
ax2.pcolormesh(X1, X2, Y_gb.reshape(X1.shape), cmap=cmap_light, shading='auto')
for i in range(2):
    ax2.scatter(X_test[y_test == i, 0], X_test[y_test == i,1], color=cmap_bold(i), label=i, s = 30, edgecolor='k')
ax2.set_title("Gradient Boost")  // 이거 두개로 예측한 걸 시각화해서 비교해보기 
ax2.legend()
  • 완전히 일치하지 않음
  • 랜덤 포레스트, Gradient Boost 모델의 결정 경계가 다름

🏷️ 피처 중요도 시각화

gb.feature_importances_ # 둘 다 중요도가 비슷하게 나옴 -> 둘다 중요 
feature_imp = pd.Series(gb.feature_importances_, ['Age','Estimated Salary']) # 두번째 매개변수는 인덱스를 준다.
feature_imp

feature_imp.plot(kind='bar',title='Feature importance')

📌 Feature Engineering

🏷️ 좋은 피처의 조건

  • 정답과 높은 관련성 O
  • 예측하는 시점에 알 수 있어야한다(아직 발생하지 않은 데이터로 훈련X)
  • 반드시 숫자로 이뤄진 데이터여야함
  • 샘플 수가 충분해야함
  • 전문가의 도메인 지식도 활용 가능

🏷️ 머신러닝을 위한 피처 엔지니어링

  • 결측치 처리

  • 데이터 포맷팅(=형식 통일)

  • 편향된 데이터 처리 --> 데이터가 균일해야 좋은 성능 발휘

  • 데이터 정규화(=피처 스케일링)

  • Binning(=구간화)

  • 카테고리 변수의 수치화

🏷️ 카테고리 변수의 수치화

⭐ 카테고리 피처는 반드시 숫자로 변환해줘야함!
1. ordinal 카테고리 (순서/크기 O)
--> 숫자로 크기(순서) 표시
ex) L > M > S --> 3,2,1
2. nominal 카테고리 (순서/크기가 X --> 보통 이게 더 많음)
--> 원-핫 인코딩 (칼럼을 분리해서 0,1로 표기)

ex) 같은 칼럼에 존재했던 경유,휘발유의 칼럼을 분리한 후, 해당하면 1, 해당하지 않으면 0으로 표시

📌 실습) Feature Engineering - Titanic 생존 예측

📢 데이터셋 설명

= Titanic호 data 를 이용한 Feature Engineering 과 Modeling

  • Pclass - Passenger Class (1 = 1st; 2 = 2nd; 3 = 3rd) 객실 등급
  • survival - 생존 여부 (0 = 사망; 1 = 생존) --> 지도학습의 정답 데이터, 레이블
  • name - 이름, sex - 성별 , age - 나이
  • sibsp - 함께 탑승한 형제 또는 배우자 수
  • parch - 함께 탑승한 부모 또는 자녀 수
  • ticket - 티켓 번호 , fare - Passenger Fare (British pound) , cabin - 선실번호
  • embarked - 탑승한 항구(얼마나 부유한지와 관련) --> C = Cherbourg; Q = Queenstown; S = Southampton

🏷️ 라이브러리 선언, 데이터셋 로드

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

df = pd.read_csv("datasets/titanic.csv")
df.head()

🏷️ 칼럼 삭제

⚠️ 정답과 연관성이 낮은 PassengerId, Name, Ticket, Cabin 칼럼 삭제 --> 노이즈 제거

df.columns # column명 확인
df.drop(['PassengerId','Name', 'Ticket', 'Cabin'],axis=1, inplace=True) # 실제로 pd에서 날려버림
df.head() # 노이즈, 필요없는 데이터 칼럼을 삭제함, 정답과 무관한 칼럼들은 없애주는게 좋은

🏷️ 데이터프레임 정보 확인

df.info()
df.isnull() // null인 것은 true, 아닌 것은 false으로 나옴
df.isnull().sum() // 결측치의 갯수
df.describe() // 데이터프레임의 기술 통계 --> 평균, 최대/최소..

df.isnull().sum()

🏷️ 피처 분석(시각화)

⚠️ Survived(=정답 데이터)와 피처 간의 상관관계 파악하는 단계
df.corr(numeric_only=True)

  • survived과 가장 높은 관계가 있는 건 Fare(25%의 관계가 있음)

import seaborn as sns
sns.heatmap(df.corr(numeric_only=True),annot = True, cmap = 'coolwarm')
# 대각선이 가장 높은 이유는 --> 자기 자신이 자기 자신이랑 젤 연관 높으니깐
# Fare하고 Pclass은 아주 강한 역의 관계가 있음
# 1,2,3등석이니깐 Pclass 숫자가 클수록 Fare이랑 역의 관계가 있음
# 그래서 Fare가 비싸질수록 pClass는 숫자가 내려감.
  • 가장 상관 관계가 높은 feature 는 Fare 이고 Pclass 는 가장 상관관계가 낮음

🏷️ 결측치 처리

⚠️ 결측치 177개 age는 중앙값으로 대체 --> 다 삭제하기엔 데이터 손실이 큼
⚠️ Embarked 결측치 2개는 그냥 삭제

df.isnull().sum() # 결측치 확인 
df['Age'].fillna(df['Age'].median(), inplace = True)
df.dropna(inplace = True)
df.isnull().sum()
  • 다 0개 --> 결측치 처리 완료

🏷️ 치우친 데이터 확인

⚠️ pandas에는 matplotlib이 내장되어 있음
⚠️ 로그 값을 취하기 전) Fare 데이터가 치우친 분포를 가짐

df.hist(bins = 30, figsize = (8,8))
plt.show()

⚠️ 로그 값을 취한 후) 대소관계가 유지된 상태로 치우침을 완화 --> 가운데로 정렬됨 & 칼럼의 특성은 바뀌지 X

 # 로그를 취한 값으로 Fare을 적용해준다. 
df['Fare'] = df['Fare'].map(lambda x: np.log(x) if x > 0 else 0) 

df.hist(bins = 30, figsize = (8,8))
plt.show()

🏷️ 카테고리 변수 처리

⚠️pd.get_dummies(df) : 카테고리인 것들만 분리해서 데이터 프레임을 전부 숫자형으로 변형함.

  • 원-핫 인코딩 전) 성별,Embarked 칼럼은 숫자형으로 되어 있지 X
df.head()

  • 원-핫 인코딩 후)
df = pd.get_dummies(df)
df.head()

🏷️ 훈련/테스트셋 분리

df.shape # (889, 11)

y = df['Survived'].values # 정답 데이터 
X = df.drop('Survived', axis = 1).values
X.shape, y.shape # 10개의 피처로 이뤄진 훈련 데이터, 1개의 피처로 이뤄진 정답 데이터 survived 
  • 실행결과 : ((889, 10), (889,))
    --> 피처(10개)랑 정답(1개) 분리
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2, random_state = 0)
X_train.shape, X_test.shape, y_train.shape, y_test.shape
  • 실행결과 : ((711, 10), (178, 10), (711,), (178,))

🏷️ 피처 스케일링

from sklearn.preprocessing import StandardScaler

sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test) # fit 하면 안됨

🏷️ 모델링 (모델훈련/예측)

  • 모델 훈련
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score

rf = RandomForestClassifier(n_estimators = 10, random_state= 0, criterion = 'entropy')
rf.fit(X_train, y_train) # 모델 학습 완료, fit

  • 모델 예측
y_pred = rf.predict(X_test)

accuracy_score(y_test,y_pred) # 정확도 76%
profile
개발 & 공부 기록

0개의 댓글