XGBoost + multiple metric【Kaggle】Text Mining Bag of Words Meets Bags of Popcorn

別verでRandomForest.verで書いた記事がありますが、この記事ではXGBoost.verで再度記事を書きます。
前回よりもmetricとモデル解釈を厚めに書いてます。
まだ途中のものもありますが随時更新します。

# importライブラリ

```python
import numpy as np 
import pandas as pd

#モデル系
import xgboost as xgb
#install出来ていない場合は下記コマンドを入力
#conda install -c anaconda py-xgboost

#model fit後に謎のディレクトリ変更が行われるためLight GBMは今回利用しない
#import lightgbm as lgb

from sklearn import datasets
from sklearn.model_selection import train_test_split

#自然言語処理系
from bs4 import BeautifulSoup
import re
import nltk
from nltk.corpus import stopwords
#stopwordsを初importする場合は下記コマンドを実行
#nltk.download('stopwords')
from sklearn.feature_extraction.text import CountVectorizer

#metric
from sklearn.metrics import accuracy_score
from sklearn.metrics import confusion_matrix
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import f1_score
from sklearn.metrics import roc_curve
from sklearn.metrics import roc_auc_score
```

#　データ読み込み/前処理
ここからは言語処理のデータ処理について記述します。
前回のverでこの辺りは詳しく書いているので詳細は下記をご覧ください
[【Kaggle】Text Mining Bag of Words Meets Bags of Popcorn](https://qiita.com/D_U_8240/items/0784b7c3d86468f71334)

```python
#データの読み込み
train001 = pd.read_csv("labeledTrainData.tsv",delimiter="\t")
train001.head()
```
↓出力結果
![Screen Shot 2020-05-10 at 11.54.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172677/c148f859-9fe6-b6f6-160a-e290a83fd39e.png)

```python
#文字列データの綺麗化関数の定義
def review_to_words(raw_reviews):
    #1.htmlのタグ消し
    review_text = BeautifulSoup(raw_reviews).get_text()
    #2.文字以外(?,!)の消去
    letters_only = re.sub("[^a-zA-Z]", " ", review_text)
    #3.全ての文字を小文字にして単語に分割
    words = letters_only.lower().split()
    #4.Stopwords Listの作成
    stops = set(stopwords.words("english"))
    #5.Remove Stopwords
    meaningful_words = [w for w in words if not w in stops]
    #6.文にして結果を返す
    return(" ".join(meaningful_words))
````

```python
#上記の関数を全てのreviewに適用し、データを綺麗か
for row in train001.index[:]:
    train001.loc[row,"clean_review"] = review_to_words(train001.loc[row,"review"])
```

```python
#CountVectorizerでclean_reviewをベクトル化
vectorizer = CountVectorizer(analyzer="word",tokenizer=None,preprocessor=None,stop_words=None,max_features=5000)

#25,000review x 5,000特徴量のデータセットを作成
train002 = vectorizer.fit_transform(train001["clean_review"])
```

# XGBoostモデルの構築

```python
#XGBoost分類モデルの宣言
model = xgb.XGBClassifier()

#モデルを構築
#model.fit(特徴量、教師データ)
model.fit(train002,train001["sentiment"])
```
↓モデルを構築することでデフォルトのチューニング情報が表示されます。
![Screen Shot 2020-05-10 at 12.02.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172677/723b0a04-7e5e-ac95-8496-2196e34d239e.png)

# モデルの実行

```python
#後のモデル評価のためにtrainデータに対してモデルを実行
#予測ラベルの割り振り
y_pred_train = model.predict(train002)

#予測確率の計算
y_pred_prob_train = model.predict_proba(train002)

#元データへの結合
#結合のためにデータフレームに変換
y_pred_train_df = pd.DataFrame(y_pred_train)
y_pred_prob_train_df = pd.DataFrame(y_pred_prob_train)
train_result = pd.concat([train001,y_pred_train_df,y_pred_prob_train_df],axis=1)
train_result
```
↓予測ラベルとそれぞれのラベルに対する確率が結合された表ができる
![Screen Shot 2020-05-10 at 12.09.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172677/dafe2b09-601a-764c-10f3-452fe036b62d.png)

#モデルの評価
モデル評価のために下記を実行
accuracy
confusion_matrix
precision_score
recall_score
f1_score
ROC Curve
AUC

参考
[scikit-learn でクラス分類結果を評価する
](https://pythondatascience.plavox.info/scikit-learn/%E5%88%86%E9%A1%9E%E7%B5%90%E6%9E%9C%E3%81%AE%E3%83%A2%E3%83%87%E3%83%AB%E8%A9%95%E4%BE%A1)
[scikit-learnでROC曲線とそのAUCを算出](https://note.nkmk.me/python-sklearn-roc-curve-auc-score/)

##accuracy
```python
#accuracy
from sklearn.metrics import accuracy_score
#accuracy_score(教師ラベル,予測ラベル)
accuracy_score(train001["sentiment"],y_pred_train)
```
![Screen Shot 2020-05-10 at 12.14.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172677/a53b8aa1-5f49-ffce-a364-5734e391bfe5.png)

##confusion_matrics
```python
#confusion_matrics
from sklearn.metrics import confusion_matrix
#confusion_matrix(教師ラベル,予測ラベル)
confusion_matrix(train001["sentiment"],y_pred_train)
```
![Screen Shot 2020-05-10 at 12.16.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172677/ed0842b4-a75d-210e-254b-709e5368f864.png)

##precision_score
```python
#precision_score
from sklearn.metrics import precision_score
#precision_score(教師ラベル,予測ラベル)
precision_score(train001["sentiment"],y_pred_train)
```
![Screen Shot 2020-05-10 at 12.17.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172677/a04a2e0a-bc81-02d6-ed60-d81173902bd6.png)

##recall_score
```python
#recall_score
from sklearn.metrics import recall_score
#recall_score(教師ラベル,予測ラベル)
recall_score(train001["sentiment"],y_pred_train)
```
![Screen Shot 2020-05-10 at 12.18.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172677/f262af9c-8c3a-40c3-dcf3-80c40ba10994.png)

##f1_score
```python
#f1_score
from sklearn.metrics import f1_score
#f1_score(教師ラベル,予測ラベル)
f1_score(train001["sentiment"],y_pred_train)
```
![Screen Shot 2020-05-10 at 12.19.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172677/96724111-d565-dd8f-e1a7-e17ae205bdb4.png)

##roc_curve
```python
#roc_curve
from sklearn.metrics import roc_curve
#roc_curve(教師ラベル、1になる確率)
fpr, tpr, thresholds = roc_curve(train001["sentiment"],y_pred_prob_train_df[1])

#roc_curveの描画
import matplotlib.pyplot as plt
plt.plot(fpr, tpr, marker='o')
plt.xlabel('FPR: False positive rate')
plt.ylabel('TPR: True positive rate')
plt.grid()
```
![Screen Shot 2020-05-10 at 12.24.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172677/31710b10-b015-b669-7004-89b4b61ecdd6.png)

##auc
```python
#aucの計算
#roc_curveに囲まれた面積を表す。1に近ければ良いモデル
from sklearn.metrics import roc_auc_score
#roc_auc_score(教師ラベル、1になる確率)
print(roc_auc_score(train001["sentiment"], y_pred_prob_train_df[1]))
```
![Screen Shot 2020-05-10 at 12.26.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172677/a07b1f7a-f202-ed28-bc91-f1163551cceb.png)

モデル評価の総括としては、NoTuningに関わらず非常に高性能なモデルの構築が出来ているといえるでしょう。

#モデル解釈
モデル解釈のために下記を実行
feature importance
permutation importance
SHAP

##feature importance
```python
#feature importance
#xgb.plot_importance(モデル名)
xgb.plot_importance(model)
```
↓よく分からない、、表示方法を検討
![Screen Shot 2020-05-10 at 12.29.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172677/a082c40a-f40c-69d1-2e35-99cfddf437cb.png)

```python
#実際のfeature importanceの値を確認したい場合のコード例
# Feature importance
importance_list = []
importance_df = pd.DataFrame({"gain":model.feature_importances_}, index=train_feature.columns).sort_values("gain", ascending=False)
importance_list += [importance_df]
print("[Importance]")
display(importance_df)
```

# モデルのsave/load

## モデルのsave

```python
#XGBoostの場合
model1 = xgb.XGBClassifier()
model1.fit(X, Y)

model1.save_model('./xgb1.model')

# 保存したmodel1をロードして使用する
model2 = xgb.XGBClassifier()
model2.load_model('./xgb1.model')
model2.predict(X)
```

```python
#Random Forestの場合
import pickle 
from sklearn.ensemble import RandomForestClassifier 
rf_model = RandomForestClassifier(n_estimators=10, max_depth=9, random_state=0) 
rf_model.fit(train_feature_for_model,train_kyosi_for_model) 
#save model to pickle file
with open("rf_model.pickle", 'wb') as file: 
    pickle.dump(rf_model, file)

# Load from file
with open("rf_model.pickle", 'rb') as file:
    rf_test_model = pickle.load(file)
y_pred_test_feature = rf_test_model.predict(test_feature_for_model)
```

##permutation importance
coming soon..

##shap
coming soon..