Post

Titanic - Machine Learning from Disaster

問題と背景

Titanic - Machine Learning from Disaster

問題:機械学習により、タイタニック号の遭難事故で生き残った乗客を予測するモデルを作成する.

背景:Kaggle試合「Titanic - Machine Learning from Disaster」のDescriptionには,「On April 15, 1912, during her maiden voyage, the widely considered “unsinkable” RMS Titanic sank after colliding with an iceberg. Unfortunately, there weren’t enough lifeboats for everyone onboard, resulting in the death of 1502 out of 2224 passengers and crew.」と述べられている.

運の要素もあるが,女性,子供,上流階級などは,他のグループと比べて生き延びる可能性が高いことが一般的に考えられる.

機械学習最終レポート 氏名:YANG GUANGZE 学籍番号:20T1126N

More about machine-lerning | Github

分析開始

1
2
3
4
5
6
7
8
9
10
# ライブラリーのインポート 
import numpy as np 
import pandas as pd 
import matplotlib.pyplot as plt 
import seaborn as sns 
%matplotlib inline

#赤いwarmを消すため
import warnings
warnings.filterwarnings("ignore")
1
2
3
# JupyterNotebookの表示領域 
pd.set_option("display.max_columns", 100) 
pd.set_option("display.max_rows", 100)
1
2
3
4
# データの読込み 
train_df = pd.read_csv("./train.csv") 
test_df = pd.read_csv("./test.csv") 
train_df.head(10) # 先頭部分の表示
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
5603Moran, Mr. JamesmaleNaN003308778.4583NaNQ
6701McCarthy, Mr. Timothy Jmale54.0001746351.8625E46S
7803Palsson, Master. Gosta Leonardmale2.03134990921.0750NaNS
8913Johnson, Mrs. Oscar W (Elisabeth Vilhelmina Berg)female27.00234774211.1333NaNS
91012Nasser, Mrs. Nicholas (Adele Achem)female14.01023773630.0708NaNC
1
2
3
# データのサイズ 
print(train_df.shape) 
print(test_df.shape)
1
2
(891, 12)
(418, 11)

分析説明:

データにより,一つの目標変数「Survived」に対して,説明変数「PassengerId」,「Pclass」,「Name」,「Sex」,「Age」,「SibSp」,「Parch」,「Ticket」,「Fare」,「Cabin」,「Embarked」がある.

日本語にすると,搭乗者番号,搭乗者階級,搭乗者氏名,性別,年齢,同乗した兄弟と配偶者の数,同乗した両親と子供の数,チケット番号,運賃,客室番号,乗車した港である.

よって,今回では,上記の説明変数を用いて目標変数「Survived」を予測する機械学習の判別問題をする.

また,学習データ891個,テストデータ418個である

内容については,以下のようになる.

1.学習データへの理解

2.説明変数の加工

3.機械学習

4.Kaggle最終結果

1.学習データへの理解

1.1データを確認する

説明変数のデータ型とデータの欠損について考察することで,加工すべきな説明変数を探す.

