AWS で医療データを暗号化したまま機械学習の推論をしてみた !

2023-03-02
ビジネス x クラウド

Author : 佐藤 航大、宋 子豪

みなさんは、データ活用のため機械学習技術等を利用したいけど、中身を知られたくないようなセンシティブなデータに関しては情報の取り扱いが難しくなかなか進まない、といった課題を抱いたことはありませんか ?

特に昨今ではこのような悩みをもつ方が増えており、我々ソリューションアーキテクトにもデータのプライバシー保護に関する質問を多くいただきます。近年のトレンドとしてユーザーデータのプライバシー保護、特に医療データの保護活用は世間一般的にも大きな関心事とされており、 AWS のお客さまでもビッグデータ、 AI を活用する上で個人のプライバシーをいかに守るかが注目されています。

AWS を利用している多くのお客さまでは Big Data に注目しており、AWS でデータレイク、データウェアハウスの構築をしています。しかしその中で、ユーザーのセンシティブなデータも多く含まれており、コンプライアンスや規制などで AI による活用が難しいデータが多いこともまた事実です。さらに、既存の技術ではデータ保護の観点からお客さまの情報を暗号化することで安全に保管します。

しかし、クラウドの発展によりデータの保管場所以外でMLによるデータの処理を行いたいニーズもあります。例えば、センシティブなデータは暗号化してGPU付きのサーバーへ送り、サーバー側で暗号化された入力データを受け付け、暗号化された推論結果を返し、再度クライアント側は受け取った暗号化データ復号して結果を得るなどといったケースもあるかと思います。しかし、これまででは暗号化された情報はそのままでは活用できないため、情報の保護と活用の両立が難しい問題でした。

暗号技術にまつわる AWS サービスやツールの開発を行っている Cryptography チームは、情報を保護しながら機械学習を行うために、データを暗号化させた状態で XGBoost を用いた推論ができるようなライブラリ: PPXGboost を開発し、Github に公開しています。これは、機械学習 のアルゴリズムである XGBoost に加え、暗号アルゴリズムである、Order-preserving encryption, Pailler 暗号を組み合わせたアルゴリズムです。入力データ、学習済みの特徴量も暗号化されるので、より高いセキュリティを保ったまま機械学習の推論を行うことができるライブラリになっています。

なんだか難しい用語がたくさん並んでいますが、一言で表すと「データと特徴量を暗号化したまま、機械学習の推論を行うことができる」ライブラリとなっております。つまり、上で述べたデータ保護とデータ活用の両立を実現してくれる技術となります。


データ保護とデータ活用の両立が実現できるとどうでしょう ? AWS は責任共有モデルにもとづいてセキュアな環境を提供していますが、その上で、誰にも知られたくないようなデータをより安全に利用したい場合でも、お客さまの大切な個人データを暗号化した状態で推論することができるようになります。

ユースケースの具体例として、たとえば AWS のようなクラウドの資源を活用して機械学習で患者の総合データから潜在的な病気を推定したり、センシティブな個人データを分析してより高度なレコメンド機能を提供するなどが考えられます。

今回の内容

今回は以下のような流れに沿って、医療系の情報を利用して、暗号化した状態で XGBoost の推論ができる PPXGBoost を触っていきます。前処理したデータは PPXGboost のリポジトリ にも保管されているため、PPXGBoost の実行から行いたい方は 6. の Amazon SageMaker Notebooks の実行から始めることが可能です。

ご注意

本記事で紹介する AWS サービスを起動する際には、料金がかかります。builders.flash メールメンバー特典の、クラウドレシピ向けクレジットコードプレゼントの入手をお勧めします。

*ハンズオン記事およびソースコードにおける免責事項 »

このシリーズ記事のその他の記事はこちら

選択
  • 選択
  • ビルダーのビルダーによるビルダーのためのセキュリティ »
  • セキュリティを何から始めれば良いか分からない開発者の方へ »
  • DevSecOps パイプラインを構築してみよう ! »
  • Amazon Inspector と AWS Systems Manager を用いて脆弱性の修復パイプラインを構築しよう
  • マルチテナント SaaS アプリケーションの認証を Amazon Cognito で実現してみよう !
  • すぐに始めて、継続できる AWS のセキュリティ対策

