반응형

0. 개요

- 타이타닉 사건: 타이타닉은 역사상 가장 유명한 해상 사고 중 하나로, 1912년 4월 15일에 발생한 비극적인 사건

- 타이타닉 데이터셋은 머신 러닝과 데이터 분석 분야에서 많이 활용되는 이유는 여러 가지가 있습니다. 이해하기 쉬운 구조와 다양한 특성들로 구성되어 있어 머신 러닝의 기본 개념을 학습하고 모델을 구축하는 데 사용하기에 적합합니다.  타이타닉 데이터셋은 생존 여부를 예측하는 이진 분류 문제로도 활용되고, 승객의 나이나 운임 등을 예측하는 회귀 문제로도 활용될 수 있습니다. 이로 인해 다양한 머신 러닝 알고리즘과 기법을 연습할 수 있습니다. 이러한 이유들로 인해 타이타닉 데이터셋은 머신 러닝과 데이터 분석의 입문자부터 전문가까지 다양한 수준의 사람들에게 인기있는 연습 및 학습용 데이터셋 중 하나로 널리 사용되고 있습니다. 

 

1. 파이썬 코드

#라이브러리 불러오기
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score

#데이터 불러오기
titanic_data = pd.read_csv('titanic.csv')

#필요한 열값만 선택
features = ['Survived', 'Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked']

#결측치 처리 및 범주형 데이터 변환
titanic_data = titanic_data[features].dropna()
titanic_data['Sex'] = titanic_data['Sex'].map({'male': 0, 'female': 1})
titanic_data['Embarked'] = titanic_data['Embarked'].map({'S': 0, 'C': 1, 'Q': 2})

#X값 Y값 정의 
X = titanic_data.drop('Survived', axis=1)
y = titanic_data['Survived']

# 데이터 분할
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 머신러닝 모델 - 랜덤포레스트 생성 및 학습
model = RandomForestClassifier(random_state=42)
model.fit(X_train, y_train)

# 테스트 데이터에 대한 예측
y_pred = model.predict(X_test)

# 정확도 평가
accuracy = accuracy_score(y_test, y_pred)
print(f'Accuracy: {accuracy:.2f}')

 

2. 탐색적 데이터 분석(EDA)

1) 데이터가 어떻게 생겼는지 확인

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# 데이터 불러오기
titanic_data = pd.read_csv('titanic.csv')

# 데이터의 일부를 살펴봅니다.
titanic_data.head()

 

대부분의 칼럼값은 이름만 봐도 쉽게 알 수 있다. 가장 중요한 survived는 생존 유무인데 1이 생존이다.  sibsp 형제 혹은 부부의 수이고 parch는 부모 혹은 자녀의 수이다.

 

2) 생존자와 사망자의 수 확인

sns.countplot(x='Survived', data=titanic_data)
plt.title('Survivors vs. Non-Survivors')
plt.show()

 

 

3) 성별에 따른 생존 여부 확인

sns.countplot(x='Survived', hue='Sex', data=titanic_data)
plt.title('Survivors and Non-Survivors by Sex')
plt.show()

 

 

4) 나이 분포 확인

sns.histplot(data=titanic_data, x='Age', bins=20, kde=True)
plt.title('Age Distribution')
plt.show()

3. 머신러닝 - 랜덤포레스트(Random Forest)

이번 모델링에서는 랜덤 포레스트를 활용하였습니다. 랜덤 포레스트는 머신 러닝 알고리즘 중 하나로, 앙상블 학습 방법 중의 하나입니다. 앙상블 학습은 여러 개의 간단한 모델을 결합하여 더 강력하고 안정적인 모델을 만드는 기법으로, 랜덤 포레스트는 이 중에서 대표적인 알고리즘입니다. 

 

랜덤 포레스트는 마치 여러 명의 전문가들이 함께 의사 결정을 내리는 것과 비슷합니다. 각 전문가는 다른 정보를 가지고 있고, 각자의 의견을 내놓습니다. 그런 다음, 모든 의견을 모아서 가장 현명한 결정을 내리는 방식입니다.

 

