Điều chỉnh các tổng hợp được đề xuất để học

Xem trên TensorFlow.org Chạy trong Google Colab Xem nguồn trên GitHub Tải xuống sổ ghi chép

Các tff.learning mô-đun chứa một số cách để udpates mô hình tổng hợp với cấu hình mặc định đề nghị:

Trong hướng dẫn này, chúng tôi giải thích động cơ cơ bản, cách chúng được triển khai và cung cấp các đề xuất về cách tùy chỉnh cấu hình của chúng.


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

Phương pháp tập hợp được đại diện bởi các đối tượng có thể được truyền cho tff.learning.build_federated_averaging_process như nó model_update_aggregation_factory tranh cãi từ khóa. Như vậy, việc tích hợp nội dung thảo luận ở đây có thể được sử dụng trực tiếp để sửa đổi một trước hướng dẫn về học tập liên.

Đường cơ sở trọng trung bình từ FedAvg thuật toán có thể được thể hiện bằng tff.aggregators.MeanFactory như sau:

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

Các kỹ thuật có thể được sử dụng để mở rộng giá trị trung bình có trọng số được đề cập trong hướng dẫn này là:

  • Zeroing
  • Cắt
  • Quyền riêng tư khác biệt
  • Nén
  • Tổng hợp an toàn

Việc gia hạn được thực hiện sử dụng thành phần, trong đó MeanFactory kết thúc tốt đẹp một nhà máy bên trong mà nó đại biểu một số phần của tập hợp, hoặc là chính nó được bao bọc bởi một nhà máy tập hợp. Để cụ thể hơn về thiết kế, thấy tập hợp tùy chỉnh thực hiện hướng dẫn.

Đầu tiên, chúng tôi sẽ giải thích cách bật và cấu hình các kỹ thuật này riêng lẻ, sau đó chỉ ra cách chúng có thể được kết hợp với nhau.

Kỹ thuật

Trước khi đi sâu vào các kỹ thuật riêng lẻ, trước tiên chúng tôi giới thiệu thuật toán đối sánh lượng tử, thuật toán này sẽ hữu ích cho việc định cấu hình các kỹ thuật bên dưới.

Đối sánh số lượng

Một số kỹ thuật tổng hợp dưới đây cần sử dụng một giới hạn chuẩn để kiểm soát một số khía cạnh của tổng hợp. Các giới hạn như vậy có thể được cung cấp như một hằng số, nhưng thông thường tốt hơn là bạn nên điều chỉnh giới hạn đó trong quá trình đào tạo. Cách khuyến cáo là sử dụng các thuật toán phù hợp quantile của Andrew et al. (2019) , ban đầu đề xuất để tương thích của nó với sự riêng tư khác biệt nhưng hữu ích rộng rãi hơn. Để ước tính giá trị tại một quantile nhất định, bạn có thể sử dụng tff.aggregators.PrivateQuantileEstimationProcess . Ví dụ: để thích ứng với mức trung bình của một phân phối, bạn có thể sử dụng:

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

Các techinques khác nhau sử dụng thuật toán ước lượng lượng tử sẽ yêu cầu các giá trị khác nhau của các tham số thuật toán, như chúng ta sẽ thấy. Nói chung, tăng learning_rate phương tiện tham số nhanh thích ứng với quantile đúng, nhưng với một biến cao hơn. Các no_noise classmethod cấu trúc một quantile quá trình phù hợp mà không thêm tiếng ồn cho sự riêng tư khác biệt.

Zeroing

Zeroing đề cập đến việc thay thế các giá trị lớn bất thường bằng các số không. Ở đây, "lớn bất thường" có thể có nghĩa là lớn hơn ngưỡng được xác định trước hoặc lớn hơn so với các giá trị từ các vòng tính toán trước đó. Zeroing có thể tăng cường độ mạnh mẽ của hệ thống đối với tình trạng hỏng dữ liệu trên các máy khách bị lỗi.

Để tính trung bình của các giá trị với định mức L-vô cực lớn hơn ZEROING_CONSTANT zeroed-out, chúng tôi quấn một tff.aggregators.MeanFactory với một tff.aggregators.zeroing_factory rằng thực hiện zeroing:

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

Ở đây chúng ta quấn một MeanFactory với một zeroing_factory bởi vì chúng tôi muốn (pre-tập hợp) ảnh hưởng của zeroing_factory để áp dụng cho các giá trị tại các khách hàng trước khi chúng được chuyển tới khu vực nội MeanFactory cho tập hợp qua trung bình.

Tuy nhiên, đối với hầu hết các ứng dụng, chúng tôi khuyên bạn nên lấy số 0 thích ứng với công cụ ước lượng lượng tử. Để làm như vậy, chúng tôi sử dụng thuật toán so khớp lượng tử như sau:

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)

