サウンドロジックと単調なAIモデル
公開: 2022-03-11AIは急速に驚くべき資産になりつつあり、画像認識、Go、さらにはポーカーなどのドメインで超人的なレベルのパフォーマンスを達成しています。 多くの人がAIと人類の未来に興奮しています。 同時に、AIには1つの厄介な欠陥があるという一般的な感覚があります。現在の状態のAIは、予測できないほど信頼性が低い可能性があります。
古典的な例はジェパディです! IBMチャレンジでは、IBM AIであるワトソンがボードを簡単に掃除しましたが、「ファイナルジェパディ!」を見逃しただけでした。 米国の都市のカテゴリーに含まれていた質問:「その最大の空港は第二次世界大戦の英雄にちなんで名付けられました。 第二次世界大戦で2番目に大きい戦いです。」 ワトソンは、「トロントとは何ですか?????」と答えました。余分な疑問符(および低い賭け金)は、その疑いを示しています。
そのため、AIには、おとぎ話のようなパフォーマンスを長期間(数か月、数年、数十年も)行う能力がありますが、突然、不思議なことに失敗する可能性が常にあります。
私たち人間にとって最も懸念されるのは、AIが間違いを犯すということではなく、間違いがどれほど「非論理的」であるかということです。 ワトソンの場合、質問に対する答えを知らない人は、少なくとも米国の主要都市を「論理的に」推測しようとします。 これが、自動運転車がまだ一般に採用されていない主な理由の1つだと思います。自動運転車の方が統計的に安全であるとしても、ワトソンと同じように、基盤となるAIが予期せず失敗する可能性があるのではないかと心配しています。 、しかし、はるかに深刻な影響があります。
これは私に疑問を投げかけました、正しいAIモデルはこの問題を修正できますか? 適切なAIには、すべての答えがない場合でも、重要な瞬間に適切な意思決定を行う機能がありますか? このようなAIは、テクノロジーの流れを変え、おとぎ話のようなAIのメリットを実現できるでしょう…
これらの質問に対する答えはイエスだと思います。 ワトソンのような間違いは、改良された、より論理的に制約されたモデルを使用することで回避できると思います。その初期のプロトタイプは単調な機械学習モデルと呼ばれます。 まだ詳細に立ち入ることなく、適切な単調なAIモデルを使用します。
- 自動運転車の方が安全です。他の信号が大量に存在する場合でも、人間の信号を最小限に検出すれば、安全プロトコルをアクティブにするのに常に十分だからです。
- 機械学習(ML)システムは、敵対的攻撃や予期しない状況に対してより堅牢になります。
- MLのパフォーマンスは、より論理的で人間が理解できるものになります。
私たちは、AIの計算能力とアルゴリズム能力が大幅に成長した時代から、AIの精巧さ、有効性、理解の時代に移行していると信じています。単調な機械学習モデルは、このエキサイティングな旅の第一歩です。 単調モデルはAIをより「論理的」にします。
編集者注:MLの基本を理解するための独自の第一歩を踏み出そうとしている読者は、MLに関する紹介記事を読むことをお勧めします。
単調AIモデルの理論
では、単調モデルとは何ですか? 大まかに言えば、単調モデルは、いくつかの機能のセット(単調機能)を持つMLモデルであり、その増加により、モデルは常に出力を増加させます。
技術的に...
...上記の定義が不正確な場所が2つあります。
まず、ここでの機能は単調増加です。 また、単調に減少する特徴を持つこともできます。その増加は常にモデルの減少につながります。 この2つは、否定(-1を掛ける)によって簡単に相互に変換できます。
第二に、出力が増加すると言うとき、それが厳密に増加していることを意味するのではなく、出力が同じままである可能性があるため、減少しないことを意味します。
実生活では、変数の多くのペアが単調な関係を示します。 例えば:
- 旅行のガソリン価格は、走行距離で単調に上昇しています。
- ローンを受け取る可能性は、より良いクレジットでより高くなります。
- 予想される運転時間は、交通量に応じて増加します。
- 広告のクリック率に応じて収益が増加します。
これらの論理的な関係は十分に明確ですが、限られたデータを使用して補間し、ドメイン知識を持たないMLモデルの場合、そうではない可能性があります。 実際、モデルはそれらを誤って補間し、ばかげて奇抜な予測をもたらす可能性があります。 このような知識を取得する機械学習モデルは、実際には(過剰適合を回避することで)パフォーマンスが向上し、デバッグが容易で、解釈しやすくなります。 ほとんどのユースケースでは、単調モデルは、学習者のアンサンブルの一部として、通常のモデルと組み合わせて使用する必要があります。
単調なAIモデルが本当に輝いている場所の1つは、敵対的な堅牢性です。 単調モデルは「強化された」機械学習モデルであり、敵対的な攻撃に耐性があることを意味します。 非単調な機能のみを操作できる攻撃者は、単調なAIモデルに関して例のラベルを変更できないため、単調なAIモデルを回避することはできません。
単調AIモデルのユースケース
これまでのところ、この議論は完全に理論的なものです。 実際のユースケースについて説明しましょう。
ユースケース#1:マルウェアの検出
単調なAIモデルの最もクールなユースケースの1つは、マルウェア検出での使用である必要があります。 Windows Defenderの一部として実装された単調なモデルは、すべての最新のWindowsデバイスに存在し、マルウェアからユーザーを静かに保護します。
あるシナリオでは、マルウェアの作成者が合法的な登録企業になりすまして認証局をだまし、信頼できる証明書を使用してマルウェアをデジタルコード署名することに成功しました。 ナイーブなマルウェア分類子は、機能としてコード署名を使用する可能性が高く、そのようなサンプルが無害であることを示します。
ただし、Windows Defenderの単調なAIモデルの場合はそうではなく、その単調な機能はマルウェアを示す機能のみです。 マルウェアの作成者がマルウェアにどれだけ「良性」のコンテンツを注入しても、Windows Defenderの単調なAIモデルは引き続きサンプルをキャッチし、ユーザーを被害から守ります。
私のコース「レッドチームハッカーのための機械学習」では、MLベースのマルウェア分類子を回避するためのいくつかの手法を教えています。 手法の1つは、悪意のあるサンプルに「良性」のコンテンツ/機能を詰め込んで、ナイーブなMLモデルを回避することです。 単調なモデルはこの攻撃に耐性があり、分類子を回避する希望がある場合は、悪意のあるアクターにさらに一生懸命働くように強制します。
ユースケース#2:コンテンツフィルタリング
チームが学校図書館用のWebサーフィンコンテンツフィルターを構築しているとします。 単調なAIモデルは、不適切なコンテンツを含むフォーラムにも受け入れ可能なコンテンツが多数含まれている可能性があるため、ここで使用するのに最適な候補です。
単純分類器は、「適切な」機能の存在と「不適切な」機能の存在を比較検討する場合があります。 しかし、コンテンツのごく一部しか占めていなくても、子供たちが不適切なコンテンツにアクセスすることを望まないため、それはうまくいきません。
ユースケース#3:自動運転車のAI
自動運転車のアルゴリズムを構築することを想像してみてください。 画像を見て、緑色のライトが見えます。 歩行者も見えます。 それはお互いの信号を比較検討する必要がありますか? 絶対違う。 歩行者の存在は、車を止める決定をするのに十分です。 歩行者の存在は単調な特徴と見なす必要があり、このシナリオでは単調なAIモデルを使用する必要があります。
ユースケース#4:推奨エンジン
レコメンデーションエンジンは、単調なAIモデルの優れたユースケースです。 一般に、星の評価、価格、レビューの数など、各製品について多くの入力がある可能性があります。星の評価や価格など、他のすべての入力が等しい場合は、レビューの数が多い製品をお勧めします。 単調なAIモデルを使用して、このようなロジックを適用できます。
ユースケース#5:スパムとフィッシングのフィルタリング
このユースケースは、マルウェア検出のユースケースに似ています。 悪意のあるユーザーは、スパムフィルターをだますために、スパムまたはフィッシングメールに良性のように見える用語を挿入する可能性があります。 単調なAIモデルはその影響を受けません。
実装とデモンストレーション
単調なAIモデルの自由に利用できる実装に関しては、XGBoost、LightGBM、TensorFlowLatticeの3つが最もよくサポートされています。
単調MLXGBoostチュートリアル
XGBoostは、長年の経験的研究と競争に基づいて、構造化データで最もパフォーマンスの高いアルゴリズムの1つと見なされています。 さらに、XGBoostでは単調性が実装されています。
単調なMLモデルの使用方法に関する次のデモXGBoostチュートリアルには、Pythonリポジトリが付属しています。
いくつかのライブラリをインポートすることから始めます。
import random import numpy as np import matplotlib.pyplot as plt %matplotlib inline from sklearn.metrics import confusion_matrix import seaborn as sns sns.set(font_scale=1.4)
モデル化するシナリオは、コンテンツフィルタリングまたはマルウェアデータベースです。 いくつかのbenign_features
があります。これは、たとえば、「科学」、「歴史」、「スポーツ」に関連するコンテンツの量、またはマルウェアの場合は「コード署名」と「認識された作成者」に関連するコンテンツの量をモデル化します。
また、 malicious_features
があります。これは、たとえば、「暴力」や「麻薬」に関連するコンテンツの量、またはマルウェアの場合は「暗号ライブラリへの呼び出しが行われた回数」や「既知のマルウェアファミリーとの類似性。」
生成モデルを介して状況をモデル化します。 次の関数を使用して、約半分が良性で半分が悪意のある多数のデータポイントをランダムに生成します。
def flip(): """Simulates a coin flip.""" return 1 if random.random() < 0.5 else 0
各データポイントは、その特徴をランダムに生成します。 「良性」のデータポイントは良性の機能に対してより高いバイアスを持ち、「悪意のある」データポイントは悪意のある機能に対してより高いバイアスを持ちます。
次のように三角分布を使用します。
bins = [0.1 * i for i in range(12)] plt.hist([random.triangular(0, 1, 1) for i in range(50000)], bins)
この関数を使用して、上記のロジックをキャプチャします。
def generate(): """Samples from the triangular distribution.""" return random.triangular(0, 1, 1)
次に、データセットの作成に進みます。
m = 100000 benign_features = 5 malicious_features = 5 n = benign_features + malicious_features benign = 0 malicious = 1 X = np.zeros((m, n)) y = np.zeros((m)) for i in range(m): vec = np.zeros((n)) y[i] = flip() if y[i] == benign: for j in range(benign_features): vec[j] = generate() for j in range(malicious_features): vec[j + benign_features] = 1 - generate() else: for j in range(benign_features): vec[j] = 1 - generate() for j in range(malicious_features): vec[j + benign_features] = generate() X[i, :] = vec
X
にはランダムに生成された特徴のベクトルが含まれ、 y
にはラベルが含まれます。 この分類の問題は簡単ではありません。