랜덤 포레스트는 컴퓨터에게 이런 방식을 가르쳐서 데이터를 예측하게 만든 것입니다. 데이터를 여러 조각으로 나누어서 작은 모델들이 각각 조각을 예측하도록 합니다. 그리고 이 작은 모델들의 의견을 모아서 예측 결과를 만들어 내죠. 이렇게 함으로써 하나의 모델보다 더 똑똑하고 정확한 예측을 할 수 있답니다. 그리고 랜덤 포레스트는 모델이 예측을 할 때, 일부 정보만을 사용하게 됩니다. 마치 몇몇 정보만 보고 결정을 내리는 것처럼요. 이렇게 함으로써 각각의 작은 모델이 더 다양한 측면을 보게 되고, 전체적으로 더 좋은 예측을 할 수 있게 되는 것이죠. 랜덤 포레스트는 간단하게 말하면 다양한 의견을 모아서 더 현명한 결정을 내리는 방법이라고 생각하시면 됩니다. 이렇게 하면 데이터 예측이 더 정확해지고 안정적으로 작동하게 되는 거죠!

 

4. 머신러닝과 예측분석

처음 머신러닝을 공부할 때 결과값 0.78만 나오고 이게 뭔가? 하였다. 결국은 내가 만든 모델을 가지고 평가를 해야하고 랜덤포레스트가 최적의 선택이었는지, 또 테스트 사이즈가 20%로 설정되었는데 이 보다 더 나은 방법은 없는지도 고민해봐야 한다. 

 

그리고 이번 데이터 분석 결과가 0.78이라고 나왔는데, 실제 데이터 셋에서 그러니까 y값 survived가 없는 상태에서 데이터를 인풋 하였을 때, 그러니까 성별, 연령,함께 탄 가족 수, 좌석 등급 등 x값을 넣었을 때 얼마나 정확하게 survived 생존여부를 예측할 수냐!를 활용하는 것이 관건일 것이다.

titanic.csv
0.06MB

반응형
Posted by 마르띤
,
반응형

회귀앙상블 - 랜덤포레스트(링크) 

분류앙상블 – 배깅, 부스팅, 랜덤 포레스트



 1) 데이터 입력

> setwd('c:/Rwork')

> german=read.table('germandata.txt',header=T)

> german$numcredits = factor(german$numcredits)

> german$residence = factor(german$residence)

> german$residpeople = factor(german$residpeople)

 

 

2) 랜덤 포레스트 방법의 실행

> library(randomForest)

> rf.german<-randomForest(y~.,data=german,ntree=100,mytr=5,importance=T,na.action = na.omit)

> summary(rf.german)

Length Class  Mode    

call               7   -none- call    

type               1   -none- character

predicted       1000   factor numeric 

err.rate         300   -none- numeric 

confusion          6   -none- numeric 

votes           2000   matrix numeric 

oob.times       1000   -none- numeric 

classes            2   -none- character

importance        80   -none- numeric 

importanceSD      60   -none- numeric 

localImportance    0   -none- NULL    

proximity          0   -none- NULL    

ntree              1   -none- numeric 

mtry               1   -none- numeric 

forest            14   -none- list    

y               1000   factor numeric 

test               0   -none- NULL    

inbag              0   -none- NULL    

terms              3   terms  call

 

함수 설명:

randomForest(y~.,data=german,ntree=100,mytr=5,importance=T,na.action = na.omit ntree는 랜덤포레스트 방법에서 생성하게 될 분류기의 개수 B이다. 100개의 분류기는 분류나무를 이용하여 생성되도록 하였다. mtry는 중간노드마다 랜덤하게 선택되는 변수의 개수를 의미한다. 5개의 입력변수를 중간노드마다 모두 선택하고 이 중에서 분할점이 탐색되도록 하였다. importance는 변수의 중요도를 계산하는 옵션이고, na.action은 결측치를 처리하는 방법에 대한 사항이다. 변수의 중요도를 계산하게 하고, 결측치는 필요한 경우에만 삭제되도락 하였다.

 

 

2) 랜덤 포레스트 방법의 실행 변수 중요도 보기