1. PPXGBoost の概要

PPXGBoost は複数の暗号技術によって支えられています。先述の通り、今回取り上げる順序保存暗号 (Order-Preserving Encryption) と 加法準同型性をもつ Paillier 暗号によって構成されています。

順序保存暗号はその名の通り、暗号化した後でも暗号文同士を復号せずに処理することで二つの異なる暗号文の平文の大小を判別できるものであり、組み合わせて使うデバイスや技術などで保管できる場合がある暗号化方式、特に検索可能暗号 DB などの実装に対して有用とされています。

一方、もう一つのキーワードである Paillier 暗号は 1999 年に Pascal Paillier が提案した公開鍵暗号方式で、加法準同型性を持つことが知られています。加法準同型性を抽象化して説明すると、暗号化した後も暗号文を足したり、引いたりした後に結果を復号すると平文に加減の操作を行なったのと同じ結果になると言う方式で、特に今回のような暗号化したままデータを操作する場合に対して有用とされています。

機械学習については、教師あり学習の活用では大きく分けると「モデルの学習」と「学習済みモデルを使った推論」の二つのフェーズがあります。学習段階では大量のデータを使ってモデルを構築し、推論では学習したモデルを使用してデータの分類などを行います。教師あり学習のアルゴリズム一つとして XGBoost があります。

XGBoost では学習器として回帰木を使い、Boosting によってモデルの構築と学習を行い、学習時にはモデルの勾配情報でパラメータを更新するモデルです。推論段階では入力データを内部の CARTs (classification and regression trees) と呼ばれる複数の木で分類 (整数と木ノードとの大小比較及び加算) します。この時、 CARTs のノードも暗号化し、 OPE で暗号化した入力の大小比較及び Pailler 暗号によって暗号化した状態での結果判定のためのスコア加算をすることで、このような技術を実現しています。

出典 : Machine learning models that act on encrypted data
(PPXGBoostの暗号化推論計算概念図)
(画像をクリックすると拡大します)

* 本記事で取り上げている PPXGBoost のライブラリは標準化されている技術ではないため、利用方法に関して注意した上でご利用ください。


2. 使用している AWS サービス

AWS では機械学習のための環境が整えられており、今回では HIPAA 準拠サービス である Amazon Sagemaker Notebooks を使用して機械学習と推論を行います。

また学習データ保存のために Amazon Simple Storage Service (Amazon S3) 、学習データの前処理に Amazon SageMaker Data Wrangler、モデルの学習と推論に Amazon SageMaker Notebooks を使用します。

Amazon S3 学習のデータの保存に利用します。ストレージとしてだけでなく、動画配信時のオリジンサーバーとして利用することで、高い耐久性を持った配信サーバーをサーバー管理不要で実現できます。
Amazon Sagemaker 機械学習の実行環境として利用します。HIPAA 準拠サービスであるため単体でも高いレベルの個人情報保護コンプライアンスに準拠しています。
Amazon Sagemaker Data Wrangler 学習用データの前処理に利用します。データ準備と特徴量エンジニアリングのプロセスを簡素化し、データ準備ワークフローの各ステップ (データの選択、クレンジング、探索、可視化など) を単一のビジュアルインターフェースで完了できるので、機械学習 (ML) 用データの集約と準備に要する時間を、数週間から数分に短縮します。

今回は、Amazon S3 と Amazon SageMaker を用いて、データセットの保存・前処理を行った後、XGBoost によるモデルを構築し、推論を行います。Notebook Instance上での推論は通常の XGBoost で平文を入力した場合、PPXGBoost で入力を暗号化した状態で推論した場合の2パターン実行して、推論結果に差異がないことを示します。

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


3. データセットを Amazon S3 へアップロード

データセットは こちら からダウンロードすることができます。