良性のサンプルは一般に最初のいくつかの機能でより大きな重みを持っているのに対し、悪意のあるサンプルは一般に最後のいくつかの機能でより大きな重みを持っていることがわかります。
データの準備ができたら、簡単なトレーニングとテストの分割を実行しましょう。
from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
関数を使用して、XGBoostチュートリアルで使用するデータを準備します。
import xgboost as xgb def prepare_for_XGBoost(X, y): """Converts a numpy X and y dataset into a DMatrix for XGBoost.""" return xgb.DMatrix(X, label=y) dtrain = prepare_for_XGBoost(X_train, y_train) dtest = prepare_for_XGBoost(X_test, y_test) dall = prepare_for_XGBoost(X, y)
それでは、データに対して単純な(非単調)XGBoostモデルをトレーニングしてテストしてみましょう。 次に、混同行列を印刷して、正しくラベル付けされた正の例、正しくラベル付けされた負の例、誤ってラベル付けされた正の例、および誤ってラベル付けされた負の例の数値の内訳を確認します。
params = {"n_jobs": -1, "tree_method": "hist"} model_no_constraints = xgb.train(params=params, dtrain=dtrain) CM = predict_with_XGBoost_and_return_confusion_matrix( model_no_constraints, dtrain, y_train ) plt.figure(figsize=(12, 10)) sns.heatmap(CM / np.sum(CM), annot=True, fmt=".2%", cmap="Blues") plt.ylabel("True Label") plt.xlabel("Predicted Label") plt.title("Unconstrained model's training confusion matrix") plt.show() print() CM = predict_with_XGBoost_and_return_confusion_matrix( model_no_constraints, dtest, y_test ) plt.figure(figsize=(12, 10)) sns.heatmap(CM / np.sum(CM), annot=True, fmt=".2%", cmap="Blues") plt.ylabel("True Label") plt.xlabel("Predicted Label") plt.title("Unconstrained model's testing confusion matrix") plt.show() model_no_constraints = xgb.train(params=params, dtrain=dall)
結果を見ると、重大な過剰適合はないことがわかります。 これらの結果を単調モデルの結果と比較します。
そのために、単調なXGBoostモデルをトレーニングしてテストしましょう。 単調制約を渡す構文はシーケンス( f 0 、 f 1 、…、 f N )です。ここで、各f iは、特徴iを単調にするかどうかに応じて、-1、0、または1のいずれかになります。それぞれ、減少、制約なし、または単調に増加します。 手元のケースでは、悪意のある機能を単調に増加するように指定します。
params_constrained = params.copy() monotone_constraints = ( "(" + ",".join([str(0) for m in range(benign_features)]) + "," + ",".join([str(1) for m in range(malicious_features)]) + ")" ) print("Monotone constraints enforced are:") print(monotone_constraints) params_constrained["monotone_constraints"] = monotone_constraints model_monotonic = xgb.train(params=params_constrained, dtrain=dtrain) CM = predict_with_XGBoost_and_return_confusion_matrix(model_monotonic, dtrain, y_train) plt.figure(figsize=(12, 10)) sns.heatmap(CM / np.sum(CM), annot=True, fmt=".2%", cmap="Blues") plt.ylabel("True Label") plt.xlabel("Predicted Label") plt.title("Monotonic model's training confusion matrix") plt.show() print() CM = predict_with_XGBoost_and_return_confusion_matrix(model_monotonic, dtest, y_test) plt.figure(figsize=(12, 10)) sns.heatmap(CM / np.sum(CM), annot=True, fmt=".2%", cmap="Blues") plt.ylabel("True Label") plt.xlabel("Predicted Label") plt.title("Monotonic model's testing confusion matrix") plt.show() model_monotonic = xgb.train(params=params_constrained, dtrain=dall)
単調モデルのパフォーマンスが制約なしモデルのパフォーマンスと同じであることは明らかです。
次に、敵対的なデータセットを作成します。 すべての悪意のあるサンプルを取得し、それらをすべて1に設定することで、それらの良性の機能を「詰め込み」ます。次に、2つのモデルがどのように動作するかを並べて確認します。
X_adversarial = X[y == malicious] y_adversarial = len(X_adversarial) * [malicious] for i in range(len(X_adversarial)): vec = X_adversarial[i, :] for j in range(benign_features): vec[j] = 1 X_adversarial[i, :] = vec
これらをXGBoostが取り込むフォームに変換してみましょう。
dadv = prepare_for_XGBoost(X_adversarial, y_adversarial)
XGBoostチュートリアルの最後のステップとして、2つの機械学習モデルタイプをテストします。
CM = predict_with_XGBoost_and_return_confusion_matrix( model_no_constraints, dadv, y_adversarial ) plt.figure(figsize=(12, 10)) sns.heatmap(CM / np.sum(CM), annot=True, fmt=".2%", cmap="Blues") plt.ylabel("True Label") plt.xlabel("Predicted Label") plt.title("Unconstrained model's confusion matrix on adversarial dataset") plt.show()
CM = predict_with_XGBoost_and_return_confusion_matrix( model_monotonic, dadv, y_adversarial ) plt.figure(figsize=(12, 10)) sns.heatmap(CM / np.sum(CM), annot=True, fmt=".2%", cmap="Blues") plt.ylabel("True Label") plt.xlabel("Predicted Label") plt.title("Monotonic model's confusion matrix on adversarial dataset") plt.show()
ご覧のとおり、単調なAIモデルは、敵対的な攻撃に対して約2,500倍堅牢でした。
LightGBM
LightGBMで単調な機能を使用するための構文は似ています。
TensorFlowラティス
TensorFlow Latticeは、単調性の制約に取り組むためのもう1つのフレームワークであり、独自のラティスモデルを構築するための事前に構築されたTensorFlowEstimatorとTensorFlowオペレーターのセットです。 格子は多次元の補間ルックアップテーブルです。つまり、格子は、これらの点の関数値とともに、空間に均等に分散された点です(グリッドのように)。 Google AIブログによると:
「…ルックアップテーブルの値は、トレーニング例の損失を最小限に抑えるようにトレーニングされますが、さらに、ルックアップテーブルの隣接する値は、入力スペースの特定の方向に沿って増加するように制約されます。これにより、モデルの出力が増加します。それらの方向。 重要なのは、ルックアップテーブルの値の間を補間するため、格子モデルは滑らかで、予測が制限され、テスト時間内の誤った大小の予測を回避するのに役立ちます。」
TensorFlowLatticeの使用方法のチュートリアルはここにあります。
単調なAIモデルと未来
悪意のある攻撃からデバイスを防御することから、論理的で役立つレストランの推奨事項を提供することまで、単調なAIモデルは、社会に大きな恩恵をもたらし、習得するための素晴らしいツールであることが証明されています。 単調なモデルは、AIの安全性、フィネス、理解の新時代へと私たちを導くためにここにあります。 つまり、これが単調なAIモデルであり、これが進歩です。