医療機器データベースに　機械学習　を利用する

# 医療機器データ解析するメリット

病院の医療機器管理は医療法で求められており　
平成19年第5次改正医療法の施行「医療機器の安全管理に係る体制整備」が義務となりました
法律でも明記されている

　「医療機器の安全対策のための責任者（医療機器安全管理責任者）の配置」
　「従業者に対する医療機器の安全使用のための研修の実施」
　「医療機器の保守点検に関する計画の策定および保守点検の実施」
　「医療機器の安全使用のために必要となる情報の収集
　　　その他の医療機器の安全使用を目的とした改善のための方策の実施」

が医療機器管理業務で必要となったのですが

対象となる医療機器が400台以上と多くデータベースの活用が必要でした

医療機器管理データベースを院内で構築すると
これまで見えてこなかった　情報が見えてくるようになりました

誰がどれくらい医療機器管理業務に携わっているか
年間でどれくらい経費節約に繋がっているか
これを皆様と具体的なデータと一緒に共有することで　
医療機器管理業務に対する　理解も得られてきました

データ解析するメリットは皆様の理解を得られることだと思います

# AIで大量のデータからデータを予想する

年々理解が進むとともに多くの方に医療機器関連データを入力していただける
「仕組み」ができ医療機器データベースの利用率は高くなってきました

AIとは簡単に解釈すると個人的には
「大量のデータからデータを予想する事」
だと考えております

大量の医療機器に関する良質なデータが集まる「仕組み」が整ったため
次にデータを活用し過去の傾向から　未来を予測するAIを利用しようと考えました

データベースのデータはスクリプトを利用すると
ボタンをクリックするだけで全てエクセルデータとして保存することが可能です

エクセルデータでみると
logデータだけでも100万件のデータとなり
それ以外の様々なエクセルをpythonで前処理する必要があります
前処理したAIに読み込ませるデータは特徴量が多くなりすぎたため

分散を見て特徴量を削減しました
https://qiita.com/TaichiEndoh/items/c9ae73a3d1170a00eeea

特徴量も削減できましたので
医療データにおけるAI（機械学習）の実装部分を記載したいと思います！

# AI（機械学習）の実装

私がAIを使えるようになったきっかけは
https://sites.google.com/view/ce-machine-learning-lab/home
2018年にCEML（臨床工学技士機械学習研究会）の方々とweb上でつながったのがきっかけでした　　

CEML（臨床工学技士機械学習研究会）部長のエンジニアスキルは格別で
ソースコードもとても綺麗で使いやすいため　部長が書いた以下のサイトのlightGBMを
自分なりに書き直して利用しました

pythonではじめるデータ分析 (データ前処理〜機械学習)
https://qiita.com/CEML/items/b7dc768d1df66e809e5a


今回は教師あり学習という種類の AI（機械学習）の実装を紹介します

### 1.予想したい医療機器の情報を0か1の2値に変換します

```
#前回の記事で特徴量削減後の変数をX_newとします
X_new
merge_data=X_new
test_classificationp=merge_data
df=test_classificationp
#1以上の時は　1　のバイナリーデータにする
df.loc[df['target'] > 0, 'target'] = 1

test_classification=df
list_t1=df["target"]
unique_set1 = set(list_t1)
unique_set1

```

pandas のカラムが　”target”　の文字列の部分を　教師あり学習の
教師として　バイナリ―データできました


### 2.データをtrain, test, validationの3つに分割します

```
merge_data=test_classification
merge_data
# Isolate the objective variable
X = merge_data.drop("target",axis=1).values
y = merge_data["target"].values
columns_name = merge_data.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 data for training and data for testing.
X_train, X_test, y_train, y_test = Test_data_and_training_data_split(merge_data,X,y)
X_test_df = pd.DataFrame(X_test, columns=columns_name)
y_test_df = pd.DataFrame(y_test)
test_dfp = pd.concat([y_test_df,X_test_df], axis=1)
test_df=test_dfp.rename(columns={0:"target"})
y_trainp = pd.DataFrame(y_train)
X_trainp = pd.DataFrame(X_train, columns=columns_name)
train=pd.concat([y_trainp, X_trainp], axis=1)
merge_data_p=train.rename(columns={0:"target"})
X = merge_data_p.drop("target",axis=1).values
y = merge_data_p["target"].values
columns_name_p = merge_data_p.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_test = pd.DataFrame(X_test)
y_testp = pd.DataFrame(y_test)
y_test=y_testp.rename(columns={0:"target"})
#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

```

これでデータが分割できました

### 3.モデルの訓練と評価

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.54とあまり精度はよくありませんでした
特徴量を削減しすぎて
データ数が少ないこととデータの分布が偏っている事が原因として考えられます

そのようなときに活躍するのが　「少数派のデータを多数派に合わせて増やす」
オーバーサンプリングです！　

次回はオーバーサンプリングについてソースコードも入れて紹介していきます！