Kaggle(27) - Sickit-learn interfaceを使う - LightGBM編4

Sickit-learn wapper interfaceというラッパーを使うと、LightGBMをSickit-learnを介して使うことができます。

端的にいうとSickit-learnでお馴染みの、fitで学習しpredictで推論することができるようになります。

データの読み込み

タイタニックのデータセットを読み込み、データの前処理を行って、正解ラベルとそれ以外にデータを分割します。

[ソース]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import numpy as np
import pandas as pd

df_train = pd.read_csv('/kaggle/input/titanic/train.csv')

# データ前処理
def preprocessing(df):
# 不要な列の削除
df.drop(['Name', 'Ticket', 'Cabin'], axis=1, inplace=True)

# カテゴリ変数の型変換
df['Sex'] = df['Sex'].astype('category')
df['Embarked'] = df['Embarked'].astype('category')

return df

x_titanic = preprocessing(df_train.drop(['Survived'], axis=1))
y_titanic = df_train['Survived']

Sickit-learn interfaceを使う

LightGBMをSickit-learn interfaceでラップし(12行目)、学習・推論を行います。

[ソース]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import lightgbm as lgb
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split

# 訓練データをtrainとvalidに分割
train_x, valid_x, train_y, valid_y = train_test_split(x_titanic, y_titanic, test_size=0.33, random_state=0)

# パラメータを定義
lgbm_params = {'objective': 'binary'}

# LightGBMの分類器をインスタンス化
gbm = lgb.LGBMClassifier(objective='binary')

# 学習
gbm.fit(train_x, train_y, eval_set=[(train_x, train_y), (valid_x, valid_y)],
early_stopping_rounds=20, # 20回連続でlossが下がらなかったら終了
verbose=10) # 10roundごとにlossを表示
# gbm.fit(train_x, train_y) # 単純学習

# 推論
pre = gbm.predict(valid_x, num_iteration=gbm.best_iteration_)
print('score', round(accuracy_score(valid_y, pre) * 100, 2))

[出力]

正解率は83.05%となりました。なかなかの結果です。

検証データを読み込み、推論・提出用のCSVの出力を行い、Kaggleに提出してみます。

[ソース]

1
2
3
4
5
6
7
8
9
# 検証データの読み込み
df_test = pd.read_csv('/kaggle/input/titanic/test.csv')
df_test = preprocessing(df_test)

pre = gbm.predict(df_test)

result = pd.DataFrame(df_test['PassengerId'])
result['Survived'] = pre
result.to_csv('result0305.csv', index=False)

[提出結果]

正解率78.82%と、もう少しで8割に到達できそうです。

便利な交差分割検証関数

LightGBMをSickit-learnと同じように扱えるようになると、cross_val_scoreというとても便利な関数を使うことができるようになります。

この関数を使うと、たった1行で分割交差検証ができてしまいます。

[ソース]

1
2
3
4
from sklearn import model_selection
score = model_selection.cross_val_score(gbm, x_titanic, y_titanic, cv=3) # cv=3は3分割の意
print('各正解率', score)
print('正解率', score.mean())

[出力]

便利すぎます。

このような便利関数があるのでSickit-learnは広く普及しているんだと思います。

Kaggle(26) - 重要度の表示 - LightGBM編3

LightGBMでは、学習済みモデルのfeature_importanceメソッドを使うと特徴の重要度を表示することができます。

重要度の表示

前回記事で学習したモデルについての重要度を表示します。

[ソース]

1
gbm.feature_importance()

[出力]

feature_importanceメソッドは、デフォルトの引数としてimportance_type=’split’が指定されており、重要度としては「特徴が使用された回数」が表示されます。

引数にimportance_type=’gain’を指定した場合は、「その特徴によりどれくらいトレーニングデータの損失を小さくできたか」を表示します。

[ソース]

1
gbm.feature_importance(importance_type='gain')

[出力]


2種類の重要度を比較しやすいように、1つのデータフレームにして表示します。

トレーニングデータの損失(gain)の方は、intに丸めてみました。

[ソース]

1
2
3
pd.DataFrame({'特徴':x_titanic.columns,
'重要度(split)':gbm.feature_importance(),
'重要度(gain)':gbm.feature_importance(importance_type='gain').astype(int)})