このデータセットは、以下の公開されているデータセットのサンプルバージョンで、患者と病院の結果に関する 15 を超える特徴を含む履歴データのが含まれています。このデータを用いてデータの前処理・機械学習の実行を行なっていきます。

"Diabetes 130-US hospitals for years 1999-2008 Data Set" (Beata Strack, Jonathan P. DeShazo, Chris Gennings, Juan L. Olmo, Sebastian Ventura, Krzysztof J. Cios, and John N. Clore, “Impact of HbA1c Measurement on Hospital Readmission Rates: Analysis of 70,000 Clinical Database Patient Records,” BioMed Research International, vol. 2014, Article ID 781670, 11 pages, 2014.)

次に、生のデータセットをアップロードする S3 バケット、整形したあとのデータセットをアップロードする S3 バケットをそれぞれ作成します。

クリックすると拡大します

その次に、ダウンロードしたデータセットを生のデータセットを格納するための S3 バケットにアップロードします。

クリックすると拡大します


4. Amazon SageMaker Studio を起動する

データセットの S3 へのアップロードができたら、次は SageMaker Studio を起動します。

クリックすると拡大します

次に、ターミナルを立ち上げて git clone コマンドを実行して github のリポジトリから SageMaker Studio 環境へアセットをコピーします。

git clone https://github.com/awslabs/privacy-preserving-xgboost-inference.git

5. データセットの前処理を行う

データセットは以下のようなカラムで構成されます。今回予測したいカラムは readmitted で、リスクの高い糖尿病患者が退院後 30 日以内に再入院するか、30 日以降に再入院するか、再入院しないかの 3 値分類問題を、SageMaker Studio で PPXGboost を用いて解いていきたいと思います。

readmitted:  リスクの高い糖尿病患者が、退院後30日以内に再入院するか、30日以降に再入院する可能性が高いか、再入院しないか
race:  次のいずれかで表される人種: Caucasian, Asian, African American, Hispanic
gender: 次のいずれかで表される性別: "Male", "Female", "Unknown/Invalid"
age: 入院時の患者の年齢
time_in_hospital:  入院日数
num_lab_procedures:  入院中に行われた臨床検査の回数
num_procedures:  入院中に行われた医療行為の回数 (臨床検査を除く)
num_medications:  入院中に投与されたジェネリック医薬品の数
number_outpatient:  入院前のある年における、外来での受診回数
number_emergency:  入院前のある年における、救急外来での受診回数
number_inpatient:  入院前のある年における、入院中の受診回数
number_diagnoses:  システムに入力された診断の数
max_glu_serum:  検査結果の範囲またはその有無を次の値で表す: ">200", ">300", "normal", "none"
a1c_result: 検査結果の範囲またはその有無を次の値で表す: ">8", ">7", "normal", "none"
change:  糖尿病治療薬の数や名称変更の有無。次の値で表す: "change", "no change"
diabetes_med: 糖尿病治療薬の処方の有無

今回のデータセットでは、文字列のカラムが存在します。全て数種類のタイプに分かれているカラムであるので、扱いやすくするために数値に変換します。データの変換には Amazon SageMaker Data Wrangler を用います。SageMaker Wrangler は、SageMaker Studio の機能で、機械学習で利用するデータセットの前処理を行うサービスです。

Data Wrangler を選択し、「Import data」をクリックします。

クリックすると拡大します

Data Wrangler と接続されるのを待ちます。

クリックすると拡大します

接続が完了したら、Create connection では「Amazon S3」を選択します。作成したバケット内にアップロードした csv ファイルを選択します。

クリックすると拡大します

データセット全体をインポートしたいので、Details の Sampling は「None」に設定します。その後「import」を選択します。 

クリックすると拡大します

インポートした後は、String 型のカラムを数値に変換します。
Add Step」を選択します。

 

クリックすると拡大します

encode categorical」を選択します。

クリックすると拡大します

