ヘルプKaggleにTensorFlowグレートバリアリーフを保護チャレンジに参加

学習のための推奨集計の調整

TensorFlow.orgで表示 GoogleColabで実行 GitHubでソースを表示 ノートブックをダウンロード

tff.learningモジュールは、推奨されるデフォルトの構成で集計モデルudpatesにいくつかの方法が含まれています。

このチュートリアルでは、根本的な動機とその実装方法を説明し、構成をカスタマイズする方法についての提案を提供します。


!pip install --quiet --upgrade tensorflow-federated-nightly
!pip install --quiet --upgrade nest-asyncio

import nest_asyncio
nest_asyncio.apply()
import math
import tensorflow_federated as tff
tff.federated_computation(lambda: 'Hello, World!')()
b'Hello, World!'

集計方法をに渡すことができるオブジェクトによって表されtff.learning.build_federated_averaging_processそのようmodel_update_aggregation_factoryキーワード引数。そのため、ここでの議論アグリゲータは、直接変更するために使用することができ、前のチュートリアル連合学習のを。

加重平均ベースラインFedAvgアルゴリズムを用いて表現することができるtff.aggregators.MeanFactory次のように

mean = tff.aggregators.MeanFactory()
iterative_process = tff.learning.build_federated_averaging_process(
    ...,
    model_update_aggregation_factory=mean)

このチュートリアルでカバーされている加重平均を拡張するために使用できる手法は次のとおりです。

  • ゼロ化
  • クリッピング
  • 差分プライバシー
  • 圧縮
  • 安全な集約

拡張は、その組成、使用して行われるMeanFactoryにそれ委譲集合の一部内工場をラップし、またはそれ自体であるが、別の集約工場でラップ。設計についての詳細は、参照実装のカスタムアグリゲータチュートリアルを。

最初に、これらの手法を個別に有効化および構成する方法を説明し、次にそれらを組み合わせる方法を示します。

テクニック

個々の手法を詳しく説明する前に、まず分位数マッチングアルゴリズムを紹介します。これは、以下の手法を構成するのに役立ちます。

分位マッチング

以下の集約手法のいくつかは、集約のいくつかの側面を制御するノルムバウンドを使用する必要があります。このような境界は定数として提供できますが、通常はトレーニングの過程で境界を調整することをお勧めします。推奨方法は、の分位マッチングアルゴリズムを使用することであるアンドリューら。 (2019) 、最初に差分プライバシーとの互換性のために提案されているが、より広義に便利。与えられた分位で値を推定するためには、使用することができますtff.aggregators.PrivateQuantileEstimationProcess 。たとえば、分布の中央値に適応するには、次を使用できます。

median_estimate = tff.aggregators.PrivateQuantileEstimationProcess.no_noise(
    initial_estimate=1.0, target_quantile=0.5, learning_rate=0.2)

分位数推定アルゴリズムを使用するさまざまな手法では、後で説明するように、アルゴリズムパラメーターのさまざまな値が必要になります。一般的には、増加learning_rateが、より高い分散と、正しい分位に速く適応パラメータ手段を。 no_noise差分プライバシーのためにノイズを追加しないクラスメソッド構文Aクォンマッチング処理。

ゼロ化

ゼロ化とは、異常に大きな値をゼロに置き換えることです。ここで、「異常に大きい」とは、事前定義されたしきい値よりも大きいこと、または前の計算ラウンドの値に比べて大きいことを意味します。ゼロ化により、障害のあるクライアントでのデータ破損に対するシステムの堅牢性を高めることができます。

より大きなL-無限の規範と値の平均を計算するにはZEROING_CONSTANTゼロアウト、我々はラップtff.aggregators.MeanFactoryしてtff.aggregators.zeroing_factory行いがゼロということ:

zeroing_mean = tff.aggregators.zeroing_factory(
    zeroing_norm=MY_ZEROING_CONSTANT,
    inner_agg_factory=tff.aggregators.MeanFactory())

ここでは、ラップMeanFactoryしてzeroing_factory我々は(事前集約を)したいので、効果のzeroing_factory 、彼らは、内側に渡される前に、クライアントでの値に適用するMeanFactory平均を経由して集約のために。

ただし、ほとんどのアプリケーションでは、分位数推定量を使用した適応ゼロ化をお勧めします。そのために、次のように分位数マッチングアルゴリズムを使用します。

zeroing_norm = tff.aggregators.PrivateQuantileEstimationProcess.no_noise(
    initial_estimate=10.0,
    target_quantile=0.98,
    learning_rate=math.log(10),
    multiplier=2.0,
    increment=1.0)
zeroing_mean = tff.aggregators.zeroing_factory(
    zeroing_norm=zeroing_norm,
    inner_agg_factory=tff.aggregators.MeanFactory())

# Equivalent to:
# zeroing_mean = tff.learning.robust_aggregator(clipping=False)