[出力]

重要度(split)では年齢(Age)の比重が大きく、重要度(gain)では性別(Sex)が最重要であることが把握できます。

Kaggle(25) - タイタニック(Titanic)コンペ - LightGBM編2

これまでデータの前処理を行うときに、カテゴリー変数についてはOne-Hotエンコーディングを行っていました。

しかし【LightGBMのドキュメント】によると、カテゴリー変数はOne-Hotエンコーディングするよりも0から始まる連続した整数に変換するほうが優れたパフォーマンスを発揮するとのことでした。

今回はOne-Hotエンコーディングの代わりに、カテゴリー変数を整数に変換してタイタニック・コンペに提出してみます。

データ読み込みと前処理

まずはいつも通りタイタニックのデータセットを読み込みます。

[ソース]

1
2
3
4
import numpy as np
import pandas as pd

df_train = pd.read_csv('/kaggle/input/titanic/train.csv')

今回のポイントであるデータ前処理ですが、LightGBMで学習・推測するためには下記の5変数を変換する必要があります。
  • Name
  • Sex
  • Ticket
  • Cabin
  • Embarked

このうち生存率に関係のなさそうなNameとTicketとCabinは単純に削除します。

そしてSexとEmbarkedを整数に変換したいのですが、一番カンタンそうな方法はデータ型をcategory型に変えることでした。

こうすることによって、自動でカテゴリーを変換した整数として扱ってくれるので、自分で0や1などの整数に置き換える必要がなくとてもラクチンでした。

[ソース]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# データ前処理
def preprocessing(df):
# 不要な列の削除
df.drop(['Name', 'Ticket', 'Cabin'], axis=1, inplace=True)

# カテゴリ変数の変換
# df = pd.get_dummies(df, columns=['Sex', 'Embarked'])
df['Sex'] = df['Sex'].astype('category')
df['Embarked'] = df['Embarked'].astype('category')

return df

x_titanic = preprocessing(df_train.drop(['Survived'], axis=1))
y_titanic = df_train['Survived']

データの前処理が終わりましたら、以前実行した時と同じようにLightGBMを使って学習を行います。

[ソース]

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import lightgbm as lgb
from sklearn.metrics import accuracy_score
from sklearn.model_selection import KFold

# 3分割交差検証を指定しインスタンス化する
kf = KFold(n_splits=3, shuffle=True)

# スコアとモデルを格納するリスト
score_list = []
models = []

for fold_, (train_index, valid_index) in enumerate(kf.split(x_titanic, y_titanic)):
print(f'fold{fold_ + 1}start')
train_x = x_titanic.iloc[train_index]
valid_x = x_titanic.iloc[valid_index]
train_y = y_titanic.iloc[train_index]
valid_y = y_titanic.iloc[valid_index]

# lab.Datasetを使って、trainとvalidを作っておく
lgb_train = lgb.Dataset(train_x, train_y)
lgb_valid = lgb.Dataset(valid_x, valid_y)

# パラメータを定義
lgbm_params = {'objective': 'binary'}

# lgb.trainで学習
evals_result = {}
gbm = lgb.train(params=lgbm_params,
train_set=lgb_train,
valid_sets=[lgb_train, lgb_valid],
early_stopping_rounds=20,
evals_result=evals_result,
verbose_eval=-1) # 学習の状態を表示しない
# valid_xについて推論
oof = (gbm.predict(valid_x) > 0.5).astype(int)
score_list.append(round(accuracy_score(valid_y, oof) * 100, 2))
# 学習が終わったモデルをリストに入れておく
models.append(gbm)
print(f'fold_{fold_ + 1} end\n')

print(score_list, '平均score', round(np.mean(score_list), 2))

[出力]

平均正解率は81.6%とそこそこの結果というところでしょうか。

最後に、学習したモデルを使って、生存の推測を行い提出用のCSVファイルを出力します。

検証データに対してもデータの前処理(3行目)を行うことをお忘れなく。

[ソース]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 検証データの読み込み
df_test = pd.read_csv('/kaggle/input/titanic/test.csv')
df_test = preprocessing(df_test)

# テストデータの予測を格納する行列を作成
test_pred = np.zeros((len(df_test), 3))

