LoginSignup
2
2

More than 1 year has passed since last update.

pythonでオーバーサンプリングの実行

Posted at

機械学習を実施したいけどデータ数が足りない

前回の記事では

院内での医療機器管理データベースを利用し
過去の傾向から予想したい医療機器の情報を予想しました
0か1で予想する比較的簡単な2値分類を実行しました

ここで特徴量を削減しすぎたため
予測精度が悪くなるといった問題が出ました

それ以外にもデータの傾向を見ると
不均衡データとなっていました

そこで今回はオーバーサンプリングを実施したいと思います

オーバーサンプリング とは

「少数派のデータを多数派に合わせて増やす」という方法
不均衡データという「データ構造に偏りがあるデータ群」に対して有用です

オーバーサンプリングの中で特によく使われる手法がSMOTEと呼ばれるものです
SMOTEは、Synthetic Minority Over-sampling TEchniqueの略で
少数派のサンプルを増やしていきます

1.オーバーサンプリングの前準備 データをtrain, test, validationの3つに分割

#テストデータをtest_df とする
test_dfp = pd.concat([y_test_df,X_test_df], axis=1)
test_df=test_dfp.rename(columns={0:"i"})
test_df
#pd.DataFrame に戻して 縦に train val 結合していく
y_trainp = pd.DataFrame(y_train)
X_trainp = pd.DataFrame(X_train)
train=pd.concat([y_trainp, X_trainp], axis=1)
train

y_valp = pd.DataFrame(y_val)
X_valp = pd.DataFrame(X_val)
val=pd.concat([y_valp, X_valp], axis=1)
val
test_vol=pd.concat([train, val])
test_vol
#yの目的変数のカラムが0になってるので target に変化 
order_of_things=test_vol.rename(columns={0:"i"})
order_of_things

order_of_things1=order_of_things

2.オーバーサンプリングの実行

from imblearn import FunctionSampler
from imblearn.over_sampling import SMOTE
#オーバーサンプリング marge_data_over_sampling
X = order_of_things1.drop("target",axis=1).values
Y = order_of_things1["target"].values
columns_name = order_of_things1.drop("target",axis=1).columns
from imblearn.over_sampling import SMOTE
sm = SMOTE(sampling_strategy =0.5, random_state=42)
X_res, Y_res = sm.fit_sample(X, Y)
y_valp_p = pd.DataFrame(Y_res)
y_valp=y_valp_p.rename(columns={0:"target"})
print(y_valp)
X_valp = pd.DataFrame(X_res, columns=columns_name)
print(X_valp)
val=pd.concat([y_valp, X_valp], axis=1)
print(val)
SMOTE_dfp=val.rename(columns={0:"i"})

#ここでシャッフルさせる
SMOTE_df=SMOTE_dfp.sample(frac=1, random_state=0)
print(SMOTE_df.shape)

marge_data_over_sampling=pd.concat([SMOTE_df, test_df])
print("marge_data_over_sampling.shape")
print(marge_data_over_sampling.shape)
marge_data_over_sampling

これでテストデータ以外のデータのオーバーサンプリングができました

3.オーバーサンプリング後のモデルの訓練と評価

# Isolate the objective variable
X = SMOTE_df.drop("target",axis=1).values
y = SMOTE_df["target"].values
columns_name = SMOTE_df.drop("target",axis=1).columns

def Test_data_and_training_data_split(df,X,Y):
         N_train = int(len(df) * 0.8)
         N_test = len(df) - N_train
         X_train, X_test, y_train, y_test = \
            train_test_split(X, Y, test_size=N_test,shuffle=False,random_state=42)
         return X_train, X_test, y_train, y_test
# Execute a function that separates the data for training from the data for validation.
X_train,X_val, y_train,y_val = Test_data_and_training_data_split(merge_data_p,X,y)

#連番の値にするためあえてカラム名を使わない :: の文字が使えないため
#X_test = pd.DataFrame(X_test, columns=columns_name)

#X_val = pd.DataFrame(X_val, columns=columns_name)
X_val = pd.DataFrame(X_val)
y_valp = pd.DataFrame(y_val)
y_val=y_valp.rename(columns={0:"target"})
#X_train = pd.DataFrame(X_train, columns=columns_name)
X_train = pd.DataFrame(X_train)
y_trainp = pd.DataFrame(y_train)
y_train =y_trainp.rename(columns={0:"target"})

# shape 確認
print("train shape", X_train.shape)
print("test shape", X_test.shape)
print("validation shape", X_val.shape)
X_test_df = pd.DataFrame(X_test)
# shape 確認
print("y_train shape", y_train.shape)
print("y_test shape", y_test.shape)
print("y_validation shape", y_val.shape)
y_test_df = pd.DataFrame(y_test)
print("y_test describe",y_test_df.describe())
print("not_ y_test describe",(~y_test_df.duplicated()).sum())
#y_test_df.value_counts().plot(kind="bar")
print("y_test_df.duplicated().sum()",y_test_df.duplicated().sum())
#print(y_test_df[y_test_df.duplicated()])  
#テストデータをtest_df とする
test_dfp = pd.concat([y_test_df,X_test_df], axis=1)
test_df=test_dfp
test_df

#lightGBMの実装
import lightgbm as lgb
    # データセットを生成する
from sklearn import metrics
lgb_train = lgb.Dataset(X_train, y_train)
lgb_eval = lgb.Dataset(X_val, y_val, reference=lgb_train)
    # LightGBM のハイパーパラメータ
lgbm_params = {
        # 二値分類問題
        'objective': 'binary',
        # AUC の最大化を目指す
        'metric': 'auc',
    }
    # 上記のパラメータでモデルを学習する
model = lgb.train(lgbm_params, lgb_train, 
                    valid_sets=lgb_eval,
                        num_boost_round=100,  # 最大イテレーション回数指定
                        )
    # 保存
model.save_model('./model/model.txt')
    # テストデータを予測する
y_pred = model.predict(X_test)
    # 保存したモデルを使う場合はこんな感じ
    #bst = lgb.Booster(model_file='model.txt')
    #ypred = bst.predict(X_test, num_iteration=bst.best_iteration)
    # AUC (Area Under the Curve) を計算する
fpr, tpr, thresholds = metrics.roc_curve(y_test, y_pred)
auc = metrics.auc(fpr, tpr)
print("auc",auc)
print("fpr False Positive Rate:偽陽性率",fpr)
print("tpr True Positive Rate:真陽性率",tpr)
print("thresholds",thresholds)
# ROC曲線をプロット
plt.plot(fpr, tpr, label='ROC curve (area = %.2f)'%auc)
plt.legend()
plt.title('ROC curve')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.grid(True)

auc 0.66
と前回に比べて向上しました!

今回使用したのはlightGBMと呼ばれる決定木系の
機械学習でしたが それ以外にも様々な機械学習があります

何を対象に機械学習を利用したのか?どのような問題点が医療現場であるのか?

具体的に知りたい方は
第32回日本臨床工学会で 2022年5月14日、BPA8セッションにて発表予定です

BPA8セッションは医療機器業界で有名な大石さんの
『医療機器管理の井戸端会議』のことも聞けるセッションとなってます
興味のある方は是非参加よろしくお願いします!

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2