プロセスは非常に迅速に(比較的大きな適応するようにパラメータが選択されているlearning_rateこれまで見た最大値よりもやや大きい値に)。クォン推定についてQ 、ゼロ調整のために使用される閾値は次のようになりますQ * multiplier + increment

バインドされたL2ノルムへのクリッピング

クライアントの更新をクリッピングする(L2ボールに投影する)と、外れ値に対する堅牢性を向上させることができます。 tff.aggregators.clipping_factory正確に同じように構成されtff.aggregators.zeroing_factory 、上述の、および一定のどちらか取ることができますtff.templates.EstimationProcessそのようclipping_norm引数を。推奨されるベストプラクティスは、次のように、適度に迅速に適度に高い基準に適応するクリッピングを使用することです。

clipping_norm = tff.aggregators.PrivateQuantileEstimationProcess.no_noise(
    initial_estimate=1.0,
    target_quantile=0.8,
    learning_rate=0.2)
clipping_mean = tff.aggregators.clipping_factory(
    clipping_norm=clipping_norm,
    inner_agg_factory=tff.aggregators.MeanFactory())

# Equivalent to:
# clipping_mean = tff.learning.robust_aggregator(zeroing=False)

多くの問題を超える我々の経験では、正確な値のtarget_quantile限り学習速度が適切にチューニングされているとしてあまり重要ではしていないようです。ただし、非常に低く設定すると、クリッピングを使用しない場合と比較して、最高のパフォーマンスを得るためにサーバーの学習率を上げる必要がある場合があります。そのため、デフォルトで0.8をお勧めします。

差分プライバシー

TFFは、適応クリッピングとガウスノイズを使用して、差分プライベート集約もサポートします。差分プライベート平均化を実行するアグリゲーターは、次のように構築できます。

dp_mean = tff.aggregators.DifferentiallyPrivateFactory.gaussian_adaptive(
    noise_multiplier=0.1, clients_per_round=100)

# Equivalent to:
# dp_mean = tff.learning.dp_aggregator(
#   noise_multiplier=0.1, clients_per_round=100, zeroing=False)

設定方法のガイダンスnoise_multiplier引数はで見つけることができTFF DPのチュートリアル

非可逆圧縮

gzipなどの可逆圧縮と比較すると、非可逆圧縮は一般にはるかに高い圧縮率をもたらし、後で可逆圧縮と組み合わせることができます。クライアントからサーバーへの通信に費やす必要のある時間が少ないため、トレーニングラウンドはより速く完了します。学習アルゴリズムの本質的にランダム化された性質により、あるしきい値まで、不可逆圧縮による不正確さは全体的なパフォーマンスに悪影響を及ぼしません。

デフォルトの推奨は、(参照、単純な均一量子化を使用することである。スレシュらテンソルのサイズ圧縮:例えば)2つの値によりパラメータthresholdとの数quantization_bits 。すべてのテンソルのためのtの要素数ならば、 t小さいか等しいthreshold 、それが圧縮されていません。それが大きい場合、の要素tに無作為丸めを用いて量子化されたquantizaton_bitsビット。つまり、演算を適用します

t = round((t - min(t)) / (max(t) - min(t)) * (2**quantizaton_bits - 1)),

範囲の整数値で得られた[0, 2**quantizaton_bits-1]量子化された値は、送信のために整数型に直接パックされてから、逆変換が適用されます。

私たちは、設定をお勧めしますquantizaton_bits 8に等しく、 threshold 20000に等しいです:

compressed_mean = tff.aggregators.MeanFactory(
    tff.aggregators.EncodedSumFactory.quantize_above_threshold(
        quantization_bits=8, threshold=20000))

# Equivalent to:
# compressed_mean = tff.learning.compression_aggregator(zeroing=False, clipping=False)

チューニングの提案

両方のパラメータ、 quantization_bitsthreshold調整することができ、各トレーニングラウンドに参加しているクライアントの数が、圧縮の有効性に影響を与えることができます。

しきい値。一般的なレイヤータイプのバイアスなど、要素の数が少ない変数は、導入されたノイズに対してはるかに敏感であることがわかったため、デフォルト値の20000が選択されています。さらに、圧縮されていないサイズはそもそも比較的小さいため、実際には要素数が少ない変数を圧縮しても得られるものはほとんどありません。

一部のアプリケーションでは、しきい値の選択を変更することが理にかなっている場合があります。たとえば、分類モデルの出力層のバイアスは、ノイズに対してより敏感である可能性があります。あなたは20004の語彙と言語モデルを訓練している場合は、設定したいことがありthreshold 20004であることを。

量子化ビット。 8のデフォルト値quantization_bitsほとんどのユーザにとって問題ありません。 8が正常に機能していて、パフォーマンスをもう少し絞りたい場合は、7または6に下げてみてください。リソースで小さなグリッド検索を実行できる場合は、トレーニングが不安定になる値を特定することをお勧めします。最終的なモデルの品質は低下し始め、次にその値を2つ増やします。例えば、設定場合quantization_bits 5つの作品に、しかし4が低下するモデルを、それを設定し、我々は「安全側」であることを6であることを、デフォルトをお勧めします。