今回の扱うデータセットの文字列のカラムは全て数種類で表現されているので、整数値に変更して扱いやすい形に変換します。そのため、 Transform はデフォルトの「Ordinal encode」を選択します。

String 型の 5 つのカラム全て (readmitted, race, gender, max_glu_serum, a1c_result) を選択します。

invalid handling strategy は「skip」を選択します。

クリックすると拡大します

previrew」ボタンを押して、データセットを確認し、String 型のカラムが数値に変更されていることを確認します。その後「Add」を選択します。

 

クリックすると拡大します

エンコーディング後のデータ型は Float になってしまうので、Float から Long 型に変換するステップも加えます。「add step」を再び選択します。Long 型に変更したあとは、次のような Step が構成されているはずです。

クリックすると拡大します

S3バケットに処理図後のデータセットを保存します。「Export data」を選択します。

クリックすると拡大します

S3 location に 整形後のデータセットを保存するための S3 バケットを選択します。その後、「Export data」を選択します。

クリックすると拡大します


6. ノートブックを実行する

それでは、糖尿病患者についての再入院リスクを入力を暗号化した状態で推論するために、PPXGBoost のリポジトリにあるノートブック を実行してみましょう。今回はデータの暗号化も Notebook Instance 上で行い、暗号化あり、なしの場合の推論実行時間と精度を結果として比較したいと思います。

また、今回はデータセットを SageMaker Data Wrangler で XGBoost が扱える形式に前処理を行いましたが、リポジトリに前処理後のデータも用意しているので、ひとまず PPXGBoost を実行してみたい方は ノートブックをそのまま実行 していただくこともできます。

それでは、readmitted.ipynb ファイルを開いて、実行してみましょう。(実行前に、requirement.txt のパッケージをインストールする必要があります)

まず、学習用のデータセットと、推論用のデータセットを用意します。予測したい値はデータセット内の readmitted にあたるため、readmitted カラムのみ分離しておきます。

train, test = train_test_split(data, train_size = 0.998, test_size = 0.002)

AttributeLabels = ['race', 'gender', 'age', 'time_in_hospital', 'num_lab_procedures', 'num_procedures', 'num_medications', 'number_outpatient', 'number_emergency', 'number_inpatient', 'number_diagnoses', 'max_glu_serum', 'a1c_result', 'change', 'diabetes_med']

# Training dataset
X_train = train[AttributeLabels]
Y_train = train[['readmitted']]

# Testing dataset
X_test = test[AttributeLabels]
Y_test = test[['readmitted']]

次に、XGBoost でモデルを構築し、推論用データセットを用いて推論を行いて推論結果を plaintext_predict に保存します。

# Train a xgboost model 
dtrain = xgb.DMatrix(X_train, label=Y_train)
num_class = 3
params = {'eta': 0.1, 'objective':'multi:softmax', 'num_class': num_class}
model = xgb.train(params=params, dtrain=dtrain)

# predict using the plaintext prediction
start = time.time()
plaintext_predict = model.predict(xgb.DMatrix(X_test))
end = time.time()
print("XGBoost Prediction : Elapsed Time: ", end - start)

その後、暗号化させた状態で推論ができるようにモデルの変換を行います。

そして、今回は一つのノートブック上で実行しますが、クライアント側の処理として推論の入力を暗号化させてモデルに入力し、サーバ側は推論を行いその結果を enc_predictions に保存し、再度クライアント側で復号を行い result に保存します。

# Booster Parser will parse the tree
#  (add fake metadata here as this testing only test the model correctness)
test_input_vector = pd.DataFrame(X_test)
min_max = {'min': 0, 'max': 132}
meta_min_max = MetaData(min_max)
p_trees, features, min_max = boostparser.model_to_trees(model, min_max)

# 1. Set up encryption materials.
prf_key = token_bytes(16)
public_key, private_key = paillier.he_key_gen()
encrypter = OPE(token_bytes(16))
ppBoostKey = PPBoostKey(public_key, prf_key, encrypter)

# 2. process the tree into ope_enc_tree
enc_trees = ppbooster.enc_xgboost_model(ppBoostKey, p_trees, meta_min_max)