for fold, gbm in enumerate(models):
test_pred[:, fold] = gbm.predict(df_test)

result = pd.DataFrame(df_test['PassengerId'])
# 平均が0.5より大きい場合,1(生存)とする
result['Survived'] = (np.mean(test_pred, axis=1) > 0.5).astype(int)
result
result.to_csv('result.csv', index=False)

予測結果を提出します。

[提出結果]

提出結果は77.99%という正解率になりました。

カテゴリ変数をOne-Hotエンコーディングしときの結果は75.59%でしたので2.4%ほど正解率が上がりました。

Kaggle(24) - タイタニック(Titanic)コンペ - 決定木編

今回はアルゴリズムに決定木を使ってみます。

決定木とは、ツリー状に条件分岐を繰り返すことによって分類するクラスを予測するモデルです。

枝分かれ部分の条件は、データの変数を使って作ります。

データ読み込みと前処理

Kaggleに準備されているタイタニックの訓練データを読み込みます。

データの前処理(不要列の削除・欠損処理・カテゴリ変数の変換)と、正解ラベルとそれ以外にデータを分けるところまで一気に実行します。

[ソース]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import numpy as np
import pandas as pd

df_train = pd.read_csv('/kaggle/input/titanic/train.csv')

# データ前処理
def preprocessing(df):
# 不要な列の削除
df.drop(['Name', 'Ticket', 'Cabin'], axis=1, inplace=True)

# 欠損値処理
df['Age'] = df['Age'].fillna(df['Age'].median())
df['Fare'] = df['Fare'].fillna(df['Fare'].median())
df['Embarked'] = df['Embarked'].fillna('S')

# カテゴリ変数の変換
df = pd.get_dummies(df, columns=['Sex', 'Embarked'])

return df

x_titanic = preprocessing(df_train.drop(['Survived'], axis=1))
y_titanic = df_train['Survived']

決定木アルゴリズムで学習・推測

決定木アルゴリズムを準備します。

学習・推測を行う前に、分割交差検証を使ってどのくらいの正答率になるか調べてみます。

[ソース]

1
2
3
4
5
6
7
8
9
from sklearn import svm, metrics, model_selection
from sklearn import tree

clf = tree.DecisionTreeClassifier(max_depth=5)

# 分割交差検証を実行
score = model_selection.cross_val_score(clf, x_titanic, y_titanic, cv=4) # cv=4は4分割の意
print('各正解率', score)
print('正解率', score.mean())

[出力]

平均正解率は78.34%とそこそこの結果というところでしょうか。


決定木アルゴリズムで学習を行い、データを予測し提出用のCSVファイルを作成します。

[ソース]

1
2
3
4
5
6
7
8
9
10
11
12
# 学習する
clf.fit(x_titanic, y_titanic)

# データを予測
df_test = pd.read_csv('/kaggle/input/titanic/test.csv')
pre = clf.predict(preprocessing(df_test))

# 予測結果をファイルに出力
result = pd.DataFrame(df_test['PassengerId'])
result['Survived'] = pre
result
result.to_csv('tree_result.csv', index=False)

予測結果を提出します。

[提出結果]

提出結果は71.291%という正解率になりました。

前回記事のSVMの時よりはましになりましたが、7割程度の正解率ではイマイチですね。

Kaggle(23) - タイタニック(Titanic)コンペ - SVM編

前回記事にてはじめてKaggleコンペの1つタイタニック(Titanic)に結果を提出(Submit)してみました。

結果としては正解率75%ほどで十分な結果とは言えなかったので、手法を少し変えて成績を向上させたいと思います。

今回はアルゴリズムをLightGBMからSVMに変更してみます。

SVMは以前、アヤメの品種を分類するときに使用しました。

Python scikit-learn - 機械学習でアヤメの品種を分類する - https://ailog.site/2020/04/21/0421/


データ読み込み

まずは、Kaggleに準備されているタイタニックの訓練データを読み込みます。

[ソース]

1
2
3
4
import numpy as np
import pandas as pd

df_train = pd.read_csv('/kaggle/input/titanic/train.csv')

データの前処理(不要列の削除・欠損処理・カテゴリ変数の変換)を行う処理を関数化します。

LightGBMとは違ってSVMでは欠損値があると学習できないので、欠損値が1つもなくなるように気を付けます。

