Ver en TensorFlow.org | Ejecutar en Google Colab | Ver fuente en GitHub | Descargar cuaderno |
El tff.learning
módulo contiene una serie de aspectos a udpates modelo agregado con la configuración por defecto recomendados:
-
tff.learning.robust_aggregator
-
tff.learning.dp_aggregator
-
tff.learning.compression_aggregator
-
tff.learning.secure_aggregator
En este tutorial, explicamos la motivación subyacente, cómo se implementan y brindamos sugerencias sobre cómo personalizar su configuración.
!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 agregación están representados por objetos que se pueden pasar a tff.learning.build_federated_averaging_process
como su model_update_aggregation_factory
argumento de palabra clave. Como tal, los agregadores discutidos aquí pueden ser utilizados directamente para modificar una anterior tutorial en el aprendizaje federado.
La línea de base media ponderada de la FedAvg algoritmo se puede expresar utilizando tff.aggregators.MeanFactory
como sigue:
mean = tff.aggregators.MeanFactory()
iterative_process = tff.learning.build_federated_averaging_process(
...,
model_update_aggregation_factory=mean)
Las técnicas que se pueden utilizar para ampliar la media ponderada tratadas en este tutorial son:
- Puesta a cero
- Recorte
- Privacidad diferencial
- Compresión
- Agregación segura
La extensión se realiza utilizando la composición, en la que el MeanFactory
envuelve una fábrica de interior a la que delega alguna parte de la agregación, o es en sí mismo envuelto por otra fábrica agregación. Para más detalles sobre el diseño, vea Implementación agregadores personalizados tutorial.
Primero, explicaremos cómo habilitar y configurar estas técnicas individualmente, y luego mostraremos cómo se pueden combinar.
Tecnicas
Antes de profundizar en las técnicas individuales, primero presentamos el algoritmo de coincidencia de cuantiles, que será útil para configurar las técnicas a continuación.
Coincidencia de cuantiles
Varias de las técnicas de agregación siguientes deben utilizar un límite de norma que controle algún aspecto de la agregación. Estos límites se pueden proporcionar como una constante, pero normalmente es mejor adaptar el límite durante el curso del entrenamiento. El método recomendado es utilizar el algoritmo de coincidencia de cuantil de Andrew et al. (2019) , propuesto inicialmente por su compatibilidad con la privacidad diferencial pero útil más ampliamente. Para estimar el valor en un determinado cuantil, puede utilizar tff.aggregators.PrivateQuantileEstimationProcess
. Por ejemplo, para adaptarse a la mediana de una distribución, puede utilizar:
median_estimate = tff.aggregators.PrivateQuantileEstimationProcess.no_noise(
initial_estimate=1.0, target_quantile=0.5, learning_rate=0.2)
Las diferentes técnicas que utilizan el algoritmo de estimación de cuantiles requerirán diferentes valores de los parámetros del algoritmo, como veremos. En general, el aumento de los learning_rate
medios de parámetros de adaptación más rápida a la cuantil correcta, pero con una mayor varianza. El no_noise
classmethod construcciones cuantil un proceso de adaptación que no añade ruido a la privacidad diferencial.
Puesta a cero
La puesta a cero se refiere a reemplazar valores inusualmente grandes por ceros. Aquí, "inusualmente grande" podría significar más grande que un umbral predefinido, o grande en relación con los valores de rondas previas del cálculo. La puesta a cero puede aumentar la solidez del sistema a la corrupción de datos en clientes defectuosos.
Para calcular una media de los valores con las normas L-infinity más grandes que ZEROING_CONSTANT
cero de salida, nos envuelva una tff.aggregators.MeanFactory
con un tff.aggregators.zeroing_factory
que realiza la puesta a cero:
zeroing_mean = tff.aggregators.zeroing_factory(
zeroing_norm=MY_ZEROING_CONSTANT,
inner_agg_factory=tff.aggregators.MeanFactory())
Aquí nos envuelva una MeanFactory
con un zeroing_factory
porque queremos que el (pre-agregación) efectos de la zeroing_factory
que se aplican a los valores a los clientes antes de que se pasan al interior MeanFactory
para la agregación a través de promedios.
Sin embargo, para la mayoría de las aplicaciones recomendamos la puesta a cero adaptativa con el estimador de cuantiles. Para hacerlo, usamos el algoritmo de coincidencia de cuantiles de la siguiente manera:
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)
Los parámetros han sido elegidos de manera que los procesos se adapta muy rápidamente (relativamente grande learning_rate
) a un valor algo mayor que los valores más grandes vistos hasta ahora. Para una estimación cuantil Q
, el umbral utilizado para poner a cero será Q * multiplier + increment
.
Recorte para limitar la norma L2
Recortar las actualizaciones del cliente (proyectarlas en una bola L2) puede mejorar la solidez frente a los valores atípicos. Un tff.aggregators.clipping_factory
está estructurado exactamente como tff.aggregators.zeroing_factory
discutió anteriormente, y puede tomar ya sea una constante o una tff.templates.EstimationProcess
como su clipping_norm
argumento. La mejor práctica recomendada es utilizar un recorte que se adapte moderadamente rápido a una norma moderadamente alta, de la siguiente manera:
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)
En nuestra experiencia de muchos problemas, el valor preciso del target_quantile
no parece importar demasiado, siempre y cuando las tasas de aprendizaje están sintonizados adecuadamente. Sin embargo, establecerlo en un valor muy bajo puede requerir aumentar la tasa de aprendizaje del servidor para obtener el mejor rendimiento, en relación con no usar el recorte, por lo que recomendamos 0.8 por defecto.
Privacidad diferencial
TFF también admite la agregación privada diferencial, utilizando recorte adaptativo y ruido gaussiano. Un agregador para realizar promedios privados diferencialmente se puede construir de la siguiente manera:
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)
Orientación sobre cómo establecer el noise_multiplier
argumento se puede encontrar en el tutorial TFF DP .
Compresión con pérdida
En comparación con la compresión sin pérdida como gzip, la compresión con pérdida generalmente da como resultado una relación de compresión mucho más alta y aún se puede combinar con la compresión sin pérdida posteriormente. Dado que es necesario dedicar menos tiempo a la comunicación entre el cliente y el servidor, las rondas de capacitación se completan más rápido. Debido a la naturaleza inherentemente aleatoria de los algoritmos de aprendizaje, hasta cierto umbral, la inexactitud de la compresión con pérdida no tiene un impacto negativo en el rendimiento general.
La recomendación predeterminada es utilizar sencilla de cuantificación uniforme (ver Suresh et al. , Por ejemplo), parametrizado por dos valores: la compresión tamaño tensor threshold
y el número de quantization_bits
. Por cada tensor t
, si el número de elementos de t
es menor o igual que threshold
, no se comprime. Si es mayor, los elementos de t
se cuantifican usando redondeo aleatorio para quantizaton_bits
bits. Es decir, aplicamos la operación
t = round((t - min(t)) / (max(t) - min(t)) * (2**quantizaton_bits - 1)),
resultando en valores enteros en el rango de [0, 2**quantizaton_bits-1]
. Los valores cuantificados se empaquetan directamente en un tipo entero para su transmisión y luego se aplica la transformación inversa.
Se recomienda ajustar quantizaton_bits
igual a 8 y el 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)
Sugerencias de ajuste
Ambos parámetros, quantization_bits
y threshold
se pueden ajustar, y el número de clientes que participan en cada ronda de entrenamiento también pueden afectar a la eficacia de la compresión.
Umbral. Se elige el valor predeterminado de 20000 porque hemos observado que las variables con un número pequeño de elementos, como los sesgos en los tipos de capas comunes, son mucho más sensibles al ruido introducido. Además, en la práctica se gana poco comprimiendo variables con un número reducido de elementos, ya que su tamaño sin comprimir es relativamente pequeño para empezar.
En algunas aplicaciones, puede tener sentido cambiar la elección del umbral. Por ejemplo, los sesgos de la capa de salida de un modelo de clasificación pueden ser más sensibles al ruido. Si usted está entrenando a un modelo de lenguaje con un vocabulario de 20.004, es posible que desee establecer threshold
para ser 20.004.
Bits de cuantificación. El valor por defecto de 8 para quantization_bits
debe estar bien para la mayoría de usuarios. Si 8 funciona bien y desea exprimir un poco más el rendimiento, podría intentar reducirlo a 7 o 6. Si los recursos lo permiten hacer una pequeña búsqueda en la cuadrícula, le recomendamos que identifique el valor por el cual el entrenamiento se vuelve inestable o La calidad final del modelo comienza a degradarse y luego aumenta ese valor en dos. Por ejemplo, si la configuración quantization_bits
a 5 obras, pero poniéndolo a 4 degrada el modelo, recomendaríamos el valor predeterminado a ser de 6 a estar "en el lado seguro".
Clientes por ronda. Tenga en cuenta que el aumento significativo del número de clientes por ronda puede permitir a un valor menor para quantization_bits
para trabajar bien, debido a la inexactitud aleatorio introducido por la cuantificación puede ser igualado por un promedio de más de más actualizaciones del cliente.
Agregación segura
Por Secure Aggregation (SecAgg) nos referimos a un protocolo criptográfico en el que las actualizaciones del cliente se cifran de tal manera que el servidor solo puede descifrar su suma. Si la cantidad de clientes que informan es insuficiente, el servidor no aprenderá nada en absoluto, y en ningún caso el servidor podrá inspeccionar actualizaciones individuales. Esto se realiza mediante el tff.federated_secure_sum_bitwidth
operador.
Las actualizaciones del modelo son valores de punto flotante, pero SecAgg opera con números enteros. Por lo tanto, necesitamos recortar cualquier valor grande a algún límite antes de la discretización a un tipo entero. El límite de recorte puede ser constante o determinado de forma adaptativa (el valor predeterminado recomendado). A continuación, los números enteros se suman de forma segura y la suma se asigna de nuevo al dominio de coma flotante.
Para calcular una media con valores ponderados sumadas utilizando SecAgg con MY_SECAGG_BOUND
como el recorte unido, pasar SecureSumFactory
a MeanFactory
como:
secure_mean = tff.aggregators.MeanFactory(
tff.aggregators.SecureSumFactory(MY_SECAGG_BOUND))
Para hacer lo mismo mientras determina los límites 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)
Sugerencias de ajuste
Los parámetros adaptativos se han elegido para que los límites sean estrechos (no perderemos mucha precisión en la discretización) pero el recorte ocurre raramente.
Si ajusta los parámetros, tenga en cuenta que el protocolo SecAgg suma las actualizaciones del modelo ponderado, después de ponderar la media. Los pesos son típicamente el número de puntos de datos procesados localmente, por lo tanto, entre diferentes tareas, el límite correcto puede depender de esta cantidad.
No se recomienda utilizar el increment
argumento de palabra clave en la creación de adaptación secagg_bound
, ya que esto podría resultar en una gran pérdida de precisión relativa, en el caso de que los extremos reales estimación siendo pequeña.
El fragmento de código anterior utilizará SecAgg solo los valores ponderados. Si también se debe usar SecAgg para la suma de pesos, recomendamos que los límites se establezcan como constantes, ya que en una configuración de entrenamiento común, el mayor peso posible se conocerá de antemano:
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 composición
Las técnicas individuales para extender una media introducidas anteriormente se pueden combinar juntas.
Recomendamos que el orden en el que se apliquen estas técnicas a los clientes sea
- Puesta a cero
- Recorte
- Otras tecnicas
Los agregadores en tff.aggregators
módulo están compuestos por de envoltura "agregadores internas" (cuya pre-agregación efectos suceder últimos y post-agregación efectos ocurren primero) en el interior "agregadores exteriores". Por ejemplo, para realizar la puesta a cero, el recorte y la compresión (en ese orden), se escribiría:
# 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)
Tenga en cuenta que esta estructura coincide con los agregadores por defecto para los algoritmos de aprendizaje.
También son posibles otras composiciones. Extendemos este documento cuando estamos seguros de que podemos proporcionar una configuración predeterminada que funcione en múltiples aplicaciones diferentes. Para la implementación de nuevas ideas, vea Implementación agregadores personalizados tutorial.