# 3. Encrypts the input vector for prediction (using prf_key_hash and ope-encrypter) based on the feature set.
ppbooster.enc_input_vector(prf_key, encrypter, features, test_input_vector, meta_min_max)

# # 4. OPE evaluation based on OPE encrypted values in the tree nodes.
start = time.time()
enc_predictions = ppbooster.predict_multiclass(enc_trees, num_class, test_input_vector)
end = time.time()
print("PPXGBoost Prediction : Elapsed Time: ", end - start)

# 5. Client decryption.
result = ppbooster.client_decrypt_prediction_multiclass(private_key, enc_predictions)

最後に、入力を暗号化した状態で推論を行った際の結果 (result) と平文のまま推論した結果を比較します。ここで暗号化した場合の結果と暗号化してない場合の精度が変わらないことを確認できます。つまり、暗号化をした上でも機械学習の精度が保たれているというメリットがあります。

result = np.array([round(x, 7) for x in result])
assert len(plaintext_predict) == len(result)

# check if the predicted values are same (the ppxgboost might not produce same values 
#                                    as the plaintext value due to precision)
for i in range(len(plaintext_predict)):
    assert abs(plaintext_predict[i] - result[i]) < 0.000001

無事プログラムが実行できたかと思います。また、通常の XGBoost 推論を実行した際の実行時間と、PPXGBoost での推論の実行時間も出力されるので、性能についてご興味のある方は確認してみてください。


7. まとめ

いかがでしたでしょうか、今回は AWS Cryptography チームが開発した「暗号化したまま機械学習の推論ができるライブラリ」 (PPXGBoost) を使用して、公開されている機械学習用の医療データでリスクの高い糖尿病患者が退院後 30 日以内に再入院するかどうかの予測を、入力を暗号化した状態で行ってみました。AWS クラウドにおける機械学習環境の SageMaker を利用することで前処理から学習まで、推論の入力を暗号化した状態でも、シームレスに AWS クラウドで学習データの準備、ML の環境整備、学習、推論をスムーズに行うことができました。

このような暗号 x 機械学習技術が標準化され、利用が進めば、あらゆる場面でセンシティブなデータを機械学習で活用できる未来も遠くないのかもしれません。機械学習含め、AWS では色々な便利な OSS 開発に取り組んでいます。ご興味のある方は、こちらのリンク をご覧ください。

このシリーズ記事のその他の記事はこちら

選択
  • 選択
  • ビルダーのビルダーによるビルダーのためのセキュリティ »
  • セキュリティを何から始めれば良いか分からない開発者の方へ »
  • DevSecOps パイプラインを構築してみよう ! »
  • Amazon Inspector と AWS Systems Manager を用いて脆弱性の修復パイプラインを構築しよう
  • マルチテナント SaaS アプリケーションの認証を Amazon Cognito で実現してみよう !
  • すぐに始めて、継続できる AWS のセキュリティ対策

builders.flash メールメンバーへ登録することで
AWS のベストプラクティスを毎月無料でお試しいただけます

筆者プロフィール

佐藤 航大
アマゾン ウェブ サービス ジャパン 合同会社
ソリューションアーキテクト

西日本のお客様を中心にクラウド活用に関する技術的な支援を行うアーキテクト。
暗号技術が好きで、最近は耐量子暗号 (PQC) に興味をもっています。

宋 子豪
アマゾン ウェブ サービス ジャパン合同会社
ソリューションアーキテクト

2022 年 4 月 に AWS Japan に入社したソリューションアーキテクト。大学院時代の研究はペアリング写像と高機能暗号。趣味は基本カメラと散歩ですが、家に 3D Printer があり、たまに小物を作ることで溜まった物作り欲を発散させています。

AWS を無料でお試しいただけます

AWS 無料利用枠の詳細はこちら ≫
5 ステップでアカウント作成できます
無料サインアップ ≫
ご不明な点がおありですか?
日本担当チームへ相談する