[ソース]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# データ前処理
def preprocessing(df):
# 不要な列の削除
df.drop(['Name', 'Ticket', 'Cabin'], axis=1, inplace=True)

# 欠損値処理
df['Age'] = df['Age'].fillna(df['Age'].median())
df['Fare'] = df['Fare'].fillna(df['Fare'].median())
df['Embarked'] = df['Embarked'].fillna('S')

# カテゴリ変数の変換
df = pd.get_dummies(df, columns=['Sex', 'Embarked'])

return df

データを正解ラベルとそれ以外に分けて、学習を行います。

今回はとりあえず1度だけ学習を行い、学習済みモデルを1つだけ作成しました。

[ソース]

1
2
3
4
5
6
7
8
x_titanic = df_train.drop(['Survived'], axis=1)
y_titanic = df_train['Survived']

from sklearn import svm

# データの学習
clf = svm.SVC()
clf.fit(preprocessing(x_titanic), y_titanic)

検証データを読み込み、予測を行います。

予測したデータをコンペ提出用にcsvファイル出力します。

[ソース]

1
2
3
4
5
6
7
8
# データを予測
df_test = pd.read_csv('/kaggle/input/titanic/test.csv')
pre = clf.predict(preprocessing(df_test))

# 予測結果をファイルに出力
result = pd.DataFrame(df_test['PassengerId'])
result['Survived'] = pre
result.to_csv('svm_result.csv', index=False)

出力したsvm_result.csvを提出した結果は次の通りです。


[提出結果]

提出結果は63.397%という正解率になりました。

LightGBMの時よりだいぶ正解率が下がってしまいました。。。

Kaggle(22) - タイタニック(Titanic)コンペに初めての提出

前回記事の3分割交差検証で、正解率90%となかなかの好成績となったので試しにタイタニックコンペに参加してみます。

(KaggleのNotebook環境で実行しています。)


データ読み込み

まずは、Kaggleに準備されているタイタニックの訓練データを読み込みます。

[ソース]

1
2
3
4
5
import numpy as np
import pandas as pd

df_train = pd.read_csv('/kaggle/input/titanic/train.csv')
df_train

[出力結果]


前処理

前処理として、不要列の削除・カテゴリ変数の変換を行います。

(LightGBMでは欠損値処理が不要とのことなので、今回欠損値処理は行いませんでした。)

[ソース]

1
2
3
4
5
6
7
8
9
10
11
# 不要な列の削除
df_train.drop(['Name', 'Ticket', 'Cabin'], axis=1, inplace=True)

# 欠損値処理
# df_train['Age'] = df_train['Age'].fillna(df_train['Age'].median())
# df_train['Embarked'] = df_train['Embarked'].fillna('S')

# カテゴリ変数の変換
df_train = pd.get_dummies(df_train, columns=['Sex', 'Embarked'])

df_train

[出力結果]

訓練データを、生存(正解ラベル)とそれ以外に分割しておきます。

[ソース]

1
2
x_titanic = df_train.drop(['Survived'], axis=1)
y_titanic = df_train['Survived']

分割交差検証で学習

前回記事と同様にLightGBNアルゴリズムの3分割交差検証を使って、学習を行います。

[ソース]

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import lightgbm as lgb
from sklearn.metrics import accuracy_score
from sklearn.model_selection import KFold

# 3分割交差検証を指定しインスタンス化する
kf = KFold(n_splits=3, shuffle=True)

# スコアとモデルを格納するリスト
score_list = []
models = []

for fold_, (train_index, valid_index) in enumerate(kf.split(x_titanic, y_titanic)):
print(f'fold{fold_ + 1}start')
train_x = x_titanic.iloc[train_index]
valid_x = x_titanic.iloc[valid_index]
train_y = y_titanic.iloc[train_index]
valid_y = y_titanic.iloc[valid_index]

# lab.Datasetを使って、trainとvalidを作っておく
lgb_train = lgb.Dataset(train_x, train_y)
lgb_valid = lgb.Dataset(valid_x, valid_y)

# パラメータを定義
lgbm_params = {'objective': 'binary'}