Các thông số đã được chọn sao cho quá trình thích nghi rất nhanh chóng (tương đối lớn learning_rate ) đến một giá trị nào lớn hơn các giá trị lớn nhất thấy cho đến nay. Đối với một ước tính quantile Q , ngưỡng sử dụng cho zeroing sẽ Q * multiplier + increment .

Cắt đến định mức L2 ràng buộc

Việc cắt bớt các bản cập nhật của ứng dụng khách (chiếu lên bóng L2) có thể cải thiện độ chắc chắn đối với các trường hợp ngoại lệ. Một tff.aggregators.clipping_factory được cấu trúc giống hệt như tff.aggregators.zeroing_factory thảo luận ở trên, và có thể mất hoặc một hằng số hoặc một tff.templates.EstimationProcess như nó clipping_norm tranh cãi. Phương pháp tốt nhất được khuyến nghị là sử dụng các đoạn cắt thích ứng nhanh vừa phải với định mức cao vừa phải, như sau:

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)

Theo kinh nghiệm của chúng tôi trong nhiều vấn đề, giá trị chính xác của target_quantile dường như không thành vấn đề quá nhiều chừng nào tỷ lệ học được điều chỉnh một cách thích hợp. Tuy nhiên, đặt nó ở mức rất thấp có thể yêu cầu tăng tốc độ học tập của máy chủ để có hiệu suất tốt nhất, liên quan đến việc không sử dụng clipping, đó là lý do tại sao chúng tôi khuyên bạn nên sử dụng 0.8 theo mặc định.

Quyền riêng tư khác biệt

TFF cũng hỗ trợ tổng hợp riêng tư khác biệt, sử dụng phương pháp cắt thích ứng và nhiễu Gaussian. Một bộ tổng hợp để thực hiện tính trung bình riêng khác biệt có thể được xây dựng như sau:

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)

Hướng dẫn làm thế nào để thiết lập các noise_multiplier đối số có thể được tìm thấy trong hướng dẫn TFF DP .

Nén lỗ

So với nén không mất dữ liệu như gzip, nén mất dữ liệu thường dẫn đến tỷ lệ nén cao hơn nhiều và vẫn có thể được kết hợp với nén không mất dữ liệu sau đó. Vì cần ít thời gian hơn để giao tiếp giữa máy khách với máy chủ, các vòng huấn luyện sẽ hoàn thành nhanh hơn. Do tính chất ngẫu nhiên vốn có của thuật toán học, cho đến một số ngưỡng, tính không chính xác từ nén mất dữ liệu không có tác động tiêu cực đến hiệu suất tổng thể.

Khuyến cáo mặc định là sử dụng đơn giản thống nhất lượng tử (xem Suresh et al. Ví dụ), tham số của hai giá trị: nén kích thước tensor threshold và số lượng quantization_bits . Đối với mỗi tensor t , nếu số phần tử của t là ít hơn hoặc bằng threshold , nó không được nén. Nếu nó là lớn hơn, các yếu tố của t được lượng tử hóa sử dụng làm tròn ngẫu nhiên để quantizaton_bits bit. Đó là, chúng tôi áp dụng hoạt động

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

kết quả là giá trị số nguyên trong khoảng [0, 2**quantizaton_bits-1] . Các giá trị lượng tử hóa được đóng gói trực tiếp thành một kiểu số nguyên để truyền và sau đó phép biến đổi nghịch đảo được áp dụng.

Chúng tôi khuyên bạn nên thiết quantizaton_bits bằng đến 8 và threshold tương đương với 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)

Điều chỉnh đề xuất

Cả hai thông số, quantization_bitsthreshold có thể được điều chỉnh, và số lượng khách hàng tham gia trong mỗi vòng đào tạo cũng có thể ảnh hưởng đến hiệu quả của nén.

Ngưỡng. Giá trị mặc định là 20000 được chọn bởi vì chúng tôi đã quan sát thấy rằng các biến có số lượng phần tử nhỏ, chẳng hạn như độ lệch trong các loại lớp phổ biến, nhạy cảm hơn nhiều với nhiễu đưa vào. Hơn nữa, có rất ít điều thu được từ việc nén các biến có số lượng phần tử nhỏ trong thực tế, vì kích thước không nén của chúng là tương đối nhỏ.

Trong một số ứng dụng, việc thay đổi lựa chọn ngưỡng có thể có ý nghĩa. Ví dụ, độ lệch của lớp đầu ra của một mô hình phân loại có thể nhạy cảm hơn với nhiễu. Nếu bạn đang đào tạo một mô hình ngôn ngữ với một vốn từ vựng của 20.004, bạn có thể muốn thiết lập threshold là 20.004.