> names(rf.german)

[1] "call"            "type"            "predicted"       "err.rate"        "confusion"     

[6] "votes"           "oob.times"       "classes"         "importance"      "importanceSD"  

[11] "localImportance" "proximity"       "ntree"           "mtry"            "forest"        

[16] "y"               "test"            "inbag"           "terms"         


> head(rf.german$predicted,10) #데이터의 예측집단을 출력

1    2    3    4    5    6    7    8    9   10

good  bad good  bad  bad good good good good  bad

Levels: bad good


> importance(rf.german)

bad        good MeanDecreaseAccuracy MeanDecreaseGini

check       13.14268724  9.63208341         15.1106884       44.838547

duration     3.33563217  8.10482760          8.6281030        41.273512

history      3.87863720  4.50449203            5.8685013        25.731461

purpose      2.67025503  3.09871408            4.1078354        35.651165

credit       2.44312087  4.16670498            4.8800356        52.641745

savings      7.48182326  2.84190645            6.1879918        21.705909

employment   1.91049595  2.70568977            3.2416484        23.910509

installment  0.02100147  3.49542966            3.0522029        15.714499

personal     2.10802207  1.83819513            3.0602966        15.365475

debtors     -0.17277289  4.39384503            3.8963219         6.718969

residence    0.74571096  0.90284661            1.1155901        17.932937

property     2.16016716  3.85454658            4.7010080        18.803008

age          2.69637542  4.35170316            5.4753585        41.451103

others       0.31569112  3.60499256            3.3679530        11.399935

housing      2.70314243  2.06074416            3.0737900         9.596539

numcredits  -0.24996827  0.95259106            0.6502566         7.944861

job          1.53070574  1.18486660            2.1420488        12.054190

residpeople  0.88657814 -0.43166449            0.1370845         4.234831

telephone    1.46824003 -0.24200291            0.6110284         6.427048

foreign      1.26297478 -0.05431566            0.5733125         1.519832


> importance(rf.german,type=1)

MeanDecreaseAccuracy

check                 15.1106884

duration               8.6281030

history                5.8685013

purpose                4.1078354

credit                 4.8800356

savings                6.1879918

employment             3.2416484

installment            3.0522029

personal               3.0602966

debtors                3.8963219

residence              1.1155901

property               4.7010080

age                    5.4753585

others                 3.3679530

housing                3.0737900

numcredits             0.6502566

job                    2.1420488

residpeople            0.1370845

telephone              0.6110284

foreign                0.5733125

 

결과 해석: check 가장 중요하고 duration 두번째로 중요

 


> order(importance(rf.german)[,'MeanDecreaseAccuracy'],decreasing = T)

[1]  1  2  6  3 13  5 12  4 10 14  7 15  9  8 17 11 16 19 20 18


> which.max(importance(rf.german)[,'MeanDecreaseAccuracy'])

check

1


> importance(rf.german)[which.max(importance(rf.german)[,'MeanDecreaseAccuracy']),]

bad                 good     MeanDecreaseAccuracy     MeanDecreaseGini

13.142687             9.632083                15.110688            44.838547


> rf.german$importance

bad          good MeanDecreaseAccuracy MeanDecreaseGini

check        5.728619e-02  2.488337e-02         3.461467e-02        44.838547

duration     1.262784e-02  2.059686e-02         1.820397e-02        41.273512

history      1.165482e-02  8.234252e-03         9.100115e-03        25.731461

purpose      1.001589e-02  5.877403e-03         7.125436e-03        35.651165

credit       8.957835e-03  9.469900e-03         9.342178e-03        52.641745

savings      1.873739e-02  4.572813e-03         8.795598e-03        21.705909

employment   5.377379e-03  4.391391e-03         4.647218e-03        23.910509

installment  5.083834e-05  4.492258e-03         3.109720e-03        15.714499

personal     4.903039e-03  2.481005e-03         3.188303e-03        15.365475

debtors     -1.380717e-04  3.198633e-03         2.202015e-03         6.718969

residence    1.833243e-03  1.342976e-03         1.400876e-03        17.932937

