自分のキャリアをあれこれ考えながら、Pythonで様々なデータを分析していくブログです

(その4-6) タイタニックの乗客の生存有無をナイーブベイズで予測してみた

Data Analytics
Data Analytics

前回、ロジスティック回帰CVで76.7%の精度でした。

(その4-5) タイタニックの乗客の生存有無をロジスティック回帰CVで予測してみた。
前回、KNNで76.5%の精度でした。 今回はロジスティック回帰CVを使って予測してみようと思います。 (その4-2) タイタニックの乗客の生存有無をロジスティック回帰分析で予測してみたと似ていますが今回はロジスティック回帰CVを使ってみま...

今回はナイーブベイズを使って予測してみようと思います。

The sklearn.naive_bayes module implements Naive Bayes algorithms. These are supervised learning methods based on applying Bayes’ theorem with strong (naive) feature independence assumptions.
引用: https://scikit-learn.org/stable/modules/classes.html

sklearnのドキュメントにはナイーブベイズはベイズの定理が基礎になっていて、変数間に強い独立性を仮定している教師ありのメソッドと説明されています。

以前RecSysというリコメンドシステムの学会に参加したとき(発表したわけではありません 笑)、とある企業の発表を聞く機会がありました。

発表の中でユーザー属性の推定をする箇所があったかと思うのですが、その時利用されていたのがナイーブベイズでした。

実装しやすく変数間に独立性を仮定しなければいけないが実際は独立していなくても使ってみると精度は悪くなかったと言ってたかと思います。

その発表を聞いて以来、ヒノマルクもナイーブベイズのファンになり多様するようになりました 笑

You do not have to normalize the probabilities if you only care about knowing which class your input most likely belongs to.
If you do want the class probabilities, then you indeed need to normalize:
引用: https://stats.stackexchange.com/questions/249762/with-the-naive-bayes-classifier-why-do-we-have-to-normalize-the-probabilities-a

またナイーブベイズを扱う上でのデータの標準化に関してですが、分類する上では気にしなくても良さそうですがクラスへの所属確率が必要な場合は標準化した方がいいとのことです。

それではやってみましょう。

全部で5種類のナイーブベイズがあったので全て試します。

スポンサーリンク

評価指標

タイタニックのデータセットは生存有無を正確に予測できた乗客の割合(Accuracy)を評価指標としています。

スポンサーリンク

分析用データの準備

事前に欠損値処理や特徴量エンジニアリングを実施してデータをエクスポートしています。

本記事と同じ結果にするためには事前に下記記事を確認してデータを用意してください。

タイタニックのモデリング用データの作成まとめ
(その3-5) タイタニックのデータセットの変数選択にてモデリング用のデータを作成し、エクスポートするコードを記載していましたが分かりずらかったので簡略しまとめました。 上から順に流していけばtitanic_train.csvとtitani...

学習データと評価データの読み込み

import pandas as pd
import numpy as np
# タイタニックデータセットの学習用データと評価用データの読み込み
df_train = pd.read_csv("/Users/hinomaruc/Desktop/notebooks/titanic/titanic_train.csv")
df_eval = pd.read_csv("/Users/hinomaruc/Desktop/notebooks/titanic/titanic_eval.csv")

概要確認

