Ajustando agregações recomendadas para aprendizagem

Mantenha tudo organizado com as coleções Salve e categorize o conteúdo com base nas suas preferências.

Ver no TensorFlow.org Executar no Google Colab Ver fonte no GitHub Baixar caderno

O tff.learning módulo contém uma série de maneiras para udpates modelo agregados com configuração padrão recomendada:

Neste tutorial, explicamos a motivação subjacente, como eles são implementados e fornecemos sugestões sobre como personalizar sua configuração.


!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!'

Métodos de agregação são representados por objetos que podem ser passados para tff.learning.build_federated_averaging_process como seu model_update_aggregation_factory argumento palavra-chave. Como tal, os agregadores discutidos aqui podem ser diretamente usados para modificar uma anterior tutorial na aprendizagem federado.

A linha de base média ponderada do FedAvg algoritmo pode ser expresso utilizando tff.aggregators.MeanFactory como se segue:

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

As técnicas que podem ser usadas para estender a média ponderada coberta neste tutorial são:

  • Zerando
  • Clipping
  • Privacidade Diferencial
  • Compressão
  • Agregação Segura

A extensão é feito usando a composição, em que o MeanFactory envolve uma fábrica interior para que ele delega alguma parte do agregado, ou é ela própria envolvida pela outra fábrica agregação. Para mais detalhes sobre o projeto, consulte execução agregadores personalizados tutorial.

Primeiro, vamos explicar como habilitar e configurar essas técnicas individualmente e, em seguida, mostrar como elas podem ser combinadas.

Técnicas

Antes de nos aprofundarmos nas técnicas individuais, primeiro apresentamos o algoritmo de correspondência de quantis, que será útil para configurar as técnicas abaixo.

Correspondência de quantis

Várias das técnicas de agregação abaixo precisam usar um limite de norma que controla alguns aspectos da agregação. Esses limites podem ser fornecidos como uma constante, mas geralmente é melhor adaptar o limite durante o curso do treinamento. A maneira recomendada é usar o algoritmo quantil correspondência de Andrew et al. (2019) , inicialmente proposto para a sua compatibilidade com privacidade diferencial útil, mas de forma mais ampla. Para estimar o valor em um determinado quantil, você pode usar tff.aggregators.PrivateQuantileEstimationProcess . Por exemplo, para se adaptar à mediana de uma distribuição, você pode usar:

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

Diferentes técnicas que usam o algoritmo de estimativa de quantis irão requerer diferentes valores dos parâmetros do algoritmo, como veremos. Em geral, aumentando as learning_rate meio de parâmetros adaptação mais rápida ao quantil correta, mas com uma variação superior. O no_noise classmethod construções um processo quantil correspondência que não adiciona ruído de privacidade diferencial.

Zerando

Zerar se refere à substituição de valores excepcionalmente grandes por zeros. Aqui, "excepcionalmente grande" pode significar maior do que um limite predefinido ou grande em relação aos valores de rodadas anteriores do cálculo. A zeragem pode aumentar a robustez do sistema para corrupção de dados em clientes com falha.

Para calcular a média dos valores com as normas L-infinito maiores do que ZEROING_CONSTANT zerado-out, nós embrulhar um tff.aggregators.MeanFactory com um tff.aggregators.zeroing_factory que realiza a zerar:

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

Aqui nós embrulhar um MeanFactory com um zeroing_factory porque queremos que o (pré-agregação) efeitos da zeroing_factory para aplicar os valores em clientes antes que eles são passados para o interior MeanFactory para a agregação via média.

No entanto, para a maioria das aplicações, recomendamos zeragem adaptativa com o estimador de quantis. Para fazer isso, usamos o algoritmo de correspondência de quantis da seguinte maneira:

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)

Os parâmetros foram escolhidos para que o processo se adapta muito rapidamente (relativamente grande learning_rate ) para um valor um pouco maior que os maiores valores observados até agora. Para obter uma estimativa quantil Q , o limiar para fazer o zero será Q * multiplier + increment .

Clipping para a norma L2 limitada

O recorte de atualizações do cliente (projetando em uma bola L2) pode melhorar a robustez para outliers. A tff.aggregators.clipping_factory é estruturado exatamente como tff.aggregators.zeroing_factory discutido acima, e pode levar uma constante ou um tff.templates.EstimationProcess como seu clipping_norm argumento. A prática recomendada é usar recorte que se adapta moderadamente rápido a uma norma moderadamente alta, da seguinte maneira:

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)

Em nossa experiência ao longo de muitos problemas, o valor preciso de target_quantile não parece importar muito, desde que as taxas de aprendizagem são ajustados de forma adequada. No entanto, defini-lo como muito baixo pode exigir o aumento da taxa de aprendizado do servidor para melhor desempenho, em relação ao não uso de recorte, por isso recomendamos 0,8 por padrão.

Privacidade Diferencial

O TFF também oferece suporte à agregação privada diferencial, usando recorte adaptativo e ruído gaussiano. Um agregador para realizar a média privada diferencialmente pode ser construído da seguinte forma:

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)

Orientação sobre como definir o noise_multiplier argumento pode ser encontrada no tutorial TFF DP .

Compressão com perda

Comparada à compactação sem perdas, como gzip, a compactação com perdas geralmente resulta em uma taxa de compactação muito mais alta e ainda pode ser combinada com a compactação sem perdas posteriormente. Como menos tempo precisa ser gasto na comunicação cliente-servidor, as rodadas de treinamento são concluídas mais rapidamente. Devido à natureza inerentemente aleatória dos algoritmos de aprendizagem, até certo ponto, a imprecisão da compactação com perdas não tem impacto negativo no desempenho geral.

