[데이터마이닝]

패키지

설치된 패키지 접기/펼치기 버튼
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from pandas.plotting import scatter_matrix
%matplotlib inline
# %matplotlib notebook
import sklearn
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import VotingClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.neural_network import MLPClassifier
from sklearn.metrics import confusion_matrix
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
dataset = pd.read_csv('C:/Users/KimJaeHyuk/데이터마이닝 코드자료 - 복사본/dataset.csv')
dataset
PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarked
0103Braund, Mr. Owen Harrismale22.010A/5 211717.2500NaNS
1211Cumings, Mrs. John Bradley (Florence Briggs Th...female38.010PC 1759971.2833C85C
2313Heikkinen, Miss. Lainafemale26.000STON/O2. 31012827.9250NaNS
3411Futrelle, Mrs. Jacques Heath (Lily May Peel)female35.01011380353.1000C123S
4503Allen, Mr. William Henrymale35.0003734508.0500NaNS
.......................................
88688702Montvila, Rev. Juozasmale27.00021153613.0000NaNS
88788811Graham, Miss. Margaret Edithfemale19.00011205330.0000B42S
88888903Johnston, Miss. Catherine Helen "Carrie"femaleNaN12W./C. 660723.4500NaNS
88989011Behr, Mr. Karl Howellmale26.00011136930.0000C148C
89089103Dooley, Mr. Patrickmale32.0003703767.7500NaNQ

891 rows × 12 columns

데이터셋 설명

  • PassengerID : 단순한 일련번호

  • Survived : 생존여부(0 : 죽음, 1 : 생존) ◀ 반응변수(y)

  • Pclass :티켓 등급 (1등석, 2등석, 3등석 등)

  • Name : 이름

  • Sex : 성별

  • Age : 나이

  • SibSp : 동승한 형제자매, 배우자의 수

  • Parch : 동승한 부모, 자식의 수

  • Ticket : 티켓 번호

  • Fare : 운임

  • Cabin : 객실번호

  • Embarked : 탑승항구

    (C: Cherbourg, Q: Queenstown, S: Southampton)

Information

dataset.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

Age, Cabin, Embarked 결측치가 존재한다.

dataset.shape
(891, 12)
description = dataset.describe()
pd.set_option('display.width', 100)  # 결과물을 잘 보여주기 위한 옵션
pd.set_option('precision', 3)        # 결과물을 잘 보여주기 위한 옵션
description
PassengerIdSurvivedPclassAgeSibSpParchFare
count891.000891.000891.000714.000891.000891.000891.000
mean446.0000.3842.30929.6990.5230.38232.204
std257.3540.4870.83614.5261.1030.80649.693
min1.0000.0001.0000.4200.0000.0000.000
25%223.5000.0002.00020.1250.0000.0007.910
50%446.0000.0003.00028.0000.0000.00014.454
75%668.5001.0003.00038.0001.0000.00031.000
max891.0001.0003.00080.0008.0006.000512.329

PassengerId는 분석으로는 활용성이 없을 듯 보아 인덱스로 사용할 예정이다.

Fare은 다른 feature들 보다 상대적으로 큰 값을 보이고 있다.

dataset['Survived'].value_counts()
0    549
1    342
Name: Survived, dtype: int64

ㄴ 891명 중 549명이 사망, 342명이 생존인 것을 알 수 있다.

plt.style.use('ggplot')
sns.set()
sns.set_palette("Set2")

plt.rc('font', size=15)
plt.rc('axes', titlesize=15)
plt.rc('axes', labelsize=15)
plt.rc('xtick', labelsize=15) 
plt.rc('ytick', labelsize=15) 
plt.rc('legend', fontsize=9)
plt.rc('figure', titlesize=15)
plt.rcParams['figure.figsize'] = (10, 10)
plt.rcParams['font.size'] = 10
dataset.hist()
plt.show()

dataset.plot(kind = 'density', subplots = True, layout = (3,3), sharex = False)
plt.show()

plt.rcParams['font.size'] = 15
dataset.plot(kind = 'box', subplots = True, layout = (3,3), sharex = False, sharey=False)
plt.show()

  • PassengerId는 자료로써 의미가 없어 보이고

  • Survived는 사망자가 생존자보다 많다는 것을 확인할 수 있다.

  • Pclass는 등급이 낮아질 수록 인원수가 많은 것을 볼 수 있는데 등급별 사망인원 파악도 중요해 보인다.

  • Age는 젊은 층이 많아 보인다.

  • SibSp,Parch를 확인하듯 동승자는 그렇게 많아 보이지 않는다.

  • Fare은 3등급의 사람이 압도적으로 많아서 그런지 운임이 저렴한대에 몰려있다.

def bar_chart(dataset, feature):
    survived = dataset[dataset['Survived'] == 1][feature].value_counts()
    dead = dataset[dataset['Survived'] == 0][feature].value_counts()
    df = pd.DataFrame([survived, dead])
    df.index = ['Survived', 'Dead']
    df.plot(kind='bar', stacked=True)
    plt.title("{}".format(feature))
    plt.xticks(rotation = 0)
plt.rc('font', size=20)
plt.rc('axes', titlesize=20)
plt.rc('axes', labelsize=20)
plt.rc('xtick', labelsize=20) 
plt.rc('ytick', labelsize=20) 
plt.rc('legend', fontsize=20)
plt.rc('figure', titlesize=20)
bar_chart(dataset, 'Pclass')

1등석에 있던 승객들은 오히려 사망한 사람보다 생존한 사람이 많고,

2등석은 대략 생존율이 50%정도 되는 것 같다.

반면 3등석은 생존한 사람보다 사망한 사람이 훨씬 많다.

자료를 보았을 때 Pclass라는 특성은 승객의 생사를 예측하는 데에 큰 영향을 끼친다는 것을 확인할 수 있다.

bar_chart(dataset, 'Sex')

성별에 따른 분류이다.

여성은 생존률이 매우 높은 반면, 남성은 사망한 사람이 훨씬 많다는 것을 관측할 수 있다.

사고 당시에 남성보다는 여성을 우선적으로 살린 것으로 보인다.

bar_chart(dataset, 'SibSp')

이 그래프는 자매와 배우자의 수에 따른 그래프이다.

SibSp 값이 3 이상부터는 잘 보이지 않아서 추가적인 확인이 필요할 것 같다.

dataset_Sibsp_2 = dataset[(dataset['SibSp'] > 2)]
bar_chart(dataset_Sibsp_2, 'SibSp')

SibSp 값이 3 이상인 사람들은 생존율이 높지 않다는 것을 확인할 수 있다.

bar_chart(dataset, 'Embarked')

지역별로 부유한 도시와 가난한 도시가 있을수도 있을 것 같다.

탑승지별로 1등석, 2등석, 3등석의 수를 비교해 봐야겠다.

S = dataset[dataset['Embarked'] == 'S']['Pclass'].value_counts()
C = dataset[dataset['Embarked'] == 'C']['Pclass'].value_counts()
Q = dataset[dataset['Embarked'] == 'Q']['Pclass'].value_counts()
df = pd.DataFrame([S, C, Q])
df.index = ['S', 'C', 'Q']
df.plot(kind='bar', stacked=True)
plt.title("Embarked")
plt.xticks(rotation = 0)
# C: Cherbourg, Q: Queenstown, S: Southampton
(array([0, 1, 2]), [Text(0, 0, 'S'), Text(1, 0, 'C'), Text(2, 0, 'Q')])

1등석의 비율이 탑승지별로 다른 것을 확인할 수 있다.

Embarked가 C인 사람들은 1등석 비율이 거의 절반에 육박한다.

이는 전 그래프에서 탑승지가 C였던 사람들의 생존률이 거의 50퍼센트에 가깝게 나왔다는 것에 큰 영향이 있을 것 같다. Sex

의 문자열 자료를 숫자로 변환하여 dataset_2에 저장한다.

  1. male

  2. female

dataset_2 = dataset.copy()
dic = {"male": 0, "female": 1}
dataset_2['Sex'] = dataset_2['Sex'].map(dic)
dataset_2
PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarked
0103Braund, Mr. Owen Harris022.010A/5 211717.250NaNS
1211Cumings, Mrs. John Bradley (Florence Briggs Th...138.010PC 1759971.283C85C
2313Heikkinen, Miss. Laina126.000STON/O2. 31012827.925NaNS
3411Futrelle, Mrs. Jacques Heath (Lily May Peel)135.01011380353.100C123S
4503Allen, Mr. William Henry035.0003734508.050NaNS
.......................................
88688702Montvila, Rev. Juozas027.00021153613.000NaNS
88788811Graham, Miss. Margaret Edith119.00011205330.000B42S
88888903Johnston, Miss. Catherine Helen "Carrie"1NaN12W./C. 660723.450NaNS
88989011Behr, Mr. Karl Howell026.00011136930.000C148C
89089103Dooley, Mr. Patrick032.0003703767.750NaNQ

891 rows × 12 columns

dataset_2에서 Age의 결측값을 Age의 중앙값으로 대체하여 dataset_2에 저장한다.

(평균과 중앙값의 큰 차이가 없기 때문에 평균을 사용하여 소수점자리수를 만드는 것보다 중앙값을 사용하였다.)

dataset_2['Age'].describe()
count    714.000
mean      29.699
std       14.526
min        0.420
25%       20.125
50%       28.000
75%       38.000
max       80.000
Name: Age, dtype: float64
dataset_2["Age"].fillna(dataset_2["Age"].median(),inplace=True)
dataset_2.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    int64  
 5   Age          891 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(6), object(4)
memory usage: 83.7+ KB
dataset_2
PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarked
0103Braund, Mr. Owen Harris022.010A/5 211717.250NaNS
1211Cumings, Mrs. John Bradley (Florence Briggs Th...138.010PC 1759971.283C85C
2313Heikkinen, Miss. Laina126.000STON/O2. 31012827.925NaNS
3411Futrelle, Mrs. Jacques Heath (Lily May Peel)135.01011380353.100C123S
4503Allen, Mr. William Henry035.0003734508.050NaNS
.......................................
88688702Montvila, Rev. Juozas027.00021153613.000NaNS
88788811Graham, Miss. Margaret Edith119.00011205330.000B42S
88888903Johnston, Miss. Catherine Helen "Carrie"128.012W./C. 660723.450NaNS
88989011Behr, Mr. Karl Howell026.00011136930.000C148C
89089103Dooley, Mr. Patrick032.0003703767.750NaNQ

891 rows × 12 columns

Age's

feature 추가

  • 0: 미성년 (15세 이하)

  • 1: 청년 (16세 이상, 30세 이하)

  • 2: 중년 (31세 이상, 45세 이하)

  • 3: 장년 (46세 이상, 60세 이하)

  • 4: 노년 (61세 이상)

dataset_2.loc[dataset_2["Age"]<=15,"Age's"] = 0
dataset_2.loc[(dataset_2["Age"]>15) & (dataset_2["Age"] <= 30),"Age's"] = 1
dataset_2.loc[(dataset_2["Age"]>30) & (dataset_2["Age"] <= 45),"Age's"] = 2
dataset_2.loc[(dataset_2["Age"]>45) & (dataset_2["Age"] <= 60),"Age's"] = 3
dataset_2.loc[dataset_2["Age"]>60,"Age's"] = 4
dataset_2
PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarkedAge's
0103Braund, Mr. Owen Harris022.010A/5 211717.250NaNS1.0
1211Cumings, Mrs. John Bradley (Florence Briggs Th...138.010PC 1759971.283C85C2.0
2313Heikkinen, Miss. Laina126.000STON/O2. 31012827.925NaNS1.0
3411Futrelle, Mrs. Jacques Heath (Lily May Peel)135.01011380353.100C123S2.0
4503Allen, Mr. William Henry035.0003734508.050NaNS2.0
..........................................
88688702Montvila, Rev. Juozas027.00021153613.000NaNS1.0
88788811Graham, Miss. Margaret Edith119.00011205330.000B42S1.0
88888903Johnston, Miss. Catherine Helen "Carrie"128.012W./C. 660723.450NaNS1.0
88989011Behr, Mr. Karl Howell026.00011136930.000C148C1.0
89089103Dooley, Mr. Patrick032.0003703767.750NaNQ2.0

891 rows × 13 columns

np.unique(dataset_2["Age's"],return_counts=True)
(array([0., 1., 2., 3., 4.]), array([ 83, 503, 202,  81,  22], dtype=int64))

사분위수에 맞춰서 Fare 범주화 실시

  1. [0,7.910]

  2. (7.910,14.454]

  3. (14.454,31]

  4. 31 초과

dataset_2['Fare'].describe()
count    891.000
mean      32.204
std       49.693
min        0.000
25%        7.910
50%       14.454
75%       31.000
max      512.329
Name: Fare, dtype: float64
dataset_2["Fare"] = pd.qcut(dataset_2['Fare'],4,labels=[0,1,2,3])
dataset_2
PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarkedAge's
0103Braund, Mr. Owen Harris022.010A/5 211710NaNS1.0
1211Cumings, Mrs. John Bradley (Florence Briggs Th...138.010PC 175993C85C2.0
2313Heikkinen, Miss. Laina126.000STON/O2. 31012821NaNS1.0
3411Futrelle, Mrs. Jacques Heath (Lily May Peel)135.0101138033C123S2.0
4503Allen, Mr. William Henry035.0003734501NaNS2.0
..........................................
88688702Montvila, Rev. Juozas027.0002115361NaNS1.0
88788811Graham, Miss. Margaret Edith119.0001120532B42S1.0
88888903Johnston, Miss. Catherine Helen "Carrie"128.012W./C. 66072NaNS1.0
88989011Behr, Mr. Karl Howell026.0001113692C148C1.0
89089103Dooley, Mr. Patrick032.0003703760NaNQ2.0

891 rows × 13 columns

Ticket, Cabin, Name 의 자료는 분석으로써의 가치가 없을 것으로 판단되어 삭제한다.

dataset_2.drop('Ticket', axis=1, inplace=True)
dataset_2.drop('Cabin', axis=1, inplace=True)
dataset_2.drop('Name', axis=1, inplace=True)
dataset_2.isnull().sum()
PassengerId    0
Survived       0
Pclass         0
Sex            0
Age            0
SibSp          0
Parch          0
Fare           0
Embarked       2
Age's          0
dtype: int64

아직 Embarked 데이터가 결측값 2개가 남았다.

dataset_2["Embarked"].value_counts()
S    644
C    168
Q     77
Name: Embarked, dtype: int64

Embarked의 최빈값인 S를 결측값에 넣어주기로 한다.

dataset_2["Embarked"].fillna("S",inplace=True)
dataset_2.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 10 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   Sex          891 non-null    int64   
 4   Age          891 non-null    float64 
 5   SibSp        891 non-null    int64   
 6   Parch        891 non-null    int64   
 7   Fare         891 non-null    category
 8   Embarked     891 non-null    object  
 9   Age's        891 non-null    float64 
dtypes: category(1), float64(2), int64(6), object(1)
memory usage: 63.8+ KB
이로써 결측값을 모두 정리했다.
dataset_2["Embarked"].value_counts()
S    646
C    168
Q     77
Name: Embarked, dtype: int64
Embarked

의 문자열 자료를 숫자로 변환하여 dataset_2에 저장한다.

  1. S

  2. C

  3. Q

dic = {"S": 0, "C": 1, "Q": 2}
dataset_2.loc[:, 'Embarked'] = dataset_2.loc[:, 'Embarked'].map(dic)
dataset_2
PassengerIdSurvivedPclassSexAgeSibSpParchFareEmbarkedAge's
0103022.010001.0
1211138.010312.0
2313126.000101.0
3411135.010302.0
4503035.000102.0
.................................
88688702027.000101.0
88788811119.000201.0
88888903128.012201.0
88989011026.000211.0
89089103032.000022.0

891 rows × 10 columns

dataset_2 자료에서 "Survived" 자료를 반응변수로 정하여 y_test에 분리한다.

y_test=dataset['Survived']
dataset_2.drop('Survived',axis=1,inplace=True)

dataset_2에서 PassengerId를 인덱스로 사용한다.

dataset_2.set_index("PassengerId",inplace=True)
dataset_2
PclassSexAgeSibSpParchFareEmbarkedAge's
PassengerId
13022.010001.0
21138.010312.0
33126.000101.0
41135.010302.0
53035.000102.0
...........................
8872027.000101.0
8881119.000201.0
8893128.012201.0
8901026.000211.0
8913032.000022.0

891 rows × 8 columns

x_test=dataset_2.copy()
x_test
PclassSexAgeSibSpParchFareEmbarkedAge's
PassengerId
13022.010001.0
21138.010312.0
33126.000101.0
41135.010302.0
53035.000102.0
...........................
8872027.000101.0
8881119.000201.0
8893128.012201.0
8901026.000211.0
8913032.000022.0

891 rows × 8 columns

x_test 데이터셋 설명

  • Pclass :티켓 등급 (1등석, 2등석, 3등석 등)

  • Sex : 성별 (0:남자, 1:여자)

  • Age : 나이

  • Age’s: 나이대

    0: 미성년 (15세 이하)

    1: 청년 (16세 이상, 30세 이하)

    2: 중년 (31세 이상, 45세 이하)

    3: 장년 (46세 이상, 60세 이하)

    4: 노년 (61세 이상)

  • SibSp : 동승한 형제자매, 배우자의 수

  • Parch : 동승한 부모, 자식의 수

  • Fare : 운임

    0: [0,7.910]

    1: (7.910,14.454]

    2: (14.454,31]

    3: 31 초과

  • Embarked : 탑승항구

    (C: Cherbourg, Q: Queenstown, S: Southampton)

    0: S

    1: C

    2: Q

지도학습모형

  • model1 : 의사결정나무

  • model2 : K-최근접이웃법

  • model3 : 로지스틱 회귀분석

  • model4 : 앙상블

  • model5 : 랜덤포레스트

  • model6 : 인공신경망

02_1. 의사결정나무(Decision Tree)

model1 = DecisionTreeClassifier()

model1.fit(x_test, y_test)

y_pred1 = model1.predict(x_test)
confusion_matrix(y_test,y_pred1, labels=[1,0])
array([[299,  43],
       [  3, 546]], dtype=int64)
np.round(accuracy_score(y_test,y_pred1),4)
0.9484
np.round(f1_score(y_test,y_pred1),4)
0.9286
f=plt.subplots(figsize=(10,5))
pd.Series(model1.feature_importances_,x_test.columns).sort_values(ascending=True).plot.barh(width=0.8)
plt.title('DecisionTreeClassifier')
Text(0.5, 1.0, 'DecisionTreeClassifier')

model1.feature_importances_
array([0.13732302, 0.34262405, 0.28184117, 0.06581069, 0.04331226,
       0.0767628 , 0.0389664 , 0.01335962])
x_test.columns
Index(['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked', 'Age's'], dtype='object')
values1 = model1.feature_importances_
pd1 = pd.Series(values1, index=x_test.columns[:]).sort_values(ascending=False)
pd1
Sex         0.343
Age         0.282
Pclass      0.137
Fare        0.077
SibSp       0.066
Parch       0.043
Embarked    0.039
Age's       0.013
dtype: float64
model1 = DecisionTreeClassifier(max_depth=4)
model1.fit(x_test, y_test)
y_pred1 = model1.predict(x_test)
plt.figure(figsize=(22,22))  # set plot size (denoted in inches)
sklearn.tree.plot_tree(model1, fontsize = 10)
plt.show()

survived = dataset[dataset['Survived'] == 1]["Sex"].value_counts()
dead = dataset[dataset['Survived'] == 0]["Sex"].value_counts()
print('남성 죽음:',str(dead[0]),'남성 생존:', str(survived[1]))
print('여성 죽음:',str(dead[1]),'여성 생존:', str(survived[0]))
남성 죽음: 468 남성 생존: 109
여성 죽음: 81 여성 생존: 233

의사결정 나무의 정확도:0.9484, F1:0.9286

특성 중요도는 성별이 가장 크고 그 다음 연령 그 다음 티켓등급이다.

의사결정 나무 그림 깊이는 4로 지정해서 출력하여 줬다.

(깊이를 지정하지 않으면 복잡한 구조가 출력되어 분석하기에 어려움이 있다.)

의사결정 나무의 그림을 살펴보면 성별로 남자(577명)와 여자(314명)로 구분짓고

남자 가지를 살펴보면 나이로 6살이하(24명)와 7살이상(553명)으로 나눈것을 알 수 있다.

6살 이하 남자 가지를 살펴보면 동승한 형제자매, 배우자의 수가 2명이하인지 3명이상인지 로 나누어 동승한 형제자매, 배우자의 수가 2명이하인 6살 남자아이 15명은 모두 생존한 것을 알 수 있다.

02_2. K-최근접이웃법(K-Nearest Neighbor)

model2 = KNeighborsClassifier()
model2.fit(x_test, y_test)
y_pred2 = model2.predict(x_test)
confusion_matrix(y_test,y_pred2, labels=[1,0])
array([[257,  85],
       [ 44, 505]], dtype=int64)
np.round(accuracy_score(y_test,y_pred2),4)
0.8552
np.round(f1_score(y_test,y_pred2),4)
0.7994

K-최근접이웃법의 정확도:0.8552, F1:0.7994

모형의 성능이 의사결정 나무 보다 나쁜 것을 볼 수 있다.

02_3. 로지스틱 회귀분석(Logistic Regression)

model3 = LogisticRegression()
model3.fit(x_test,y_test)
y_pred3 = model3.predict(x_test)
D:\Anaconda\lib\site-packages\sklearn\linear_model\_logistic.py:763: 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(
confusion_matrix(y_test,y_pred3,labels=[1,0])
array([[245,  97],
       [ 79, 470]], dtype=int64)
np.round(accuracy_score(y_test,y_pred3),4)
0.8025
np.round(f1_score(y_test,y_pred3),4)
0.7357

로지스틱 회귀분석의 정확도:0.8025, F1:0.7357

모형의 성능이 의사결정 나무 보다 나쁜 것을 볼 수 있다.

02_5. 앙상블(Ensemble) - 함수 이용

model4 = VotingClassifier(estimators=[('DT',DecisionTreeClassifier()),
                                      ('KNN',KNeighborsClassifier()),
                                      ('LR',LogisticRegression())],
                          voting='soft')

model4.fit(x_test,y_test)
y_pred4 = model4.predict(x_test)
D:\Anaconda\lib\site-packages\sklearn\linear_model\_logistic.py:763: 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(
confusion_matrix(y_test,y_pred4, labels=[1,0])
array([[299,  43],
       [ 15, 534]], dtype=int64)
np.round(accuracy_score(y_test,y_pred4),4)
0.9349
np.round(f1_score(y_test,y_pred4),4)
0.9116

앙상블의 정확도:0.9349, F1:0.9116

의사결정나무, K-최근접이웃법,로지스틱 회귀분석을 활용하여 앙상블을 만들었다.

모형의 성능이 K-최근접이웃법, 로지스틱 회귀분석 보다는 좋지만,

의사결정 나무 보다 나쁜 것을 볼 수 있다.

03.Random Forests

model5 = RandomForestClassifier()
model5.fit(x_test,y_test)
y_pred5 = model5.predict(x_test)
confusion_matrix(y_test,y_pred5, labels=[1,0])
array([[308,  34],
       [ 12, 537]], dtype=int64)
np.round(accuracy_score(y_test,y_pred5),4)
0.9484
np.round(f1_score(y_test,y_pred5),4)
0.9305
f=plt.subplots(figsize=(10,5))
pd.Series(model5.feature_importances_,x_test.columns).sort_values(ascending=True).plot.barh(width=0.8)
plt.title('RandomForestClassifier')
Text(0.5, 1.0, 'RandomForestClassifier')

values2 = model5.feature_importances_
pd2 = pd.Series(values2, index=x_test.columns[:]).sort_values(ascending=False)
pd2
Age         0.288
Sex         0.287
Pclass      0.112
Fare        0.094
SibSp       0.064
Age's       0.057
Parch       0.050
Embarked    0.048
dtype: float64

랜덤포레스트의 정확도:0.9484, F1:0.9305

랜덤포레스트에서는 특성 중요도 연령이 가장 크고 그 다음 성별 그 다음 티켓등급이다.

모형의 성능이 지금까지의 모형들 중 가장 좋은 것을 볼 수 있다.

신경망(다층신경망, MLP; Multi-Layer Perceptron)

model6 = MLPClassifier(hidden_layer_sizes = (10), activation = 'relu', solver = 'adam', 
                      batch_size = 'auto', learning_rate_init = 0.01, max_iter = 1000)

model6.fit(x_test, y_test)
y_pred6 = model6.predict(x_test)
  • hidden_layer_sizes : 히든 레이어의 층 및 노드 개수 / (기본값) 100

  • activation : 활성함수 / (기본값) ‘relu’=’렐루함수’, ‘identity’, ‘logistic’, ‘tanh’

  • solver : 경사하강법(Gradient Descent) / (기본값) ‘adam’, ‘lbfgs’, ‘sgd’

  • batch_size : 배치(batch)의 크기 / (기본값) min(200, 자료의 개수)

  • learning_rate_init : 학습률 / (기본값) 0.001

  • max_iter(epoch) : 반복회수 (기본값) 200

confusion_matrix(y_test,y_pred6, labels=[1,0])
array([[242, 100],
       [ 87, 462]], dtype=int64)
np.round(accuracy_score(y_test,y_pred6),4)
0.7901
np.round(f1_score(y_test,y_pred6),4)
0.7213

인공신경망의 정확도:0.7901, F1:0.7213

모형의 성능을 확인해 보면 그렇게 성능이 좋지 않을 것을 볼 수 있다.

히든 레이어의 수랑 학습률을 변경해봐도 성능이 많이 좋아지지 않는다.

모형들의 정확도 / F1

  • 의사결정나무 : 0.9484 / 0.9286

  • K-최근접이웃법 : 0.8552 / 0.7994

  • 로지스틱 회귀분석: 0.8025 / 0.7357

  • 앙상블 : 0.9349 / 0.9116

  • 랜덤포레스트 : 0.9484 / 0.9301

  • 신경망 : 0.7901 / 0.7213

모형의 성능이 가장 좋았던 랜덤포레스트를 사용하여 x_test를 확인하여 보겠다.

prediction = model5.predict(x_test)
pred = pd.DataFrame({"PassengerId" : x_test.index, 
                    "Survived" : prediction})
pred.head(10)
PassengerIdSurvived
010
121
231
341
450
560
670
780
891
9101
test = np.array(pred["Survived"]==dataset["Survived"])
np.unique(test, return_counts=True)
(array([False,  True]), array([ 46, 845], dtype=int64))
845/(46+845)
0.9483726150392817

정확도가 랜덤포레스트 모형의 정확도와 일치하는 것을 볼 수 있다.