# 概要確認
df_train.info()
Out[0]

    RangeIndex: 891 entries, 0 to 890
    Data columns (total 22 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            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       891 non-null    object
     12  FamilyCnt      891 non-null    int64
     13  SameTicketCnt  891 non-null    int64
     14  Pclass_str_1   891 non-null    float64
     15  Pclass_str_2   891 non-null    float64
     16  Pclass_str_3   891 non-null    float64
     17  Sex_female     891 non-null    float64
     18  Sex_male       891 non-null    float64
     19  Embarked_C     891 non-null    float64
     20  Embarked_Q     891 non-null    float64
     21  Embarked_S     891 non-null    float64
    dtypes: float64(10), int64(7), object(5)
    memory usage: 153.3+ KB
# 概要確認
df_eval.info()
Out[0]

    RangeIndex: 418 entries, 0 to 417
    Data columns (total 21 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            418 non-null    float64
     5   SibSp          418 non-null    int64
     6   Parch          418 non-null    int64
     7   Ticket         418 non-null    object
     8   Fare           418 non-null    float64
     9   Cabin          91 non-null     object
     10  Embarked       418 non-null    object
     11  Pclass_str_1   418 non-null    float64
     12  Pclass_str_2   418 non-null    float64
     13  Pclass_str_3   418 non-null    float64
     14  Sex_female     418 non-null    float64
     15  Sex_male       418 non-null    float64
     16  Embarked_C     418 non-null    float64
     17  Embarked_Q     418 non-null    float64
     18  Embarked_S     418 non-null    float64
     19  FamilyCnt      418 non-null    int64
     20  SameTicketCnt  418 non-null    int64
    dtypes: float64(10), int64(6), object(5)
    memory usage: 68.7+ KB

# 描画設定
import seaborn as sns
from matplotlib import ticker
import matplotlib.pyplot as plt
sns.set_style("whitegrid")
from matplotlib import rcParams
rcParams['font.family'] = 'Hiragino Sans' # Macの場合
#rcParams['font.family'] = 'Meiryo' # Windowsの場合
#rcParams['font.family'] = 'VL PGothic' # Linuxの場合
rcParams['xtick.labelsize'] = 12       # x軸のラベルのフォントサイズ
rcParams['ytick.labelsize'] = 12       # y軸のラベルのフォントサイズ
rcParams['axes.labelsize'] = 18        # ラベルのフォントとサイズ
rcParams['figure.figsize'] = 18,8      # 画像サイズの変更(inch)

モデリング用に学習用データを訓練データとテストデータに分割

# 訓練データとテストデータに分割する。
from sklearn.model_selection import train_test_split
x_train, x_test = train_test_split(df_train, test_size=0.20,random_state=100)

# 説明変数
FEATURE_COLS=[
   'Age'
 , 'Fare'
 , 'SameTicketCnt'
 , 'Pclass_str_1'
 , 'Pclass_str_3'
 , 'Sex_female'
 , 'Embarked_Q'
 , 'Embarked_S'
]

X_train = x_train[FEATURE_COLS] # 説明変数 (train)
Y_train = x_train["Survived"] # 目的変数 (train)
X_test = x_test[FEATURE_COLS] # 説明変数 (test)
Y_test = x_test["Survived"] # 目的変数 (test)
スポンサーリンク

ナイーブベイズ (GaussianNB)

モデル作成 (GaussianNB)

# https://scikit-learn.org/stable/modules/generated/sklearn.naive_bayes.GaussianNB.html
from sklearn.naive_bayes import GaussianNB
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
pipeline = make_pipeline(StandardScaler(), GaussianNB())
fit_pipeline = pipeline.fit(X_train,Y_train)
# 訓練データへの当てはまりを確認
# Return the mean accuracy on the given test data and labels.
fit_pipeline.score(X_train,Y_train)
Out[0]

    0.7935393258426966

# テストデータへの当てはまりを確認
# Return the mean accuracy on the given test data and labels.
fit_pipeline.score(X_test,Y_test)
Out[0]

    0.7988826815642458

# モデルパラメータ一覧
fit_pipeline.get_params()
Out[0]

    {'memory': None,
     'steps': [('standardscaler', StandardScaler()), ('gaussiannb', GaussianNB())],
     'verbose': False,
     'standardscaler': StandardScaler(),
     'gaussiannb': GaussianNB(),
     'standardscaler__copy': True,
     'standardscaler__with_mean': True,
     'standardscaler__with_std': True,
     'gaussiannb__priors': None,
     'gaussiannb__var_smoothing': 1e-09}

model_pipeline = fit_pipeline.named_steps["gaussiannb"] # or pipeline.steps[1][1]
model_pipeline.get_params()
Out[0]

    {'priors': None, 'var_smoothing': 1e-09}

精度確認 (GaussianNB)

# https://scikit-learn.org/stable/modules/generated/sklearn.metrics.ConfusionMatrixDisplay.html
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.metrics import ConfusionMatrixDisplay
from sklearn.metrics import confusion_matrix

print(confusion_matrix(Y_test,fit_pipeline.predict(X_test)))

ConfusionMatrixDisplay.from_estimator(fit_pipeline,X_test,Y_test,cmap="Reds",display_labels=["非生存","生存"],normalize="all")
plt.show()
Out[0]

[[92 12]
[24 51]]

png

Kaggleへ予測データをアップロード (GaussianNB)

df_eval["Survived"] = fit_pipeline.predict(df_eval[FEATURE_COLS])
df_eval[["PassengerId","Survived"]].to_csv("titanic_submission.csv",index=False)
!/Users/hinomaruc/Desktop/notebooks/my-venv/bin/kaggle competitions submit -c titanic -f titanic_submission.csv -m "model #006. gaussiannb (normalized)"
Out[0]

    100%|████████████████████████████████████████| 2.77k/2.77k [00:04<00:00, 598B/s]
    Successfully submitted to Titanic - Machine Learning from Disaster

Kaggleでの精度確認の結果
0.74641

まずまずな結果です。

スポンサーリンク

ナイーブベイズ (ComplementNB)

モデル作成 (ComplementNB)

# https://scikit-learn.org/stable/modules/generated/sklearn.naive_bayes.ComplementNB.html
from sklearn.naive_bayes import ComplementNB
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import MinMaxScaler
pipeline = make_pipeline(MinMaxScaler(), ComplementNB())

StandardScalerで標準化してfitしたら下記エラーが発生しました。

ValueError: Negative values in data passed to ComplementNB (input X)

そのため、0から1の範囲にスケールするMinMaxScalerを使用しました。

fit_pipeline = pipeline.fit(X_train,Y_train)
# Return the mean accuracy on the given data and labels.
print("train",fit_pipeline.score(X_train,Y_train))
print("test",fit_pipeline.score(X_test,Y_test))
Out[0]
    train 0.7443820224719101
    test 0.776536312849162
# モデルパラメータ一覧
fit_pipeline.get_params()
Out[0]

    {'memory': None,
     'steps': [('minmaxscaler', MinMaxScaler()), ('complementnb', ComplementNB())],
     'verbose': False,
     'minmaxscaler': MinMaxScaler(),
     'complementnb': ComplementNB(),
     'minmaxscaler__clip': False,
     'minmaxscaler__copy': True,
     'minmaxscaler__feature_range': (0, 1),
     'complementnb__alpha': 1.0,
     'complementnb__class_prior': None,
     'complementnb__fit_prior': True,
     'complementnb__norm': False}

model_pipeline = fit_pipeline.named_steps["complementnb"] # or pipeline.steps[1][1]
model_pipeline.get_params()
Out[0]

    {'alpha': 1.0, 'class_prior': None, 'fit_prior': True, 'norm': False}

精度確認 (ComplementNB)

# https://scikit-learn.org/stable/modules/generated/sklearn.metrics.ConfusionMatrixDisplay.html
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.metrics import ConfusionMatrixDisplay
from sklearn.metrics import confusion_matrix

print(confusion_matrix(Y_test,fit_pipeline.predict(X_test)))

ConfusionMatrixDisplay.from_estimator(fit_pipeline,X_test,Y_test,cmap="Reds",display_labels=["非生存","生存"],normalize="all")
plt.show()
Out[0]

[[79 25]
[15 60]]

png

Kaggleへ予測データをアップロード (ComplementNB)

df_eval["Survived"] = fit_pipeline.predict(df_eval[FEATURE_COLS])
df_eval[["PassengerId","Survived"]].to_csv("titanic_submission.csv",index=False)
!/Users/hinomaruc/Desktop/notebooks/my-venv/bin/kaggle competitions submit -c titanic -f titanic_submission.csv -m "model #006. complementnb (normalized)"
Out[0]

    100%|████████████████████████████████████████| 2.77k/2.77k [00:05<00:00, 505B/s]
    Successfully submitted to Titanic - Machine Learning from Disaster

Kaggleでの精度確認の結果

0.70574

結構下がってしまいました。

スポンサーリンク

ナイーブベイズ (CategoricalNB)

モデル作成 (CategoricalNB)

# https://scikit-learn.org/stable/modules/generated/sklearn.naive_bayes.CategoricalNB.html
from sklearn.naive_bayes import CategoricalNB
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import MinMaxScaler
pipeline = make_pipeline(MinMaxScaler(), CategoricalNB())

StandardScalerで標準化してfitしたら下記エラーが発生しました。

ValueError: Negative values in data passed to CategoricalNB (input X)

そのため、0から1の範囲にスケールするMinMaxScalerを使用しました。

fit_pipeline = pipeline.fit(X_train,Y_train)
# Return the mean accuracy on the given data and labels.
print("train",fit_pipeline.score(X_train,Y_train))
print("test",fit_pipeline.score(X_test,Y_test))
Out[0]

    train 0.8019662921348315
    test 0.7988826815642458

# モデルパラメータ一覧
fit_pipeline.get_params()
Out[0]

    {'memory': None,
     'steps': [('minmaxscaler', MinMaxScaler()),
      ('categoricalnb', CategoricalNB())],
     'verbose': False,
     'minmaxscaler': MinMaxScaler(),
     'categoricalnb': CategoricalNB(),
     'minmaxscaler__clip': False,
     'minmaxscaler__copy': True,
     'minmaxscaler__feature_range': (0, 1),
     'categoricalnb__alpha': 1.0,
     'categoricalnb__class_prior': None,
     'categoricalnb__fit_prior': True,
     'categoricalnb__min_categories': None}

model_pipeline = fit_pipeline.named_steps["categoricalnb"] # or pipeline.steps[1][1]
model_pipeline.get_params()
Out[0]

    {'alpha': 1.0, 'class_prior': None, 'fit_prior': True, 'min_categories': None}

精度確認 (CategoricalNB)

# https://scikit-learn.org/stable/modules/generated/sklearn.metrics.ConfusionMatrixDisplay.html
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.metrics import ConfusionMatrixDisplay
from sklearn.metrics import confusion_matrix

print(confusion_matrix(Y_test,fit_pipeline.predict(X_test)))

ConfusionMatrixDisplay.from_estimator(fit_pipeline,X_test,Y_test,cmap="Reds",display_labels=["非生存","生存"],normalize="all")
plt.show()
Out[0]

[[95 9]
[27 48]]

png

Kaggleへ予測データをアップロード (CategoricalNB)

df_eval["Survived"] = fit_pipeline.predict(df_eval[FEATURE_COLS])
df_eval[["PassengerId","Survived"]].to_csv("titanic_submission.csv",index=False)
!/Users/hinomaruc/Desktop/notebooks/my-venv/bin/kaggle competitions submit -c titanic -f titanic_submission.csv -m "model #006. CategoricalNB (minmax scaled)"
Out[0]

    100%|████████████████████████████████████████| 2.77k/2.77k [00:06<00:00, 457B/s]
    Successfully submitted to Titanic - Machine Learning from Disaster

Kaggleでの精度確認の結果
0.76315

現時点の暫定1位の精度が76.7%なので、かなり近いです。
デフォルトの設定でこの精度はかなりいい線をいってるのでないでしょうか。

スポンサーリンク

ナイーブベイズ (MultinomialNB)

モデル作成 (MultinomialNB)

# https://scikit-learn.org/stable/modules/generated/sklearn.naive_bayes.MultinomialNB.html
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import MinMaxScaler
pipeline = make_pipeline(MinMaxScaler(), MultinomialNB())

StandardScalerで標準化してfitしたら下記エラーが発生しました。

ValueError: Negative values in data passed to CategoricalNB (input X)

そのため、0から1の範囲にスケールするMinMaxScalerを使用しました。

fit_pipeline = pipeline.fit(X_train,Y_train)
# Return the mean accuracy on the given data and labels.
print("train",fit_pipeline.score(X_train,Y_train))
print("test",fit_pipeline.score(X_test,Y_test))
Out[0]

    train 0.7865168539325843
    test 0.770949720670391

# モデルパラメータ一覧
fit_pipeline.get_params()
Out[0]

    {'memory': None,
     'steps': [('minmaxscaler', MinMaxScaler()),
      ('multinomialnb', MultinomialNB())],
     'verbose': False,
     'minmaxscaler': MinMaxScaler(),
     'multinomialnb': MultinomialNB(),
     'minmaxscaler__clip': False,
     'minmaxscaler__copy': True,
     'minmaxscaler__feature_range': (0, 1),
     'multinomialnb__alpha': 1.0,
     'multinomialnb__class_prior': None,
     'multinomialnb__fit_prior': True}

model_pipeline = fit_pipeline.named_steps["multinomialnb"] # or pipeline.steps[1][1]
model_pipeline.get_params()
Out[0]

    {'alpha': 1.0, 'class_prior': None, 'fit_prior': True}

精度確認 (MultinomialNB)

# https://scikit-learn.org/stable/modules/generated/sklearn.metrics.ConfusionMatrixDisplay.html
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.metrics import ConfusionMatrixDisplay
from sklearn.metrics import confusion_matrix

print(confusion_matrix(Y_test,fit_pipeline.predict(X_test)))

ConfusionMatrixDisplay.from_estimator(fit_pipeline,X_test,Y_test,cmap="Reds",display_labels=["非生存","生存"],normalize="all")
plt.show()
Out[0]

[[98 6]
[35 40]]

png

Kaggleへ予測データをアップロード (MultinomialNB)

df_eval["Survived"] = fit_pipeline.predict(df_eval[FEATURE_COLS])
df_eval[["PassengerId","Survived"]].to_csv("titanic_submission.csv",index=False)
!/Users/hinomaruc/Desktop/notebooks/my-venv/bin/kaggle competitions submit -c titanic -f titanic_submission.csv -m "model #006. multinomialnb (minmax scaled)"
Out[0]

    100%|████████████████████████████████████████| 2.77k/2.77k [00:04<00:00, 591B/s]
    Successfully submitted to Titanic - Machine Learning from Disaster

Kaggleでの精度確認の結果
0.75598
スポンサーリンク

ナイーブベイズ (BernoulliNB)

モデル作成 (BernoulliNB)

# https://scikit-learn.org/stable/modules/generated/sklearn.naive_bayes.GaussianNB.html
from sklearn.naive_bayes import BernoulliNB
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
pipeline = make_pipeline(StandardScaler(), BernoulliNB())
fit_pipeline = pipeline.fit(X_train,Y_train)
# Return the mean accuracy on the given data and labels.
print("train",fit_pipeline.score(X_train,Y_train))
print("test",fit_pipeline.score(X_test,Y_test))
Out[0]

    train 0.7485955056179775
    test 0.7374301675977654

# モデルパラメータ一覧
fit_pipeline.get_params()
Out[0]

    {'memory': None,
     'steps': [('standardscaler', StandardScaler()),
      ('bernoullinb', BernoulliNB())],
     'verbose': False,
     'standardscaler': StandardScaler(),
     'bernoullinb': BernoulliNB(),
     'standardscaler__copy': True,
     'standardscaler__with_mean': True,
     'standardscaler__with_std': True,
     'bernoullinb__alpha': 1.0,
     'bernoullinb__binarize': 0.0,
     'bernoullinb__class_prior': None,
     'bernoullinb__fit_prior': True}

model_pipeline = fit_pipeline.named_steps["bernoullinb"] # or pipeline.steps[1][1]
model_pipeline.get_params()
Out[0]

    {'alpha': 1.0, 'binarize': 0.0, 'class_prior': None, 'fit_prior': True}

精度確認 (BernoulliNB)

# https://scikit-learn.org/stable/modules/generated/sklearn.metrics.ConfusionMatrixDisplay.html
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.metrics import ConfusionMatrixDisplay
from sklearn.metrics import confusion_matrix

print(confusion_matrix(Y_test,fit_pipeline.predict(X_test)))

ConfusionMatrixDisplay.from_estimator(fit_pipeline,X_test,Y_test,cmap="Reds",display_labels=["非生存","生存"],normalize="all")
plt.show()
Out[0]

[[90 14]
[33 42]]

png

Kaggleへ予測データをアップロード (BernoulliNB)

df_eval["Survived"] = fit_pipeline.predict(df_eval[FEATURE_COLS])
df_eval[["PassengerId","Survived"]].to_csv("titanic_submission.csv",index=False)
!/Users/hinomaruc/Desktop/notebooks/my-venv/bin/kaggle competitions submit -c titanic -f titanic_submission.csv -m "model #006. bernoullinb (normalized)"
Out[0]
    100%|████████████████████████████████████████| 2.77k/2.77k [00:03<00:00, 729B/s]
    400 - Bad Request
Kaggleでの精度確認の結果
0.72248
スポンサーリンク

まとめ

ベイズはよく業務で使いますが、ナイーブベイズにも色々名称が付いていたのは知らなかったです 笑

タイトルとURLをコピーしました