# lgb.trainで学習
evals_result = {}
gbm = lgb.train(params=lgbm_params,
train_set=lgb_train,
valid_sets=[lgb_train, lgb_valid],
early_stopping_rounds=20,
evals_result=evals_result,
verbose_eval=-1) # 学習の状態を表示しない
# valid_xについて推論
oof = (gbm.predict(valid_x) > 0.5).astype(int)
score_list.append(round(accuracy_score(valid_y, oof) * 100, 2))
# 学習が終わったモデルをリストに入れておく
models.append(gbm)
print(f'fold_{fold_ + 1} end\n')

print(score_list, '平均score', round(np.mean(score_list), 2))

[出力結果]

平均スコアは82.04%となりました。


学習済みモデルを使って推論

学習済みモデルを使って、推論を行います。

3回推論を行い予測した生存の平均が0.5より大きい場合に、生存している(1)と予測します。

[ソース]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 検証データの読み込み
df_test = pd.read_csv('/kaggle/input/titanic/test.csv')
df_test.drop(['Name', 'Ticket', 'Cabin'], axis=1, inplace=True)
df_test = pd.get_dummies(df_test, columns=['Sex', 'Embarked'])

# テストデータの予測を格納する行列を作成
test_pred = np.zeros((len(df_test), 3))

for fold, gbm in enumerate(models):
test_pred[:, fold] = gbm.predict(df_test)

result = pd.DataFrame(df_test['PassengerId'])
# 平均が0.5より大きい場合,1(生存)とする
result['Survived'] = (np.mean(test_pred, axis=1) > 0.5).astype(int)
result
result.to_csv('result.csv', index=False)


提出用に作成したcsvファイルは下記のようなフォーマットになります。

[出力結果]


結果提出

予測したcsvファイルを提出(submit)してみます。

[提出結果]

提出結果は75.56%という正解率になりました。

もう少しいい成績なると思っていたのですが、残念です。

Kaggle(21) - 分割交差検証での学習・推論(LightGBM)

前回試したホールドアウト法は、簡単にモデルの性能評価ができるので使いやすいのですがvalidセットを学習に使えていないという欠点があります。

精度が必要な場合には、この問題を解決したk分割交差検証を使うのが一般的です。

データの読み込みと前処理

前回と同様に、タイタニックのデータセットを読み込み、前処理(不要列の削除・欠損値処理・カテゴリ変数の変換)を行っておきます。

[ソース]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import pandas as pd
import seaborn as sns
titanic = sns.load_dataset('titanic')

# 不要な列の削除
titanic.drop(['class', 'who', 'adult_male', 'deck', 'embark_town', 'alive', 'alone'], axis=1, inplace=True)

# 欠損値処理
#titanic.isnull().sum()
titanic['age'] = titanic['age'].fillna(titanic['age'].median())
titanic['embarked'] = titanic['embarked'].fillna('S')

# カテゴリ変数の変換
titanic = pd.get_dummies(titanic, columns=['sex', 'embarked'])

x_titanic = titanic.drop(['survived'], axis=1)
y_titanic = titanic['survived']

x_titanic

[出力結果]

分割交差検証

k分割交差検証のk=3の場合の3分割交差検証を行います。

fold1、fold2、fold3の合計3回の学習・検証を行います。

3分割したデータはtrainセット(訓練用)に2回、validセット(検証用)に1回ずつ使われます。

学習を3回行うので学習済みモデルも3つできます。3つの予測結果ができますので、最後にそれらを1つにまとめています。

[ソース]

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import lightgbm as lgb
import numpy as np
from sklearn.metrics import accuracy_score
from sklearn.model_selection import KFold

# 3分割交差検証を指定しインスタンス化する
kf = KFold(n_splits=3, shuffle=True)

# スコアとモデルを格納するリスト
score_list = []
models = []

for fold_, (train_index, valid_index) in enumerate(kf.split(x_titanic, y_titanic)):
print(f'fold{fold_ + 1}start')
train_x = x_titanic.iloc[train_index]
valid_x = x_titanic.iloc[valid_index]
trains_y = y_titanic.iloc[train_index]
valid_y = y_titanic.iloc[valid_index]

# lab.Datasetを使って、trainとvalidを作っておく
lgb_train = lgb.Dataset(train_x, train_y)
lgb_valid = lgb.Dataset(valid_x, valid_y)

