ホモモーフィック暗号化による暗号化データの感情分析
'ホモモーフィック暗号化を使用した暗号化データの感情分析'
感情分析モデルは、テキストがポジティブ、ネガティブ、または中立であるかを判断することが広く知られています。しかし、このプロセスには通常、暗号化されていないテキストへのアクセスが必要であり、プライバシー上の懸念が生じる可能性があります。
ホモモーフィック暗号化は、復号化することなく暗号化されたデータ上で計算を行うことができる暗号化の一種です。これにより、ユーザーの個人情報や潜在的に機密性の高いデータがリスクにさらされるアプリケーションに適しています(例:プライベートメッセージの感情分析)。
このブログ投稿では、Concrete-MLライブラリを使用して、データサイエンティストが暗号化されたデータ上で機械学習モデルを使用することができるようにしています。事前の暗号学の知識は必要ありません。暗号化されたデータ上で感情分析モデルを構築するための実践的なチュートリアルを提供しています。
この投稿では以下の内容をカバーしています:
- オーディオデータセットの完全ガイド
- Hugging Faceデータセットとトランスフォーマーを使用した画像の類似性
- Hugging Faceがフランスのデータ保護機関の強化サポートプログラムに選ばれました
- トランスフォーマー
- トランスフォーマーをXGBoostと組み合わせて感情分析を実行する方法
- トレーニング方法
- Concrete-MLを使用して予測を暗号化されたデータ上の予測に変換する方法
- クライアント/サーバープロトコルを使用してクラウドにデプロイする方法
最後に、この機能を実際に使用するためのHugging Face Spaces上の完全なデモで締めくくります。
環境のセットアップ
まず、次のコマンドを実行してpipとsetuptoolsが最新であることを確認します:
pip install -U pip setuptools
次に、次のコマンドでこのブログに必要なすべてのライブラリをインストールします。
pip install concrete-ml transformers datasets
公開データセットの使用
このノートブックで使用するデータセットはこちらで見つけることができます。
感情分析のテキストを表現するために、トランスフォーマーの隠れた表現を使用することを選びました。これにより、TF-IDFアプローチのようなより一般的な手法と比較して、非常に効率的に最終モデルの高い精度が得られます。詳細なノートブックはこちらをご覧ください。
データセットを開いていくつかの統計情報を可視化することから始めることができます。
from datasets import load_datasets
train = load_dataset("osanseviero/twitter-airline-sentiment")["train"].to_pandas()
text_X = train['text']
y = train['airline_sentiment']
y = y.replace(['negative', 'neutral', 'positive'], [0, 1, 2])
pos_ratio = y.value_counts()[2] / y.value_counts().sum()
neg_ratio = y.value_counts()[0] / y.value_counts().sum()
neutral_ratio = y.value_counts()[1] / y.value_counts().sum()
print(f'ポジティブな例の割合:{round(pos_ratio * 100, 2)}%')
print(f'ネガティブな例の割合:{round(neg_ratio * 100, 2)}%')
print(f'中立な例の割合:{round(neutral_ratio * 100, 2)}%')
次のような出力が得られます:
ポジティブな例の割合:16.14%
ネガティブな例の割合:62.69%
中立な例の割合:21.17%
ポジティブと中立の例の割合はかなり似ていますが、ネガティブな例ははるかに多いです。最終的な評価指標を選択する際には、これを念頭に置いておきましょう。
次に、データセットをトレーニングセットとテストセットに分割することができます。このコードでは再現性を確保するためにシードを使用します。
from sklearn.model_selection import train_test_split
text_X_train, text_X_test, y_train, y_test = train_test_split(text_X, y,
test_size=0.1, random_state=42)
トランスフォーマーを使用したテキスト表現
トランスフォーマーは、テキスト内に現れる次の単語を予測するように訓練されることが多いニューラルネットワークです(このタスクは一般的にセルフスーパーバイズド学習と呼ばれます)。また、特定のサブタスクでもファインチューニングすることができ、特定の問題においてより良い結果を得ることができます。
これらは、あらゆる種類の自然言語処理タスクに対する強力なツールです。実際、トランスフォーマーの表現を使用してテキストを取り扱い、よりFHEに適した機械学習モデル(分類のためのもの)にフィードすることができます。このノートブックでは、XGBoostを使用します。
まず、トランスフォーマーの要件をインポートします。ここでは、Hugging Faceの人気ライブラリを使用して迅速にトランスフォーマーを取得します。
選んだモデルは、Stanford Sentiment TreebankデータセットでファインチューニングされたBERTトランスフォーマーです。
import torch
from transformers import AutoModelForSequenceClassification, AutoTokenizer
device = "cuda:0" if torch.cuda.is_available() else "cpu"
# トークナイザをロードする(テキストをトークンに変換する)
tokenizer = AutoTokenizer.from_pretrained("cardiffnlp/twitter-roberta-base-sentiment-latest")
# 事前学習済みモデルをロードする
transformer_model = AutoModelForSequenceClassification.from_pretrained(
"cardiffnlp/twitter-roberta-base-sentiment-latest"
)
これにより、モデルがダウンロードされ、使用する準備ができました。
テキストの隠れ表現を使用することは最初は難しいかもしれませんが、これにはさまざまなアプローチがあります。以下に、私たちが選んだアプローチを示します。
まず、テキストをトークナイズします。トークナイズとは、テキストをトークン(特定の文字のシーケンスで、単語でもあることがあります)に分割し、各トークンを番号で置き換えることです。次に、トークナイズされたテキストをトランスフォーマーモデルに送り、各単語に対して隠れ表現(分類レイヤーへの入力としてよく使用されるセルフアテンションレイヤーの出力)を出力します。最後に、各単語の表現を平均してテキストレベルの表現を得ます。
結果は形状(例の数、隠れサイズ)の行列です。隠れサイズは、隠れ表現の次元数です。BERTの場合、隠れサイズは768です。隠れ表現は、さまざまなタスクに使用できるテキストを表す数値のベクトルです。この場合、その後のXGBoostによる分類に使用します。
import numpy as np
import tqdm
# テキストのリストをトランスフォーマーによって学習された表現に変換する関数
def text_to_tensor(
list_text_X_train: list,
transformer_model: AutoModelForSequenceClassification,
tokenizer: AutoTokenizer,
device: str,
) -> np.ndarray:
# リスト内のテキストを1つずつトークナイズする
tokenized_text_X_train_split = []
tokenized_text_X_train_split = [
tokenizer.encode(text_x_train, return_tensors="pt")
for text_x_train in list_text_X_train
]
# モデルをデバイスに送る
transformer_model = transformer_model.to(device)
output_hidden_states_list = [None] * len(tokenized_text_X_train_split)
for i, tokenized_x in enumerate(tqdm.tqdm(tokenized_text_X_train_split)):
# トークンをトランスフォーマーモデルに渡し、隠れ状態を取得する
# 現時点では、最後の隠れ層の状態のみ保持する
output_hidden_states = transformer_model(tokenized_x.to(device), output_hidden_states=True)[
1
][-1]
# トークンの軸を平均してテキストレベルの表現を得る
output_hidden_states = output_hidden_states.mean(dim=1)
output_hidden_states = output_hidden_states.detach().cpu().numpy()
output_hidden_states_list[i] = output_hidden_states
return np.concatenate(output_hidden_states_list, axis=0)
# トランスフォーマーを使用してテキストをベクトル化しましょう
list_text_X_train = text_X_train.tolist()
list_text_X_test = text_X_test.tolist()
X_train_transformer = text_to_tensor(list_text_X_train, transformer_model, tokenizer, device)
X_test_transformer = text_to_tensor(list_text_X_test, transformer_model, tokenizer, device)
このテキストの変換(テキストからトランスフォーマーの表現への変換)は、クライアントマシン上で実行する必要があります。なぜなら、暗号化はトランスフォーマーの表現上で行われるからです。
XGBoostによる分類
これで、正しく構築されたトレーニングセットとテストセットを使用して分類器をトレーニングする準備が整いました。次に、scikit-learnのGridSearchなどのハイパーパラメータチューニングツールを使用して、FHEモデルのトレーニングを行います。
from concrete.ml.sklearn import XGBClassifier
from sklearn.model_selection import GridSearchCV
# モデルを構築しましょう
model = XGBClassifier()
# GridSearchを使用して最適なパラメータを見つける
parameters = {
"n_bits": [2, 3],
"max_depth": [1],
"n_estimators": [10, 30, 50],
"n_jobs": [-1],
}
# これで各ツイートに対する表現が得られたので、これを使用してモデルをトレーニングできます。
grid_search = GridSearchCV(model, parameters, cv=5, n_jobs=1, scoring="accuracy")
grid_search.fit(X_train_transformer, y_train)
# 最も良いモデルの精度を確認する
print(f"Best score: {grid_search.best_score_}")
# 最適なハイパーパラメータを確認する
print(f"Best parameters: {grid_search.best_params_}")
# 最良のモデルを抽出する
best_model = grid_search.best_estimator_
出力は以下の通りです:
最高のスコア:0.8378111718275654
最適なパラメータ:{'max_depth': 1, 'n_bits': 3, 'n_estimators': 50, 'n_jobs': -1}
さあ、モデルがテストセットでどのように機能するかを見てみましょう。
from sklearn.metrics import ConfusionMatrixDisplay
# テストセットでのメトリクスを計算する
y_pred = best_model.predict(X_test_transformer)
y_proba = best_model.predict_proba(X_test_transformer)
# 混同行列を計算してプロットする
matrix = confusion_matrix(y_test, y_pred)
ConfusionMatrixDisplay(matrix).plot()
# 正解率を計算する
accuracy_transformer_xgboost = np.mean(y_pred == y_test)
print(f"正解率:{accuracy_transformer_xgboost:.4f}")
次のような出力が得られます:
正解率:0.8504
暗号化データ上での予測
ここでは、暗号化されたテキスト上で予測を行います。アイデアは、生のテキスト自体ではなく、トランスフォーマーによって与えられる表現を暗号化することです。Concrete-MLでは、予測関数のパラメータexecute_in_fhe=True
を設定するだけで、これを非常に迅速に行うことができます。これは開発者向けの機能であり(主にFHEモデルの実行時間を確認するために使用されます)、デプロイメントの設定でどのように機能するかを後ほど見ていきます。
import time
# FHE推論エンジンを取得するためにモデルをコンパイルする
# (選択したモデルによっては、数分かかる場合があります)
start = time.perf_counter()
best_model.compile(X_train_transformer)
end = time.perf_counter()
print(f"コンパイル時間:{end - start:.4f} 秒")
# カスタムの例を作成して、FHEで予測する
tested_tweet = ["AirFrance is awesome, almost as much as Zama!"]
X_tested_tweet = text_to_tensor(tested_tweet, transformer_model, tokenizer, device)
clear_proba = best_model.predict_proba(X_tested_tweet)
# 今度はFHEを使って単一のツイートで予測し、所要時間を表示する
start = time.perf_counter()
decrypted_proba = best_model.predict_proba(X_tested_tweet, execute_in_fhe=True)
end = time.perf_counter()
fhe_exec_time = end - start
print(f"FHE推論時間:{fhe_exec_time:.4f} 秒")
出力は次のようになります:
コンパイル時間:9.3354 秒
FHE推論時間:4.4085 秒
FHEの予測結果がクリアな予測結果と同じであることを確認することも必要です。
print(f"FHE推論からの確率:{decrypted_proba}")
print(f"クリアなモデルからの確率:{clear_proba}")
この出力は次のようになります:
FHE推論からの確率:[[0.08434131 0.05571389 0.8599448 ]]
クリアなモデルからの確率:[[0.08434131 0.05571389 0.8599448 ]]
デプロイメント
この時点で、モデルは完全にトレーニングされ、コンパイルされ、デプロイ準備が整っています。Concrete-MLでは、デプロイメントAPIを使用してこれを簡単に行うことができます:
# モデルを保存して後でサーバーにプッシュするために
from concrete.ml.deployment import FHEModelDev
fhe_api = FHEModelDev("sentiment_fhe_model", best_model)
fhe_api.save()
これらの数行で、クライアントとサーバーの両方に必要なすべてのファイルをエクスポートすることができます。詳細な説明が記載されているノートブックは、こちらで確認できます。
Hugging Face Spaceでの完全な例
Hugging Face Spaceで最終的なアプリケーションを確認することもできます。クライアントアプリはGradioで開発され、サーバーはUvicornで実行され、FastAPIで開発されました。
プロセスは次のようになります:
- ユーザーが新しい公開/秘密鍵を生成する
- ユーザーがエンコード、量子化、暗号化されるメッセージを入力する
- サーバーは暗号化されたデータを受け取り、公開評価鍵を使用して暗号化されたデータ上で予測を開始します
- サーバーは暗号化された予測結果を送信し、クライアントは自分の秘密鍵を使用してそれらを復号化することができます
結論
私たちは、トランスフォーマーのパワーを活用する方法を提案しました。この表現は以下のように使用されます:
- ツイートを分類するための機械学習モデルをトレーニングする
- このモデルを使用してFHEを使って暗号化されたデータ上で予測する
最終モデル(トランスフォーマー表現 + XGboost)は、80%の正確さを持つトランスフォーマー自体を上回る85%の正確さを持ちます(比較のためにこのノートブックをご覧ください)。
1つの例当たりのFHE実行時間は、16コアのCPU上で4.4秒です。
デプロイメント用のファイルは、データの暗号化を維持しながら、クライアントがサーバーから感情分析の予測を要求できる感情分析アプリに使用されます。
Concrete-ML(Githubで私たちにスターをつけるのをお忘れなく⭐️💛)は、簡単なMLモデルの構築とFHEと同等の予測能力への変換を可能にします。
この記事を楽しんでいただけたら幸いです。ご意見やフィードバックをお知らせください!
また、最初のHugging Face Spaceを構築するための以前のアドバイスについては、Abubakar Abidさんに特別な感謝を申し上げます。
We will continue to update VoAGI; if you have any questions or suggestions, please contact us!
Was this article helpful?
93 out of 132 found this helpful
Related articles