【XGBoost】糖尿病データを機械学習してみた

この記事ではPythonの機械学習フレームワークXGBoostを使って、糖尿病の患者を推定するコードを書いてみたいと思います。

機械学習というと、K-NN(K- Nearest Neighbor)やランダムフォレスト、SVM(Support Vector Machine) が有名です。

実は私も、XGBoostを使ったことがありませんでしたが、ふとネットで見かけて使ってみたら思ったよりも精度が良かったのでご紹介したいと思います。

[toc]

事前準備

まずはデータセットの収集から。

糖尿病データは以下からダウンロードしました。

https://www.kaggle.com/uciml/pima-indians-diabetes-database

次に、XGBoostをインストールします。

XGBoostは調べてみたら、conda-forgeのチャンネルにあるみたい。

いつもなら下記のようにコマンドでパッケージをインストールしています。

「conda install -c チャンネル名 パッケージ名」

でも、よくよく調べてみたらAnaconda Navigatorでも、チャンネルを追加することができたんですよ。(今更感)

channelで、以下のように”conda-forge”を入力して追加するだけです。

これで、Anaconda NavigatorからもXGBoostが検索&インストールできました。

学習&ハイパーパラメータ探索

データを読み込んで、特徴量とラベルに分割します。

その後にGridSearchCVを使って、ハイパーパラメータ、つまり学習時の最良なパラメータを探索します。

探索する時の可変パラメータを、variable_params, 固定パラメータを、static_paramsに格納します。

最後に、精度が最も良かった時の精度とパラメータを出力して終了です。

import numpy as np
import pandas as pd
from xgboost.sklearn import XGBClassifier 

from sklearn.model_selection import GridSearchCV


data=pd.read_csv("diabetes.csv")

print(data.describe())
print(data.keys())

X_data=data.drop(["Outcome"],axis=1)
y_data=data["Outcome"]

variable_params = {'max_depth':[2,4,6,10], 'n_estimators':[5, 10, 20, 25], 'learning_rate':np.linspace(1e-16, 1 , 3)}
static_params = {'objective':'multi:softmax','num_class':4, 'silent':1}

bst_grid = GridSearchCV (
        estimator = XGBClassifier(**static_params),
        param_grid = variable_params,
        scoring = "accuracy"
        )

bst_grid.fit(X_data, y_data)

print("Best Accuracy:{}".format(bst_grid.best_score_))
for key,value in bst_grid.best_params_.items():
    print("{}:{}".format(key,value))

出力は以下の通り。

Best Accuracy:0.7734375
learning_rate:0.5
max_depth:4
n_estimators:10

以下の記事で、Kerasで同じデータセットに対してディープラーニングで学習させてみたのですが、その時は73%程度でした。

【Keras】ディープラーニングで糖尿病を判別する

より短いコードで高い精度が出たので、XGBoostさん優秀ですね。

特徴量エンジニアリング

次に、どの特徴量が重要か判別するためのコードを書いていきたいと思います。

これを特徴量エンジニアリング分析といったりします。

DMatrixというのは、XGBoostで使うためのデータマトリックスのこと。

メモリの使用量や学習スピードが最適化されているようです。

https://xgboost.readthedocs.io/en/latest/python/python_api.html#xgboost.DMatrix

import xgboost as xgb
from sklearn.model_selection import train_test_split
import pandas as pd
%matplotlib inline

data = pd.read_csv("diabetes.csv")
print(data.describe())
print(data.keys())

X_data=data.drop(["Outcome"],axis=1)
y_data=data["Outcome"]

dtrain = xgb.DMatrix(X_data,y_data)

params = {
        'objective':'binary:logistic',
        'max-depth':2,
        'silent':1,
        'eta':0.5
        }

num_rounds = 5

bst = xgb.train(params,dtrain,num_rounds)

tdump = bst.get_dump(fmap = "./featmap.txt", with_stats = True)

for trees in tdump:
    print(trees)
  
    
xgb.plot_importance(bst, importance_type = 'gain', xlabel = 'Gain')

get_dumpを使用することで、パラメータをテキストファイルに書き出すことができます。

plot_importanceで、特徴量の重要度をグラフ化して出力します。(Matplotlibが必要です。)

グルコース(血糖値)が糖尿病に最も関係していることがわかりました。

糖尿病の人は血糖値が高いと言われています。

血糖値だけを見てもある程度は判断できてしまうのでしょう。

BMIや年も、糖尿病と判断するのに重要だと分かりました。

このようにグラフ化してみると、何が重要な特徴量がすぐにわかって面白いですね。

おわり。

参考

https://www.kaggle.com/uciml/pima-indians-diabetes-database

https://towardsdatascience.com/model-tuning-feature-engineering-using-xgboost-ef819bccc82e

ABOUTこの記事をかいた人

個人アプリ開発者。Python、Swift、Unityのことを発信します。月間2.5万PVブログ運営。 Twitter:@yamagablog