property     6.357328e-03  5.871030e-03         6.069060e-03        18.803008

age          1.026633e-02  8.969565e-03         9.239623e-03        41.451103

others       6.321219e-04  4.940365e-03         3.562374e-03        11.399935

housing      5.086080e-03  2.740150e-03         3.358222e-03         9.596539

numcredits  -3.793953e-04  7.653351e-04         4.256327e-04         7.944861

job          2.803065e-03  1.422938e-03         1.912685e-03        12.054190

residpeople  9.171770e-04 -2.801992e-04         7.286163e-05         4.234831

telephone    2.173474e-03 -2.108124e-04         4.743466e-04         6.427048

foreign      5.935867e-04 -1.538455e-05         1.547421e-04         1.519832

 

추가:

rf.german$importance #이건 importance(rf.german) 결과와 어떻게 다른지 공부하자

 

 

3) 분류예측치를 구하고 정확도 평가

> pred.rf.german<-predict(rf.german,newdata=german)

> head(pred.rf.german,10)

  1    2    3    4    5    6    7    8    9   10

  good  bad good good  bad good good good good  bad

  Levels: bad good

> tab=table(german$y,pred.rf.german,dnn=c("Actual","Predicted"))

> tab

        Predicted

  Actual  bad   good

    bad    300    0

 good   0      700

> addmargins(tab)

  Predicted

  Actual  bad  good  Sum

  bad   300   0      300

  good  0      700  700

  Sum   300  700  1000

> 1-sum(diag(tab)/sum(tab))

  [1] 0

결과 해석기존 cart 분류나무 모형 오분류율은 19.6%, 배깅은 3.7%, 부스팅은 22.6%인 반면

랜덤 포레스트는 오분류율이 0%로 기존 그 어떠한 모형보다 대단히 우수한 결과를 보임을 알 수 있다


(분류나무 cart 모형 바로가기) / (분류앙상블 모형 – 배깅 바로가기) / (분류앙상블 모형 – 부스팅 바로가기)

 

4) 몇개의 분류기가 적당할까?

> plot(rf.german,'l')


 

결과 해석: x축은 분류기, y축은 OOB 오분류율을 의미 out of bag 약자로 부트스트랩에 포함되지 못한 데이터를 의미. 결국 oob데이터는 검증데이터의 역할과 비슷. 가장 아래선은 목표변수 good 대한 오분율, 가장 위쪽 선은 bad 대한 오분율. 가운데는 전체 오분류율. 그림에 따르면 분류기 개수가 80개이상이면 안정적인 형태로 보인다

 

 

5) 훈련 데이터와 검증데이터로 분할하여 랜덤포레스트 방법을 평가해 보자.

> set.seed(1234)

> i=sample(1:nrow(german),round(nrow(german)*0.7)) #70% for training 훈련 data, 30% test 검증 데이

> german.train = german[i,]

> german.test = german[-i,]

> rf.train.german<-randomForest(y~.,data=german.train,ntree=100,mtry=5,importance=T,na.action = na.omit)

> pred.rf.train.german<-predict(rf.train.german,newdata=german.test)

> tab.train = table(german.test$y,pred.rf.train.german,dnn=c('Actual','Predicted'))

> tab.train

Predicted

Actual bad good

bad   39   60

good  15  186


addmargins(tab.train)

Predicted

Actual   bad  good Sum

bad    39   60     99

good  15   186    201

Sum   54   246    300


> 1-sum(diag(tab.train) / sum(tab.train)) #오분류율이 25% 어느정도 향상

[1] 0.25

 

결과 해석: 검증데이터에 대한 오분류율은 기존 cart 분류 나무는 26.3%, 배깅 역시 26.3%, 부스팅은 25.3%. 랜덤포레스트는 25%, 조금 향상 되었음.


(분류나무 cart 모형 바로가기) / (분류앙상블 모형 – 배깅 바로가기) / (분류앙상블 모형 부스팅 바로가기)


출처: 데이터마이닝(장영재, 김현중, 조형준 공저) 

반응형
Posted by 마르띤
,