1
2
train_df.dtypes # データの型を表示
train_df.info() # データの詳細を表示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<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
1
2
test_df.dtypes # データの型を表示
test_df.info() # データの詳細を表示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 418 entries, 0 to 417
Data columns (total 11 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   PassengerId  418 non-null    int64  
 1   Pclass       418 non-null    int64  
 2   Name         418 non-null    object 
 3   Sex          418 non-null    object 
 4   Age          332 non-null    float64
 5   SibSp        418 non-null    int64  
 6   Parch        418 non-null    int64  
 7   Ticket       418 non-null    object 
 8   Fare         417 non-null    float64
 9   Cabin        91 non-null     object 
 10  Embarked     418 non-null    object 
dtypes: float64(2), int64(4), object(5)
memory usage: 36.0+ KB

よって,以下の3点をまとめられる.

1.データの型について「Name」,「Sex」,「Ticket」,「Cabin」,「Embarked」はobject型なので,説明変数の加工(ダミー変数への変換)が必要である.

2.データの損失について「Age」,「Fare」はデータの欠損があるので,説明変数の加工(欠損値 の置き換え)が必要である.

3.「Cabin」の欠損が大きいので,「Cabin」を重要な要素として扱わない方が良いと考える.

1.2データの分布,目標変換との関係

データ変数の分布を考察することで,各変数を深く理解する.

1.2.1 目標変数「Survived」に対して

1
2
# 学習データにおける生存率(1:生存, 0:故人) 
train_df["Survived"].mean()
1
0.3838383838383838

学習データの生存率は,約38%であることをわかった.

1.2.2 説明変数Pclassに対して

階級により,身分の高さが目標変数「Survived」に大きく影響を与えると期待する.

また,階級による経済的な差もあるので,チケット番号,運賃,客室番号に影響を及ぼすことを予想する. チケット番号,運賃,客室番号は,階級による間接効果であると仮説する.

1
2
# 要素の頻度 
train_df["Pclass"].value_counts()
1
2
3
4
3    491
1    216
2    184
Name: Pclass, dtype: int64
1
2
3
# Pclass別の生存数カウント 
import seaborn as sns 
sns.countplot(data=train_df, x="Pclass", hue="Survived");

png

1
2
# Pclass別の生存率 
train_df["Survived"].groupby(train_df["Pclass"]).mean()
1
2
3
4
5
Pclass
1    0.629630
2    0.472826
3    0.242363
Name: Survived, dtype: float64

結果:説明変数の「Pclass」別により,生存率が大幅に異なっていることをわかった.

よって,階級が高い(1>2>3)の方が生き延びる可能性が高いことが明らかになっている.Pclassは非常に重要な変数である.

1.2.3 説明変数Sexに対して

性別により,目標変数「Survived」に大きく影響を与えると期待する.理由として,欧米の文化には「adies first」が存在しているためである.

1
2
# Sex別の生存数カウント(1:生存, 0:故人) 
sns.countplot(data=train_df, x="Sex", hue="Survived");

png

1
2
# 要素の頻度 
train_df["Sex"].value_counts()
1
2
3
male      577
female    314
Name: Sex, dtype: int64
1
2
# Sex別の生存率 
train_df["Survived"].groupby(train_df["Sex"]).mean()
1
2
3
4
Sex
female    0.742038
male      0.188908
Name: Survived, dtype: float64

結果:予想通りに,女性の方が生存率がとても高いことをわかった.

ただし,この影響は,性別の直接効果か階級による性別の間接効果かを考察すべきだと考える.

1
2
# Sex別のPclassカウント 
sns.countplot(data=train_df, x="Sex",hue="Pclass");

png

この図により,男性の中に階級が低いの方が多いのに,女性の方が生存率が高いということは,確かに性別の直接効果(female>male)である.階級より影響力が高い要素かもしれない.

1.2.4 説明変数Ageに対して

年齢により,目標変数「Survived」に大きく影響を与えると期待する.理由として,「子供を優先すること」が存在しているためである.

1
2
3
# Ageの抽出 
Age0 = train_df[ train_df["Survived"]==0 ]["Age"] 
Age1 = train_df[ train_df["Survived"]==1 ]["Age"]
1
2
3
4
# ヒストグラム 
plt.hist( [Age0, Age1], bins=8, label=["0: Death", "1: Survive"] ) 
plt.legend() 
plt.xlabel("Age");

png

結果:予想通りに若いほど生き延びる可能性が高いことをわかった.

ただし,この影響は,年齢の直接効果か間接効果かを考察すべきだと考える.

1
2
3
# AgeとSexの関係 
Age2 = train_df[ train_df["Sex"]=="male" ]["Age"] 
Age3 = train_df[ train_df["Sex"]=="female" ]["Age"]
1
2
3
4
# ヒストグラム 
plt.hist( [Age2, Age3], bins=8, label=["male", "female"] ) 
plt.legend() 
plt.xlabel("Age");

png

1
2
3
4
# AgeとPclassの関係
Age4 = train_df[ train_df["Pclass"]==1 ]["Age"] 
Age5 = train_df[ train_df["Pclass"]==2 ]["Age"]
Age6 = train_df[ train_df["Pclass"]==3 ]["Age"]
1
2
3
4
# ヒストグラム 
plt.hist( [Age4, Age5, Age6], bins=8, label=["Pclass:1", "Pclass:2","Pclass:3"] ) 
plt.legend() 
plt.xlabel("Age");

png

これによって,年齢ごとに,階級と性別の偏りがないので,若いほど生き延びる可能性が高いことは,年齢の直接効果だと考えられる.

1.2.5 説明変数SibSp,Parchに対して

同乗した兄弟,配偶者,両親,子供の数は,生存率に大きく影響されないと考えられるが,これらのデータを考察する

1
2
# SibSp別の生存率 
train_df["Survived"].groupby(train_df["SibSp"]).mean()
1
2
3
4
5
6
7
8
9
SibSp
0    0.345395
1    0.535885
2    0.464286
3    0.250000
4    0.166667
5    0.000000
8    0.000000
Name: Survived, dtype: float64
1
2
# 要素の頻度 
train_df["SibSp"].value_counts()
1
2
3
4
5
6
7
8
0    608
1    209
2     28
4     18
3     16
8      7
5      5
Name: SibSp, dtype: int64
1
2
3
4
5
6
7
# SibSpの抽出 
SibSp0 = train_df[ train_df["Survived"]==0 ]["SibSp"] 
SibSp1 = train_df[ train_df["Survived"]==1 ]["SibSp"]
# ヒストグラム 
plt.hist( [SibSp0, SibSp1], bins=8, label=["0: Death", "1: Survive"] ) 
plt.legend() 
plt.xlabel("SibSp");

png

1
2
# Parch別の生存率 
train_df["Survived"].groupby(train_df["Parch"]).mean()
1
2
3
4
5
6
7
8
9
Parch
0    0.343658
1    0.550847
2    0.500000
3    0.600000
4    0.000000
5    0.200000
6    0.000000
Name: Survived, dtype: float64
1
2
# 要素の頻度 
train_df["Parch"].value_counts()
1
2
3
4
5
6
7
8
0    678
1    118
2     80
5      5
3      5
4      4
6      1
Name: Parch, dtype: int64
1
2
3
4
5
6
7
# Parchの抽出 
Parch0 = train_df[ train_df["Survived"]==0 ]["Parch"] 
Parch1 = train_df[ train_df["Survived"]==1 ]["SibSp"]
# ヒストグラム 
plt.hist( [Parch0, Parch1], bins=6, label=["0: Death", "1: Survive"] ) 
plt.legend() 
plt.xlabel("Parch");

png

結果:要素の頻度により,同乗した兄弟,配偶者,両親,子供の数が多いの方が少ないので,参考にならない.さらに同乗した兄弟,配偶者,両親,子供の数と生存率の関係は,明らかに線形的ではない.しかしながら,家族の有無は,生存率に影響を与えると考えられる.

説明変数SibSp,Parchに対して,新しな説明変数「Family」で家族の有無を表示すれば,機械学習モデルの正確さを高めるだろう.

1.2.6 説明変数Fareに対して

運賃が生存率に若干影響を与えると予想される.理由としては,運賃の高さも階級を表すと考えっている.

1
2
3
4
5
6
7
# Fareの抽出 
Fare0 = train_df[ train_df["Survived"]==0 ]["Fare"] 
Fare1 = train_df[ train_df["Survived"]==1 ]["Fare"]
# ヒストグラム 
plt.hist( [Fare0, Fare1], bins=8, label=["0: Death", "1: Survive"] ) 
plt.legend() 
plt.xlabel("Fare");

png

結果:予想通りに,運賃が高い方が生き延びる可能性が高いかもしれない.

そして,この影響が運賃の直接効果か階級による間接効果かを考察する.

1
2
3
4
5
6
7
8
# FareとPclassの関係
Fare2 = train_df[ train_df["Pclass"]==1 ]["Fare"] 
Fare3 = train_df[ train_df["Pclass"]==2 ]["Fare"]
Fare4 = train_df[ train_df["Pclass"]==3 ]["Fare"]
# ヒストグラム 
plt.hist( [Fare2, Fare3, Fare4], bins=8, label=["Pclass:1", "Pclass:2","Pclass:3"] ) 
plt.legend() 
plt.xlabel("Fare");

png

これによって,運賃は階級ごとに明らかな偏りが存在しているので,運賃の影響は階級による間接効果だと考えられる

機械学習モデルの正確さを高めるために,Fare要素の重さを小さくする方が良いかもしれない.

1.2.7 説明変数Name,Ticket,Cabin,Embarkedに対して

名前,チケット番号,客室番号,乗車した港は,生存率にあまり影響を及ばないと予想される.理由は,これらのデータが多様な文字列としてルールがない.

1
2
# データの確認 
train_df["Name"].head()
1
2
3
4
5
6
0                              Braund, Mr. Owen Harris
1    Cumings, Mrs. John Bradley (Florence Briggs Th...
2                               Heikkinen, Miss. Laina
3         Futrelle, Mrs. Jacques Heath (Lily May Peel)
4                             Allen, Mr. William Henry
Name: Name, dtype: object
1
2
# 要素毎のデータ数 
train_df["Name"].value_counts()
1
2
3
4
5
6
7
8
9
10
11
12
Braund, Mr. Owen Harris                     1
Boulos, Mr. Hanna                           1
Frolicher-Stehli, Mr. Maxmillian            1
Gilinski, Mr. Eliezer                       1
Murdlin, Mr. Joseph                         1
                                           ..
Kelly, Miss. Anna Katherine "Annie Kate"    1
McCoy, Mr. Bernard                          1
Johnson, Mr. William Cahoone Jr             1
Keane, Miss. Nora A                         1
Dooley, Mr. Patrick                         1
Name: Name, Length: 891, dtype: int64
1
2
# データの確認 
train_df["Ticket"].head()
1
2
3
4
5
6
0           A/5 21171
1            PC 17599
2    STON/O2. 3101282
3              113803
4              373450
Name: Ticket, dtype: object
1
2
# 要素毎のデータ数 
train_df["Ticket"].value_counts()
1
2
3
4
5
6
7
8
9
10
11
12
347082      7
CA. 2343    7
1601        7
3101295     6
CA 2144     6
           ..
9234        1
19988       1
2693        1
PC 17612    1
370376      1
Name: Ticket, Length: 681, dtype: int64
1
2
# データの確認 
train_df["Cabin"].head()
1
2
3
4
5
6
0     NaN
1     C85
2     NaN
3    C123
4     NaN
Name: Cabin, dtype: object
1
2
# 要素毎のデータ数 
train_df["Cabin"].value_counts()
1
2
3
4
5
6
7
8
9
10
11
12
B96 B98        4
G6             4
C23 C25 C27    4
C22 C26        3
F33            3
              ..
E34            1
C7             1
C54            1
E36            1
C148           1
Name: Cabin, Length: 147, dtype: int64
1
2
# Embarked別の生存率 
train_df["Survived"].groupby(train_df["Embarked"]).mean()
1
2
3
4
5
Embarked
C    0.553571
Q    0.389610
S    0.336957
Name: Survived, dtype: float64
1
2
# 要素の頻度 
train_df["Embarked"].value_counts()
1
2
3
4
S    644
C    168
Q     77
Name: Embarked, dtype: int64
1
2
# Embarked別のSurvivedカウント 
sns.countplot(data=train_df, x="Embarked",hue="Survived");

png

結果:名前,チケット番号,客室番号は,予想通りになっている.しかしながら,乗車した港は,目標変数に対して関係があることをわかった.

以上で,学習データを理解した上で,以下のように重要な説明変数を取り上げられる.

1.Placss

2.sex

3.Age

4.EmbarkedFare

5.Embarked

6.Family(SibSp+Parch)

ただし,残りのPassengerId,Name,Ticket,Cabinを除去する.

2.説明変数の加工

2.1学習とテストデータの結合

1
2
3
4
5
6
7
8
9
10
11
12
13
# 仕切り直し
train_df = pd.read_csv("./train.csv") 
test_df = pd.read_csv("./test.csv")

#不要データを除去する.
train_df = train_df.drop(['Name','Ticket', 'Cabin'], axis=1)
test_df = test_df.drop(['Name','Ticket', 'Cabin'], axis=1)

# 学習用データとテスト用データの結合 
all_df = pd.concat( [train_df, test_df], sort = False ) # 並び替えナシ

# インデックス番号の振り直し (trainとtestでindexが重複するので) 
all_df.reset_index( drop=True ) # 古いindexを削除
PassengerIdSurvivedPclassSexAgeSibSpParchFareEmbarked
010.03male22.0107.2500S
121.01female38.01071.2833C
231.03female26.0007.9250S
341.01female35.01053.1000S
450.03male35.0008.0500S
..............................
13041305NaN3maleNaN008.0500S
13051306NaN1female39.000108.9000C
13061307NaN3male38.5007.2500S
13071308NaN3maleNaN008.0500S
13081309NaN3maleNaN1122.3583C

1309 rows × 9 columns

2.2カテゴリ変数の書き換え

1
2
# ダミー変数への変換 
all_df = pd.get_dummies( all_df, drop_first=True )
1
2
# 欠損値の確認 
all_df.isna().sum()
1
2
3
4
5
6
7
8
9
10
11
PassengerId      0
Survived       418
Pclass           0
Age            263
SibSp            0
Parch            0
Fare             1
Sex_male         0
Embarked_Q       0
Embarked_S       0
dtype: int64

2.3欠損値の置き換え

1
2
3
# 欠損値を平均値で埋める
all_df["Age"] = all_df["Age"].fillna( all_df["Age"].mean() ) 
all_df["Fare"] = all_df["Fare"].fillna( all_df["Fare"].mean() )

2.4データの統合

1
2
#新たな変数Familyを作成する
all_df["Family"] = np.where( (all_df['SibSp'] == 0) & (all_df['Parch'] == 0),0,1)
1
2
#新たな変数Familyを確認する
all_df['Family']
1
2
3
4
5
6
7
8
9
10
11
12
0      1
1      1
2      0
3      1
4      0
      ..
413    0
414    0
415    0
416    0
417    1
Name: Family, Length: 1309, dtype: int32
1
2
#SibSpとParchを除去する
all_df = all_df.drop( ["SibSp", "Parch"], axis=1 )
1
2
#データを再確認する
all_df
PassengerIdSurvivedPclassAgeFareSex_maleEmbarked_QEmbarked_SFamily
010.0322.0000007.25001011
121.0138.00000071.28330001
231.0326.0000007.92500010
341.0135.00000053.10000011
450.0335.0000008.05001010
..............................
4131305NaN329.8811388.05001010
4141306NaN139.000000108.90000000
4151307NaN338.5000007.25001010
4161308NaN329.8811388.05001010
4171309NaN329.88113822.35831001

1309 rows × 9 columns

2.5データの分離

1
2
3
#trainとtestに戻す 
train_df_2 = all_df[:len(train_df)] 
test_df_2 = all_df[len(train_df):]
1
2
3
4
# 説明変数と目的変数の分離 (列を削除) 
train_X = train_df_2.drop( ["Survived", "PassengerId"], axis=1 ) 
test_X = test_df_2.drop( ["Survived", "PassengerId"], axis=1 )
train_Y = train_df_2["Survived"]
1
train_X.shape, train_Y.shape, test_X.shape
1
((891, 7), (891,), (418, 7))

3.機械学習

学習モデルについて,以下のようになっている.

1.決定木

2.ランダムフォレスト

3.勾配ブースティング

4.集団学習

5.スタッキング

3.1決定木

1
2
3
4
5
6
7
8
9
10
11
12
# 決定木
from sklearn.tree import DecisionTreeClassifier 
from sklearn.model_selection import cross_val_score
MAX_DEPTH = 10
accuracy = np.zeros(MAX_DEPTH)

for depth in range(1, MAX_DEPTH+1):
    decision_tree = DecisionTreeClassifier(max_depth = depth)
    scores = cross_val_score(decision_tree,train_X,train_Y,cv=10)
    accuracy[depth-1] = np.mean(scores)
    
plt.plot(range(1, MAX_DEPTH+1),accuracy,'.-')
1
[<matplotlib.lines.Line2D at 0x1c7acaee700>]

png

1
2
3
4
#パラメータ最適化
decision_tree = DecisionTreeClassifier(max_depth=3)#過学習を防ぐために,depth=3
decision_tree.fit(train_X, train_Y)
Y_pred_dt = decision_tree.predict(test_X)
1
2
3
4
# 予測結果の出力 
file = pd.read_csv("./gender_submission.csv") 
file["Survived"] = Y_pred_dt.astype(int) # 整数型に変換 (少数点以下を削除)
file.to_csv("./submission_dt.csv", index=False) # indexは上書きしない

3.1ランダムフォレスト

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ランダムフォレスト
from sklearn.ensemble import RandomForestClassifier

X=train_X
Y=train_Y

MAX_DEPTH = 20
accuracy = np.zeros(MAX_DEPTH)

for depth in range(1,MAX_DEPTH+1):
    model_rf = RandomForestClassifier(n_estimators = 500 ,max_depth=depth,random_state=1126)
    model_rf.fit(X,Y)
    model_rf.score(X, Y)
    scores = cross_val_score(model_rf,X,Y,cv=20)
    accuracy[depth-1] = np.mean(scores)
    
plt.plot(range(1, MAX_DEPTH+1),accuracy,'.-')
1
[<matplotlib.lines.Line2D at 0x1c7ac1782b0>]

png

1
2
3
4
#パラメータ最適化
model_rf = RandomForestClassifier(n_estimators = 500 ,max_depth=4,random_state=1126)
model_rf.fit(train_X,train_Y)
Y_pred_rf = model_rf.predict(test_X)
1
2
3
file = pd.read_csv("./gender_submission.csv") 
file["Survived"] = Y_pred_rf.astype(int) # 整数型に変換 (少数点以下を削除)
file.to_csv("./submission_rf.csv", index=False) # indexは上書きしない

3.3勾配ブースティング

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from sklearn.ensemble import GradientBoostingClassifier

X=train_X
Y=train_Y

MAX_DEPTH = 10
accuracy = np.zeros(MAX_DEPTH)

for depth in range(1,MAX_DEPTH+1):
    model_gb = GradientBoostingClassifier(n_estimators = 500 ,max_depth=depth,random_state=1234)
    scores = cross_val_score(model_gb,X,Y,cv=10)
    accuracy[depth-1] = np.mean(scores)
    
plt.plot(range(1, MAX_DEPTH+1),accuracy,'.-')
1
[<matplotlib.lines.Line2D at 0x1c7ac3c4100>]

png

1
2
3
4
#パラメータ最適化
model_gb = GradientBoostingClassifier(n_estimators = 500 ,max_depth=3,random_state=1234)
model_gb.fit(train_X,train_Y)
Y_pred_gb = model_gb.predict(test_X)
1
2
3
file = pd.read_csv("./gender_submission.csv") 
file["Survived"] = Y_pred_gb.astype(int) # 整数型に変換 (少数点以下を削除)
file.to_csv("./submission_gb.csv", index=False) # indexは上書きしない

3.4集団学習

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
model1 = RandomForestClassifier( n_estimators=500,random_state=1126, max_depth = 4 ) 
model2 = RandomForestClassifier( n_estimators=500,random_state=9999, max_depth = 4 ) 
model3 = GradientBoostingClassifier( n_estimators=500,random_state=1126, max_depth = 3 ) 
model4 = GradientBoostingClassifier( n_estimators=500,random_state=9999, max_depth = 3 ) 

# 学習
model1.fit( train_X, train_Y ) 
model2.fit( train_X, train_Y ) 
model3.fit( train_X, train_Y ) 
model4.fit( train_X, train_Y ) 

# テスト 
pred_test_Y1 = model1.predict( test_X ) 
pred_test_Y2 = model2.predict( test_X ) 
pred_test_Y3 = model3.predict( test_X ) 
pred_test_Y4 = model4.predict( test_X ) 

# 予測結果の多数決 (平均値)
ensemble_Y = ( pred_test_Y1 + pred_test_Y2 
 + pred_test_Y3 + pred_test_Y4) / 4 
1
2
3
4
# 予測結果の出力 
file = pd.read_csv("./gender_submission.csv") 
file["Survived"] = ensemble_Y.astype(int)
file.to_csv("./submission_ENS.csv", index=False)

3.5スタッキング

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#スタッキング
pred_train_Y1 = model1.predict(train_X)
pred_train_Y2 = model2.predict(train_X)
pred_train_Y3 = model3.predict(train_X)
pred_train_Y4 = model4.predict(train_X)
Ens_train_Y=np.array([pred_train_Y1,pred_train_Y2,pred_train_Y3,pred_train_Y4]).T

#ここで重回帰モデルLinearClassifierをimportできないために,ほかの線形分類器を用いた.
#確率的勾配降下法SGD
from sklearn.linear_model import SGDClassifier
model_boss = SGDClassifier()

X=Ens_train_Y
Y=train_Y

model_boss.fit(X,Y)

#子分の予測
pred_test_Y1 = model1.predict(test_X)
pred_test_Y2 = model2.predict(test_X)
pred_test_Y3 = model3.predict(test_X)
pred_test_Y4 = model4.predict(test_X)
Ens_test_X = np.array([pred_test_Y1, pred_test_Y2, pred_test_Y3, pred_test_Y4 ]).T

#ボス予測
pred_test_YBoss = model_boss.predict(Ens_test_X)
1
2
3
file = pd.read_csv("./gender_submission.csv") 
file["Survived"] = pred_test_YBoss.astype(int) # 整数型に変換 (少数点以下を削除)
file.to_csv("./submission_STK.csv", index=False) # indexは上書きしない

4.Kaggle最終結果

決定木: 0.77990

ランダムフォレスト: 0.77751

勾配ブースティング: 0.75458

集団学習: 0.77511

スタッキング: 0.75598

得点最も高いのは,決定木である.

スコア

0.77990

順位

2923

ハンドルネーム

koutaku young

This post is licensed under CC BY 4.0 by the author.