A recomendação padrão é a utilização simples de quantização uniforme (ver Suresh et al. , Por exemplo), parametrizado por dois valores de: a compressão tamanho tensor de threshold e o número de quantization_bits . Para cada tensor t , se o número de elementos de t é menor ou igual a threshold , não é comprimido. Se for maior, os elementos de t são quantificados usando arredondamento randomizado para quantizaton_bits pedaços. Ou seja, aplicamos a operação

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

resultando em valores inteiros no intervalo de [0, 2**quantizaton_bits-1] . Os valores quantizados são empacotados diretamente em um tipo inteiro para transmissão e, em seguida, a transformação inversa é aplicada.

Recomendamos a criação quantizaton_bits igual a 8 e threshold igual a 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)

Sugestões de ajuste

Ambos os parâmetros, quantization_bits e threshold pode ser ajustada, e o número de clientes que participam em cada rodada de treinamento também podem afetar a eficácia da compressão.

Limiar. O valor padrão de 20000 é escolhido porque observamos que variáveis ​​com pequeno número de elementos, como vieses em tipos de camadas comuns, são muito mais sensíveis ao ruído introduzido. Além disso, há pouco a ganhar compactando variáveis ​​com pequeno número de elementos na prática, visto que seu tamanho não compactado é relativamente pequeno para começar.

Em algumas aplicações, pode fazer sentido alterar a escolha do limite. Por exemplo, as tendências da camada de saída de um modelo de classificação podem ser mais sensíveis ao ruído. Se você está treinando um modelo de linguagem com um vocabulário de 20004, você pode querer definir threshold para ser 20,004.

Bits de quantização. O valor padrão de 8 para quantization_bits deve ser bom para a maioria dos usuários. Se 8 estiver funcionando bem e você quiser reduzir um pouco mais o desempenho, pode tentar reduzi-lo para 7 ou 6. Se os recursos permitirem fazer uma pequena pesquisa na grade, recomendamos que você identifique o valor para o qual o treinamento se torna instável ou a qualidade do modelo final começa a diminuir e, a seguir, aumenta esse valor em dois. Por exemplo, se definir quantization_bits a 5 obras, mas defini-la para 4 degrada o modelo, nós recomendamos o padrão a ser de 6 a ser "no lado seguro".

Clientes por rodada. Note-se que aumentar significativamente o número de clientes por rodada pode permitir que um valor menor para quantization_bits para trabalhar bem, porque a imprecisão randomizado introduzido pela quantização pode ser igualado por uma média de mais mais atualizações do cliente.

Agregação Segura

Por Secure Aggregation (SecAgg) nos referimos a um protocolo criptográfico em que as atualizações do cliente são criptografadas de tal forma que o servidor só pode descriptografar sua soma. Se o número de clientes que reportam for insuficiente, o servidor não aprenderá nada - e em nenhum caso o servidor será capaz de inspecionar atualizações individuais. Isto é realizado usando o tff.federated_secure_sum_bitwidth operador.

As atualizações do modelo são valores de ponto flutuante, mas SecAgg opera em inteiros. Portanto, precisamos cortar quaisquer valores grandes para algum limite antes da discretização para um tipo inteiro. O limite de recorte pode ser uma constante ou determinado adaptativamente (o padrão recomendado). Os inteiros são então somados com segurança e a soma é mapeada de volta para o domínio de ponto flutuante.

Para calcular uma média com valores ponderados somados usando SecAgg com MY_SECAGG_BOUND como o recorte ligado, passar SecureSumFactory para MeanFactory como:

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

Para fazer o mesmo enquanto determina os limites de forma adaptativa:

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)

Sugestões de ajuste

Os parâmetros adaptativos foram escolhidos de forma que os limites sejam estreitos (não perderemos muita precisão na discretização), mas o corte raramente acontece.

Se estiver ajustando os parâmetros, lembre-se que o protocolo SecAgg está somando as atualizações do modelo ponderado, após ponderar na média. Os pesos são normalmente o número de pontos de dados processados ​​localmente, portanto, entre diferentes tarefas, o limite certo pode depender dessa quantidade.

Nós não recomendamos usar o increment argumento palavra-chave ao criar adaptativa secagg_bound , pois isso pode resultar em uma grande perda de precisão relativa, no caso as extremidades reais estimados por ser pequeno.

O trecho de código acima usará SecAgg apenas os valores ponderados. Se SecAgg também deve ser usado para a soma dos pesos, recomendamos que os limites sejam definidos como constantes, como em uma configuração de treinamento comum, o maior peso possível será conhecido com antecedência:

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))

Técnicas de composição

Técnicas individuais para estender um meio introduzido acima podem ser combinadas.

Recomendamos que a ordem em que essas técnicas são aplicadas aos clientes seja

  1. Zerando
  2. Clipping
  3. Outras técnicas

Os agregadores em tff.aggregators módulo são compostas por envolver "agregadores interior" (cuja pré-agregação efeitos acontecer últimos e pós-agregação efeitos acontecer primeiro) dentro "agregadores exteriores". Por exemplo, para zerar, recortar e compactar (nessa ordem), deve-se escrever:

# 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)

Note-se que esta estrutura coincide com os agregadores padrão para algoritmos de aprendizagem.

Outras composições também são possíveis. Estendemos este documento quando temos certeza de que podemos fornecer a configuração padrão que funciona em vários aplicativos diferentes. Para a implementação de novas idéias, consulte execução agregadores personalizados tutorial.