Các bit lượng tử hóa. Giá trị mặc định là 8 cho quantization_bits nên sử dụng tốt cho hầu hết người dùng. Nếu 8 đang hoạt động tốt và bạn muốn tăng hiệu suất hơn một chút, bạn có thể thử giảm nó xuống 7 hoặc 6. Nếu tài nguyên cho phép thực hiện tìm kiếm lưới nhỏ, chúng tôi khuyên bạn nên xác định giá trị mà việc đào tạo trở nên không ổn định hoặc chất lượng mô hình cuối cùng bắt đầu giảm và sau đó tăng giá trị đó lên hai. Ví dụ, nếu thiết quantization_bits đến 5 tác phẩm, nhưng đặt nó vào 4 phân hủy các mô hình, chúng tôi muốn giới thiệu mặc định là 6 là "ở bên an toàn".

Khách hàng mỗi vòng. Lưu ý rằng việc tăng đáng kể số lượng khách hàng mỗi vòng có thể kích hoạt một giá trị nhỏ hơn cho quantization_bits để làm việc tốt, bởi vì sự thiếu chính xác ngẫu nhiên được giới thiệu bởi lượng tử có thể được evened ra bởi trung bình trên cập nhật khách hàng hơn.

Tổng hợp an toàn

Bằng Tổng hợp bảo mật (SecAgg), chúng tôi đề cập đến một giao thức mật mã trong đó các bản cập nhật máy khách được mã hóa theo cách mà máy chủ chỉ có thể giải mã tổng của chúng. Nếu số lượng máy khách báo cáo lại không đủ, máy chủ sẽ không học được gì - và trong mọi trường hợp máy chủ sẽ không thể kiểm tra các bản cập nhật riêng lẻ. Này được thực hiện bằng cách sử dụng tff.federated_secure_sum_bitwidth điều hành.

Các bản cập nhật mô hình là giá trị dấu phẩy động, nhưng SecAgg hoạt động trên số nguyên. Do đó, chúng ta cần phải cắt bất kỳ giá trị lớn nào thành một số ràng buộc trước khi tùy biến thành một kiểu số nguyên. Giới hạn cắt có thể là một hằng số hoặc được xác định một cách thích ứng (mặc định được khuyến nghị). Sau đó, các số nguyên được tính tổng một cách an toàn và tổng được ánh xạ trở lại miền dấu phẩy động.

Để tính trung bình với giá trị trọng tóm tắt sử dụng SecAgg với MY_SECAGG_BOUND như cắt ràng buộc, vượt qua SecureSumFactory để MeanFactory như:

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

Để làm điều tương tự trong khi xác định giới hạn một cách thích ứng:

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)

Điều chỉnh đề xuất

Các thông số thích ứng đã được chọn để giới hạn chặt chẽ (chúng tôi sẽ không mất nhiều độ chính xác khi tùy ý) nhưng việc cắt xén hiếm khi xảy ra.

Nếu điều chỉnh các tham số, hãy nhớ rằng giao thức SecAgg đang tổng hợp các bản cập nhật mô hình có trọng số, sau khi có trọng số ở mức trung bình. Trọng số thường là số điểm dữ liệu được xử lý cục bộ, do đó giữa các tác vụ khác nhau, giới hạn bên phải có thể phụ thuộc vào số lượng này.

Chúng tôi không khuyên bạn sử dụng các increment tranh cãi từ khóa khi tạo thích nghi secagg_bound , vì điều này có thể dẫn đến một sự mất mát chính xác tương đối lớn, trong trường hợp dự toán đầu thực tế lên là nhỏ.

Đoạn mã trên sẽ chỉ sử dụng SecAgg các giá trị có trọng số. Nếu SecAgg cũng nên được sử dụng cho tổng trọng lượng, chúng tôi khuyên bạn nên đặt giới hạn dưới dạng hằng số, như trong thiết lập đào tạo thông thường, trọng lượng lớn nhất có thể sẽ được biết trước:

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

Kỹ thuật sáng tác

Các kỹ thuật riêng lẻ để mở rộng giá trị trung bình được giới thiệu ở trên có thể được kết hợp với nhau.

Chúng tôi đề xuất thứ tự áp dụng các kỹ thuật này cho khách hàng

  1. Zeroing
  2. Cắt
  3. Các kỹ thuật khác

Các tập hợp trong tff.aggregators module được sáng tác bởi gói "tập hợp bên trong" (mà trước tập hợp các hiệu ứng xảy ra hiệu ứng cuối cùng và sau khi tập hợp xảy ra đầu tiên) bên trong "tập hợp bên ngoài". Ví dụ, để thực hiện zeroing, clipping và nén (theo thứ tự đó), người ta sẽ viết:

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

Lưu ý rằng cấu trúc này phù hợp với tập hợp mặc định cho các thuật toán học.

Các sáng tác khác cũng có thể. Chúng tôi mở rộng tài liệu này khi chúng tôi tự tin rằng chúng tôi có thể cung cấp cấu hình mặc định hoạt động trong nhiều ứng dụng khác nhau. Đối với việc thực hiện những ý tưởng mới, xem tập hợp tùy chỉnh thực hiện hướng dẫn.