# パラメータを定義
lgbm_params = {'objective': 'binary'}

# lgb.trainで学習
evals_result = {}
gbm = lgb.train(params=lgbm_params,
train_set=lgb_train,
valid_sets=[lgb_train, lgb_valid],
early_stopping_rounds=20,
evals_result=evals_result,
verbose_eval=-1) # 学習の状態を表示しない
# valid_xについて推論
oof = (gbm.predict(valid_x) > 0.5).astype(int)
score_list.append(round(accuracy_score(valid_y, oof) * 100, 2))
# 学習が終わったモデルをリストに入れておく
models.append(gbm)
print(f'fold_{fold_ + 1} end\n')

print(score_list, '平均score', round(np.mean(score_list), 2))

[出力結果]

正解率は90.35%となりました。

なかなかの好成績になったのではないでしょうか。

(実行環境としてGoogleさんのColaboratoryを使用ています。)

Kaggle(20) - ホールドアウト法での学習・推論(LightGBM)

LightGBMというアルゴリズムを使って、タイタニックの生存予測を行います。

LightGBMは、マイクロソフトが開発したアルゴリズムで次のような特徴があります。

  • 決定木ベースの勾配ブースティングを行う
  • 精度が高い
  • 非常に高速
  • 欠損値の補完が不要
  • 特徴のスケーリング(例えば最小値0、最大値1に正規化すること)が不要

前処理

前処理(Preprocessing)では、与えられたデータセットに対してアルゴリズムを用いて予測ができる形式に変換するまでの処理を行います。

具体的には、下記の処理があげられます。

  • 欠損値の対応
  • 外れ値の検出・処理
  • ダミー変数の作成
  • 連続データの離散化
  • 特徴量選択

前処理の仕方によって、予測結果が大きく変わってきますのでとても重要であり、多くの時間を費やす作業となります。

今回は、タイタニックのデータセットに対して、不要列の削除・欠損値処理・カテゴリ変数の変換を行います。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import pandas as pd
import seaborn as sns
titanic = sns.load_dataset('titanic')

# 不要な列の削除
titanic.drop(['class', 'who', 'adult_male', 'deck', 'embark_town', 'alive', 'alone'], axis=1, inplace=True)

# 欠損値処理
#titanic.isnull().sum()
titanic['age'] = titanic['age'].fillna(titanic['age'].median())
titanic['embarked'] = titanic['embarked'].fillna('S')

# カテゴリ変数の変換
titanic = pd.get_dummies(titanic, columns=['sex', 'embarked'])

x_titanic = titanic.drop(['survived'], axis=1)
y_titanic = titanic['survived']

x_titanic
前処理を行ったデータセット

ホールドアウト法での学習

scikit-learnのtrain_test_split関数を用いて、データセットを67%対33%の割合でtrainセット(訓練用)とvalidセット(検証用)に分割し学習を行います。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import lightgbm as lgb
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# x_titanicとy_titanicをtraintとvalidに分割
train_x, valid_x, train_y, valid_y = train_test_split(x_titanic, y_titanic, test_size=0.33, random_state=0)

# lgb.Datasetでtrainとvalidを作っておく
lgb_train = lgb.Dataset(train_x, train_y)
lgb_eval = lgb.Dataset(valid_x, valid_y)

# パラメータを定義
lgbm_params = {'objective': 'binary'}

# lgb.trainで学習
evals_result = {}
gbm = lgb.train(params=lgbm_params,
train_set=lgb_train,
valid_sets=[lgb_train, lgb_eval],
early_stopping_rounds=20,
evals_result=evals_result,
verbose_eval=10)

27roundでlossが最低となり、学習が終了しています。

生存予測

学習したモデルが、validセット(検証用データ)に対してどのくらい予測性能があるか確認します。

1
2
3
# valid_xについて推論
oof = (gbm.predict(valid_x) > 0.5).astype(int)
print('score', round(accuracy_score(valid_y, oof) * 100, 2))

約82.7%の正解率で予測できました。

学習の状況が、eval_resultsに格納されているので学習曲線を表示してみます。

1
2
3
4
5
import matplotlib.pyplot as plt

plt.plot(evals_result['training']['binary_logloss'], label='train_loss')
plt.plot(evals_result['valid_1']['binary_logloss'], label='valid_loss')
plt.legend()
学習曲線