ラウンドあたりのクライアント。大きくラウンドあたりのクライアント数を増やすことの値を小さく有効にできることに注意してくださいquantization_bits量子化によって導入されたランダム化不正確さがより多くのクライアントの更新を超える平均化することによって均一化することができるので、うまく動作するようにします。

安全な集約

Secure Aggregation(SecAgg)とは、サーバーが合計を復号化することしかできないようにクライアントの更新を暗号化する暗号化プロトコルを指します。報告するクライアントの数が不十分な場合、サーバーは何も学習しません。また、サーバーが個々の更新を検査することもできません。これは、使用して実現されているtff.federated_secure_sum_bitwidth演算子を。

モデルの更新は浮動小数点値ですが、SecAggは整数で動作します。したがって、整数型に離散化する前に、大きな値をある範囲にクリップする必要があります。クリッピング境界は、定数または適応的に決定することができます(推奨されるデフォルト)。次に、整数が安全に合計され、合計が浮動小数点ドメインにマップされます。

SecAggを使用して加算された加重値と平均値を計算するにはMY_SECAGG_BOUNDバインドクリッピングなど、合格SecureSumFactoryするMeanFactoryよう:

secure_mean = tff.aggregators.MeanFactory(
    tff.aggregators.SecureSumFactory(MY_SECAGG_BOUND))

境界を適応的に決定しながら同じことを行うには:

secagg_bound = tff.aggregators.PrivateQuantileEstimationProcess.no_noise(
    initial_estimate=50.0,
    target_quantile=0.95,
    learning_rate=1.0,
    multiplier=2.0)
secure_mean = tff.aggregators.MeanFactory(
    tff.aggregators.SecureSumFactory(secagg_bound))

# Equivalent to:
# secure_mean = tff.learning.secure_aggregator(zeroing=Fasle, clipping=False)

チューニングの提案

適応パラメータは、境界が厳しくなるように選択されていますが(離散化の精度がそれほど失われることはありません)、クリッピングが発生することはめったにありません。

パラメータを調整する場合、SecAggプロトコルは、平均で重み付けした後、重み付けされたモデルの更新を合計していることに注意してください。重みは通常、ローカルで処理されるデータポイントの数であるため、異なるタスク間では、右の境界はこの量に依存する可能性があります。

私たちは、使用することはお勧めしませんincrement適応の作成時にキーワード引数をsecagg_bound 、これは大きな相対精度の損失につながる可能性のような小さなものまでの場合には、実際の見積もりを終了します。

上記のコードスニペットは、加重値のみをSecAggで使用します。重みの合計にもSecAggを使用する必要がある場合は、一般的なトレーニングセットアップのように、境界を定数として設定することをお勧めします。可能な最大の重みが事前にわかっています。

secure_mean = tff.aggregators.MeanFactory(
    value_sum_factory=tff.aggregators.SecureSumFactory(secagg_bound),
    weight_sum_factory=tff.aggregators.SecureSumFactory(
        upper_bound_threshold=MAX_WEIGHT, lower_bound_threshold=0.0))

作曲テクニック

上で紹介した平均を拡張するための個々の手法は、一緒に組み合わせることができます。

これらの手法がクライアントに適用される順序をお勧めします

  1. ゼロ化
  2. クリッピング
  3. その他のテクニック

でアグリゲータtff.aggregators (そのプレ凝集効果が最後に発生し、後の凝集効果が最初に起こる)「外側アグリゲータ」内側包装「内側アグリゲータ」によって構成されているモジュール。たとえば、ゼロ調整、クリッピング、圧縮を(この順序で)実行するには、次のように記述します。

# Compression is innermost because its pre-aggregation effects are last.
compressed_mean = tff.aggregators.MeanFactory(
    tff.aggregators.EncodedSumFactory.quantize_above_threshold(
        quantization_bits=8, threshold=20000))
# Compressed mean is inner aggregator to clipping...
clipped_compressed_mean = tff.aggregators.clipping_factory(
    clipping_norm=MY_CLIPPING_CONSTANT,
    inner_agg_factory=compressed_mean)
# ...which is inner aggregator to zeroing, since zeroing happens first.
final_aggregator = tff.aggregators.zeroing_factory(
    zeroing_norm=MY_ZEROING_CONSTANT,
    inner_agg_factory=clipped_compressed_mean)

この構造は一致していることを注意デフォルトアグリゲータアルゴリズムを学ぶために。

他の構成も可能です。複数の異なるアプリケーションで機能するデフォルト構成を提供できると確信できる場合は、このドキュメントを拡張します。新しいアイデアを実現するために、参照実装のカスタムアグリゲータチュートリアルを。