train(訓練)のロスは下がり続けていますが、valid(検証)のロスは20roundあたりから下がりにくくなっています。

ロスが最も少なくなるのが27roundであり、推論はこの27roundで行われます。

predict関数のnum_iterationでroundを指定することができますが、指定しない場合はbestのroundが使われます。

(実行環境としてGoogleさんのColaboratoryを使用ています。)

Kaggle(19) - カテゴリ変数の変換(One-Hotエンコーディング)

タイタニック・データセットの性別(sex)や乗船地(embarked)は「男・女」「C・Q・S」というカテゴリを表しており、カテゴリ間の大小関係はありません。

これらの変数のことをカテゴリ変数と呼びますが、文字のままでは扱うのが難しいので何らかの変換処理が必要となります。

データの読み込み

タイタニックのデータセットを読み込み、見やすくするために不要な列を削除しておきます。

1
2
3
4
5
6
7
import seaborn as sns
titanic = sns.load_dataset('titanic')

# 不要な列の削除
titanic.drop(['sibsp', 'parch', 'class', 'who', 'adult_male', 'deck', 'embark_town', 'alive', 'alone'], axis=1, inplace=True)

titanic

カテゴリ変数の変換(One-Hotエンコーディング)

性別(sex)項目と乗船地(embarked)項目のカテゴリ変数を変換します。

1
2
import pandas as pd
pd.get_dummies(titanic, columns=['sex', 'embarked'])

Pandasのget_dummies関数を使うと、sex項目の代わりにsex_female / sex_male項目が追加され、embarked項目の代わりにembarked_C / embarked_Q / embarked_S項目が追加されます。

該当する場合に1、非該当の場合に0が設定されます。

このような変換手法をOne-Hotエンコーディングといいます。

(実行環境としてGoogleさんのColaboratoryを使用ています。)

Kaggle(18) - Pandas Profileによる探索的データ解析(EDA)

Pandas Profileというライブラリを使うと、数行のコードを書くだけでデータセットの概要や特徴量を決められたフォーマットで分かりやすく表示することができます。

Pandas Profileのアップデート

GoogleさんのColaboratoryでPandas Profileを実行するとバージョンの問題でエラーになるので、Pandas Profileをアップデートしておきます。

1
!pip install -U pandas_profiling

アップデート完了後に一旦ランタイムを再起動します。(Restart Runtimeボタンを押下)


Pandas Profileの実行

タイタニックのデータセットを読み込み、Pandas Profileを実行します。

なお、データ量の問題でメモリ不足のエラーが発生するので、いくつか不要そうな項目を削除しています。

1
2
3
4
5
6
7
8
9
import seaborn as sns
titanic = sns.load_dataset('titanic')

# 不要なカラムの削除
titanic.drop(['deck', 'embark_town', 'alive', 'alone'], axis=1, inplace=True)

import pandas as pd
import pandas_profiling as pdp
pdp.ProfileReport(titanic)

Pandas Profileの内容確認

Overview項目では、データセットの概要を確認できます。

  • 11列 891行のデータであること。
  • 179の欠損値(Missing)があり、全体の1.8%であること。
  • Variable Typesではカテゴリデータ(Categorical)が6項目、数値型(Numeric)が4項目、ブール型(Boolean)が1項目あること。


Variables項目では、各データ型に応じて統計量やヒストグラムが表示されます。

Toggle detailsボタンを押すと、さらに詳細なデータ(統計情報)が表示されます



Interactions項目では、変数を指定し散布図を確認することができます。



Correlations項目では、ヒートマップが表示されます。

ヒートマップは2変数間の相関係数の値を色にしたものであり、変数間の相関を一目でみることができます。



Missing Values項目では、欠損値の情報を見ることができます。

Samples項目では、先頭の10行と最後の10行が表示されます。



Duplication Rows項目では、重複行の情報を確認することができます。



Pandas Profileを使うと一気に各データの特徴を把握することができるので本当に便利ですね。

またto_file関数を使うと、ファイル出力(Html)できますのでプロファイリング結果を受け渡しする場合に有益かと思います。

1
profile.to_file('Profiling.html')

(実行環境としてGoogleさんのColaboratoryを使用ています。)