На этой странице описывается, как работать с API-интерфейсами федеративного обучения, предоставляемыми функцией персонализации на устройстве, для обучения модели с помощью процесса обучения с федеративным усреднением и фиксированным гауссовским шумом .
Прежде чем начать
Прежде чем начать, выполните следующие действия на тестовом устройстве:
Убедитесь, что установлен модуль OnDevicePersonalization. Модуль стал доступен в виде автоматического обновления в апреле 2024 года.
# List the modules installed on the device adb shell pm list packages --apex-only --show-versioncode
Убедитесь, что следующий модуль указан с кодом версии 341717000 или выше:
package:com.google.android.ondevicepersonalization versionCode:341717000
Если этого модуля нет в списке, перейдите в «Настройки» > «Безопасность и конфиденциальность» > «Обновления» > «Обновление системы Google Play», чтобы убедиться, что на вашем устройстве установлена последняя версия. При необходимости выберите Обновить .
Включите все новые функции, связанные с федеративным обучением.
# Enable On-Device Personalization apk. adb shell device_config put on_device_personalization global_kill_switch false # Enable On-Device Personalization APIs. adb shell device_config put on_device_personalization enable_ondevicepersonalization_apis true # Enable On-Device Personalization overriding. adb shell device_config put on_device_personalization enable_personalization_status_override true adb shell device_config put on_device_personalization personalization_status_override_value true # Enable Federated Compute apk. adb shell device_config put on_device_personalization federated_compute_kill_switch false
Создайте задачу федеративного обучения
Цифры на диаграмме объясняются более подробно в следующих восьми шагах.
Настройка объединенного вычислительного сервера
Федеративное обучение — это преобразование карт, которое выполняется на федеративном вычислительном сервере (редуктор) и наборе клиентов (сопоставители). Сервер Federated Compute хранит метаданные и информацию о модели каждой задачи федеративного обучения. На высоком уровне:
- Разработчик федеративного обучения создает новую задачу и загружает на сервер метаданные выполнения задачи и информацию о модели.
- Когда клиент Federated Compute инициирует новый запрос назначения задачи на сервер, сервер проверяет приемлемость задачи и возвращает соответствующую информацию о задаче.
- Как только клиент Federated Compute завершает локальные вычисления, он отправляет результаты вычислений на сервер. Затем сервер выполняет агрегацию и обработку результатов вычислений и применяет результат к окончательной модели.
Чтобы узнать больше об этих концепциях, посетите:
- Федеративное обучение: совместное машинное обучение без централизованных данных обучения
- На пути к федеративному обучению в масштабе: проектирование системы (SysML 2019)
ODP использует расширенную версию федеративного обучения, где калиброванный (централизованный) шум применяется к агрегатам перед применением к модели. Масштаб шума гарантирует, что агрегаты сохранят дифференциальную конфиденциальность.
Шаг 1. Создайте объединенный вычислительный сервер
Следуйте инструкциям проекта Federated Compute, чтобы настроить собственный Federated Compute Server.
Шаг 2. Подготовьте сохраненную функциональную модель
Подготовьте сохраненный файл FunctionalModel . Вы можете использовать «functional_model_from_keras» для преобразования «Model» в «FunctionalModel» и использовать «save_functional_model» для сериализации этой «FunctionalModel» как «SavedModel» .
functional_model = tff.learning.models.functional_model_from_keras(keras_model=model)
tff.learning.models.save_functional_model(functional_model, saved_model_path)
Шаг 3. Создайте конфигурацию федеративного вычислительного сервера.
Подготовьте файл fcp_server_config.json
, который включает политики, настройку федеративного обучения и настройку дифференциальной конфиденциальности. Пример:
# Identifies the set of client devices that will participate.
population_name: "my_new_population"
# Options you can choose:
# * TRAINING_ONLY: Only one training task will be generated under this
# population.
# * TRAINING_AND_EVAL: One training task and one evaluation task will be
# generated under this population.
# * EVAL_ONLY: Only one evaluation task will be generated under this
# population.
mode: TRAINING_AND_EVAL
policies {
# Policy for sampling on-device examples. It is checked every time a
# device attempts to start a new training.
min_separation_policy {
# The minimum number of rounds before the same client participated.
minimum_separation: 3
}
# Policy for releasing training results to developers. It is checked
# when uploading a new task to the Federated Compute Server.
model_release_policy {
# Server stops training when number of training rounds reaches this
# number.
num_max_training_rounds: 1000
}
}
# Federated learning setups. They are applied inside Task Builder.
federated_learning {
learning_process {
# Use FED_AVG to build federated learning process. Options you can
# choose:
# * FED_AVG: Federated Averaging algorithm
# (https://arxiv.org/abs/2003.00295)
# * FED_SDG: Federated SGD algorithm
# (https://arxiv.org/abs/1602.05629)
type: FED_AVG
# Optimizer used at client side training. Options you can choose:
# * ADAM
# * SGD
client_optimizer: SGD
# Learning rate used at client side training.
client_learning_rate: 0.01
# Optimizer used at server side training. Options you can choose:
# * ADAM
# * SGD
server_optimizer: ADAM
# Learning rate used at server side training.
sever_learning_rate: 1
runtime_config {
# Number of participating devices for each round of training.
report_goal: 2000
}
# List of metrics to be evaluated by the model during training and
# evaluation. Federated Compute Server provides a list of allowed
# metrics.
metrics {
name: "auc-roc"
}
metrics {
name: "binary_accuracy"
}
}
# Whether or not to generate a corresponding evaluation task under the same
# population. If this field isn't set, only one training task is
# generated under this population.
evaluation {
# The task id under the same population of the source training task that
# this evaluation task evaluates.
source_training_task_id: 1
# Decides how checkpoints from the training task are chosen for
# evaluation.
# * every_k_round: the evaluation task randomly picks one checkpoint
# from the past k rounds of training task checkpoints.
# * every_k_hour: the evaluation task randomly picks one checkpoint
# from the past k hours of training task checkpoints.
checkpoint_selector: "every_1_round"
# The traffic of this evaluation task in this population.
evaluation_traffic: 0.1
# Number of participating devices for each round of evaluation.
report_goal: 200
}
}
# Differential Privacy setups. They are applied inside the Task Builder.
differential_privacy {
# The DP aggregation algorithm you want to use. Options you can choose:
# * FIXED_GAUSSIAN: Federated Learning DP-SGD with fixed clipping norm
# described in "Learning Differentially Private Recurrent
# Language Models" (https://arxiv.org/abs/1710.06963).
# * ADAPTIVE_GAUSSIAN: Federated Learning DP-SGD with quantile-based clip
# norm estimation described in "Differentially Private
# Learning with Adaptive Clipping"
# (https://arxiv.org/abs/1905.03871).
# * TREE: DP-FTRL algorithm described in "Practical and Private (Deep)
# Learning without Sampling or Shuffling"
# (https://arxiv.org/abs/2103.00039).
# * ADADPTIVE_TREE: DP-FTRL with adaptive clipping norm descirbed in
# "Differentially Private Learning with Adaptive Clipping"
# (https://arxiv.org/abs/1905.03871).
type: FIXED_GAUSSIAN
# Noise multiplier for the Gaussian noise.
noise_multiplier: 0.1
# The value of the clipping norm.
clip_norm: 0.1
}
Шаг 4. Отправьте конфигурацию zip-архива на сервер Federated Compute.
Отправьте zip-файл и fcp_server_config.json
на сервер Federated Compute.
task_builder_client --task_builder_server='http://{federated_compute_server_endpoint}' --saved_model='saved_model' --task_config='fcp_server_config.json'
Конечная точка Federated Compute Server — это сервер, который вы настроили на шаге 1.
Встроенная библиотека операторов LiteRT поддерживает только ограниченное количество операторов TensorFlow (выберите операторы TensorFlow). Поддерживаемый набор операторов может различаться в разных версиях модуля OnDevicePersonalization. Для обеспечения совместимости процесс проверки оператора проводится в конструкторе задач во время создания задачи.
Минимальная поддерживаемая версия модуля OnDevicePersonalization будет включена в метаданные задачи. Эту информацию можно найти в информационном сообщении построителя задач.
I1023 22:16:53.058027 139653371516736 task_builder_client.py:109] Success! Tasks are built, and artifacts are uploaded to the cloud. I1023 22:16:53.058399 139653371516736 task_builder_client.py:112] applied_algorithms { learning_algo: FED_AVG client_optimizer: SGD server_optimizer: SGD dp_aggregator: FIXED_GAUSSIAN } metric_results { accepted_metrics: "binary_accuracy, binary_crossentropy, recall, precision, auc-roc, auc-pr" } dp_hyperparameters { dp_delta: 0.000001 dp_epsilon: 6.4 noise_multiplier: 1.0 dp_clip_norm: 1.0 num_training_rounds: 10000 } I1023 22:16:53.058594 139653371516736 task_builder_client.py:113] training_task { min_client_version: "341912000" } eval_task { min_client_version: "341812000" }
Сервер Federated Compute назначит эту задачу всем устройствам, оснащенным модулем OnDevicePersonalization с версией выше 341812000.
Если ваша модель включает операции, которые не поддерживаются никакими модулями OnDevicePersonalization, во время создания задачи будет сгенерировано сообщение об ошибке.
common.TaskBuilderException: Cannot build the ClientOnlyPlan: Please contact Google to register these ops: {'L2Loss': 'L2LossOp<CPUDevice, float>'} . Stop building remaining artifacts.
Подробный список поддерживаемых гибких операций можно найти на GitHub .
Создайте APK-файл для интегрированных вычислений Android
Чтобы создать APK-файл Federated Compute Android, вам необходимо указать конечную точку URL-адреса Federated Compute Server в файле AndroidManifest.xml
, к которому подключается ваш Federated Compute Client.
Шаг 5. Укажите конечную точку URL-адреса федеративного вычислительного сервера.
Укажите конечную точку URL-адреса федеративного вычислительного сервера (которую вы настроили на шаге 1) в файле AndroidManifest.xml
, к которому подключается ваш клиент федеративных вычислений.
<!-- Contents of AndroidManifest.xml -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.odpsample" >
<application android:label="OdpSample">
<!-- XML resource that contains other ODP settings. -->
<property android:name="android.ondevicepersonalization.ON_DEVICE_PERSONALIZATION_CONFIG"
android:resource="@xml/OdpSettings"></property>
<!-- The service that ODP will bind to. -->
<service android:name="com.example.odpsample.SampleService"
android:exported="true" android:isolatedProcess="true" />
</application>
</manifest>
Файл ресурсов XML, указанный в теге <property>
, также должен объявить класс обслуживания в теге <service>
и указать конечную точку URL-адреса федеративного вычислительного сервера, к которому будет подключаться клиент федеративных вычислений:
<!-- Contents of res/xml/OdpSettings.xml -->
<on-device-personalization>
<!-- Name of the service subclass -->
<service name="com.example.odpsample.SampleService">
<!-- If you want to use federated compute feature to train a model,
specify this tag. -->
<federated-compute-settings url="https://fcpserver.com/" />
</service>
</on-device-personalization>
Шаг 6. Внедрите API IsolatedWorker#onTrainingExample
Внедрите общедоступный API персонализации на устройстве IsolatedWorker#onTrainingExample
для создания обучающих данных.
Код, работающий в IsolatedProcess
не имеет прямого доступа к сети, локальным дискам или другим службам, работающим на устройстве; однако доступны следующие API:
- 'getRemoteData' — неизменяемые данные «ключ-значение», загружаемые с удаленных серверов, управляемых разработчиком, если применимо.
- 'getLocalData' — изменяемые данные «ключ-значение», локально сохраняемые разработчиками, если это применимо.
- «UserData» — данные пользователя, предоставленные платформой.
- 'getLogReader' — возвращает DAO для таблиц REQUESTS и EVENTS.
Пример:
@Override public void onTrainingExample(
@NonNull TrainingExampleInput input,
@NonNull Consumer<TrainingExampleOutput> consumer) {
// Check if the incoming training task is the task we want.
if (input.getPopulationName() == "my_new_population") {
TrainingExampleOutput result = new TrainingExampleOutput.Builder():
RequestLogRecord record = this.getLogReader().getRequestLogRecord(1);
int count = 1;
// Iterate logging event table.
for (ContentValues contentValues: record.rows()) {
Features features = Features.newBuilder()
// Retrieve carrier from user info.
.putFeature("carrier", buildFeature(mUserData.getCarrier()))
// Retrieve features from logging info.
.putFeature("int_feature_1",
buildFeature(contentValues.get("int_feature_1")
result.addTrainingExample(
Example.newBuilder()
.setFeatures(features).build().toByteArray())
.addResumptionToken(
String.format("token%d", count).getBytes()))
.build();
count++;
}
consumer.accept(result.build());
}
}
Шаг 7. Запланируйте повторяющуюся обучающую задачу.
Персонализация на устройстве предоставляет разработчикам FederatedComputeScheduler
, позволяющие планировать или отменять задания объединенных вычислений. Существуют различные варианты вызова его через IsolatedWorker
: либо по расписанию, либо по завершении асинхронной загрузки. Далее следуют примеры того и другого.
Вариант по расписанию. Вызовите
FederatedComputeScheduler#schedule
вIsolatedWorker#onExecute
.@Override public void onExecute( @NonNull ExecuteInput input, @NonNull Consumer<ExecuteOutput> consumer ) { if (input != null && input.getAppParams() != null && input.getAppParams().getString("schedule_training") != null) { if (input.getAppParams().getString("schedule_training").isEmpty()) { consumer.accept(null); return; } TrainingInterval interval = new TrainingInterval.Builder() .setMinimumInterval(Duration.ofSeconds(10)) .setSchedulingMode(2) .build(); FederatedComputeScheduler.Params params = new FederatedComputeScheduler .Params(interval); FederatedComputeInput fcInput = new FederatedComputeInput.Builder() .setPopulationName( input.getAppParams().getString("schedule_training")).build(); mFCScheduler.schedule(params, fcInput); ExecuteOutput result = new ExecuteOutput.Builder().build(); consumer.accept(result); } }
Скачать полный вариант. Вызовите
FederatedComputeScheduler#schedule
вIsolatedWorker#onDownloadCompleted
, если планирование задачи обучения зависит от каких-либо асинхронных данных или процессов.
Валидация
Следующие шаги описывают, как проверить, правильно ли выполняется задача федеративного обучения.
Шаг 8. Проверьте, правильно ли выполняется задача федеративного обучения.
Новая контрольная точка модели и новый файл показателей создаются на каждом этапе агрегирования на стороне сервера.
Метрики находятся в файле пар ключ-значение в формате JSON. Файл создается на основе списка Metrics
определенных вами на шаге 3. Пример репрезентативного JSON-файла показателей выглядит следующим образом:
{"server/client_work/train/binary_accuracy":0.5384615659713745, "server/client_work/train/binary_crossentropy":0.694046676158905, "server/client_work/train/recall":0.20000000298023224, "server/client_work/train/precision":0.3333333432674408, "server/client_work/train/auc-roc":0.3500000238418579, "server/client_work/train/auc-pr":0.44386863708496094, "server/finalizer/update_non_finite":0.0}
Вы можете использовать что-то похожее на следующий скрипт, чтобы получить метрики модели и отслеживать эффективность обучения:
import collections
import json
import matplotlib.pyplot as plt
from google.cloud import storage
# The population_name you set in fcp_server_config.json in Step 3.
POPULATION_NAME = 'my_new_population'
# The Google Cloud storage you set in Step 1.
GCS_BUCKET_NAME = 'fcp-gcs'
NUM_TRAINING_ROUND = 1000
storage_client = storage.Client()
bucket = storage_client.bucket(GCS_BUCKET_NAME)
metrics = collections.defaultdict(list)
for i in range(NUM_TRAINING_ROUND):
blob = bucket.blob('{}/{}/1/{}/s/0/metrics'.format(GCS_BUCKET_NAME, POPULATION_NAME, i+1))
with blob.open("r") as f:
metric = json.loads(f.read())
for metric_name in metric.keys():
metrics[metric_name].append(metric[metric_name])
for metric_name in metrics:
print(metric_name)
plt.plot(metrics[metric_name])
plt.show()
Обратите внимание, что на графике предыдущего примера:
- По оси X указано количество раундов обучения.
- Ось Y — значение auc-roc каждого раунда.
Обучение модели классификации изображений для персонализации на устройстве
В этом руководстве набор данных EMNIST используется для демонстрации того, как запустить задачу федеративного обучения в ODP.
Шаг 1. Создайте tff.learning.models.FunctionalModel.
def get_image_classification_input_spec():
return (
tf.TensorSpec([None, 28, 28, 1], tf.float32),
tf.TensorSpec([None, 1], tf.int64),
)
def create_and_save_image_classification_functional_model(
model_path: str,
) -> None:
keras_model = emnist_models.create_original_fedavg_cnn_model(
only_digits=True
)
functional_model = tff.learning.models.functional_model_from_keras(
keras_model=keras_model,
input_spec=get_image_classification_input_spec(),
loss_fn=tf.keras.losses.SparseCategoricalCrossentropy(),
)
tff.learning.models.save_functional_model(functional_model, model_path)
- Подробности модели emnist keras можно найти в emnist_models .
- У TfLite пока нет хорошей поддержки tf.sparse.SparseTensor или tf.RaggedTensor . Постарайтесь как можно чаще использовать tf.Tensor при построении модели.
- ODP Task Builder перезапишет все метрики при построении процесса обучения , указывать какие-либо метрики не нужно. Подробнее эта тема будет рассмотрена на шаге 2. Создайте конфигурацию построителя задач .
Поддерживаются два типа входных данных модели:
Тип 1. Кортеж(features_tensor, label_tensor).
- При создании модели input_spec выглядит так:
def get_input_spec(): return ( tf.TensorSpec([None, 28, 28, 1], tf.float32), tf.TensorSpec([None, 1], tf.int64), )
- Соедините приведенное выше со следующей реализацией общедоступного API ODP ИзолированныеWorker#onTrainingExamples, чтобы сгенерировать данные обучения на устройстве:
return tf.train.Example( features=tf.train.Features( feature={ 'x': tf.train.Feature( float_list=tf.train.FloatList(value=[1.0] * 784) ), 'y': tf.train.Feature( int64_list=tf.train.Int64List( value=[1] ) ), } ) ).SerializeToString()
Тип 2.
Tuple(Dict[feature_name, feature_tensor], label_tensor)
- При создании модели input_spec выглядит так:
def get_input_spec() -> ( Tuple[collections.OrderedDict[str, tf.TensorSpec], tf.TensorSpec] ): return ( collections.OrderedDict( [('feature-1', tf.TensorSpec([None, 1], tf.float32)), ('feature-2', tf.TensorSpec([None, 1], tf.float32))] ), tf.TensorSpec([None, 1], tf.int64), )
- Соедините предыдущее со следующей реализацией общедоступного API ODP ИзолированныеWorker#onTrainingExamples, чтобы сгенерировать данные обучения:
return tf.train.Example( features=tf.train.Features( feature={ 'feature-1': tf.train.Feature( float_list=tf.train.FloatList(value=[1.0]) ), 'feature-2': tf.train.Feature( float_list=tf.train.FloatList(value=[2.0]) ), 'my_label': tf.train.Feature( int64_list=tf.train.Int64List( value=[1] ) ), } ) ).SerializeToString()
- Не забудьте зарегистрировать label_name в конфигурации построителя задач.
mode: TRAINING_AND_EVAL # Task execution mode population_name: "my_example_model" label_name: "my_label"
ODP автоматически обрабатывает DP при построении процесса обучения. Поэтому при создании функциональной модели нет необходимости добавлять какой-либо шум.
Выходные данные этой сохраненной функциональной модели должны выглядеть как образец в нашем репозитории GitHub.
Шаг 2. Создайте конфигурацию построителя задач
Вы можете найти примеры конфигурации построителя задач в нашем репозитории GitHub.
Метрики обучения и оценки
Учитывая, что метрики могут привести к утечке пользовательских данных, в Task Builder будет список метрик, которые процесс обучения может генерировать и публиковать. Полный список вы можете найти в нашем репозитории GitHub.
Вот пример списка метрик при создании новой конфигурации построителя задач:
federated_learning { learning_process { metrics { name: "binary_accuracy" } metrics { name: "binary_crossentropy" } metrics { name: "recall" } metrics { name: "precision" } metrics { name: "auc-roc" } metrics { name: "auc-pr" } } }
Если интересующих вас метрик нет в данном списке, свяжитесь с нами.
Конфигурации ДП
Необходимо указать несколько конфигураций, связанных с DP:
policies { min_separation_policy { minimum_separation: 1 } model_release_policy { num_max_training_rounds: 1000 dp_target_epsilon: 10 dp_delta: 0.000001 } } differential_privacy { type: FIXED_GAUSSIAN clip_norm: 0.1 noise_multiplier: 0.1 }
- Для прохождения проверки присутствует либо
dp_target_epsilon
, либоnoise_mulitipiler
: (noise_to_epsilon
epislon_to_noise
). - Вы можете найти эти настройки по умолчанию в нашем репозитории GitHub.
- Для прохождения проверки присутствует либо
Шаг 3. Загрузите сохраненную модель и конфигурацию построителя задач в любое облачное хранилище разработчика.
Не забудьте обновить поля артефакта_построение при загрузке конфигурации построителя задач.
Шаг 4. (опционально) Тестирование сборки артефакта без создания новой задачи.
cd ${odp_fcp_github_repo}/python
bazel run //python/taskbuilder:task_builder_client -- --saved_model=${path_of_cloud_storage}/mnist_model/ --task_config=${path_of_cloud_storage}/mnist_cnn_task_config_build_artifact_only.pbtxt --build_artifact_only=true --task_builder_server=${task_builder_server_endpoint}
Пример модели проверяется как с помощью проверки flex ops, так и с помощью проверки dp; вы можете добавить skip_flex_ops_check
и skip_dp_check
для обхода во время проверки (эта модель не может быть развернута в текущей версии клиента ODP из-за отсутствия нескольких гибких операций).
cd ${odp_fcp_github_repo}/python
bazel run //python/taskbuilder:task_builder_client -- --saved_model=${path_of_cloud_storage}/mnist_model/ --task_config=${path_of_cloud_storage}/mnist_cnn_task_config_build_artifact_only.pbtxt --build_artifact_only=true --task_builder_server=${task_builder_server_endpoint} --skip_flex_ops_check=True --skip_dp_check=True
flex_ops_check: встроенная библиотека операторов TensorFlow Lite поддерживает только ограниченное количество операторов TensorFlow ( совместимость операторов TensorFlow Lite и TensorFlow ). Все несовместимые операции тензорного потока необходимо устанавливать с помощью гибкого делегата ( Android.bp ). Если модель содержит неподдерживаемые операции, свяжитесь с нами, чтобы зарегистрировать их:
Cannot build the ClientOnlyPlan: Please contact Google to register these ops: {...}
Лучший способ отладки построителя задач — запустить его локально:
# Starts a server at localhost:5000 bazel run //python/taskbuilder:task_builder # Links to a server at localhost:5000 by removing task_builder_server flag bazel run //python/taskbuilder:task_builder_client -- --saved_model=${path_of_cloud_storage}/mnist_model/ --task_config=${path_of_cloud_storage}/mnist_cnn_task_config_build_artifact_only.pbtxt --build_artifact_only=true --skip_flex_ops_check=True --skip_dp_check=True
Полученные артефакты вы можете найти в облачном хранилище, указанном в конфигурации. Это должно быть что-то похожее на пример в нашем репозитории GitHub .
Шаг 5. Создайте артефакты и создайте новую пару задач обучения и оценки на сервере FCP.
Удалите флаг build_artifact_only
, и построенные артефакты будут загружены на сервер FCP. Вам следует убедиться, что пара задач обучения и оценки создана успешно.
cd ${odp_fcp_github_repo}/python
bazel run //python/taskbuilder:task_builder_client -- --saved_model=${path_of_cloud_storage}/mnist_model/ --task_config=${path_of_cloud_storage}/mnist_cnn_task_config.pbtxt --task_builder_server=${task_builder_server_endpoint}
Шаг 6. Подготовьте клиентскую часть FCP
- Внедрите общедоступный API ODP
IsolatedWorker#onTrainingExamples
для создания обучающих данных. - Вызовите
FederatedComputeScheduler#schedule
. - Найдите несколько примеров в нашем репозитории исходного кода Android.
Шаг 7. Мониторинг
Метрики сервера
Инструкции по настройке можно найти в нашем репозитории GitHub.
- Метрики модели
На одной диаграмме можно сравнивать метрики разных прогонов. Например:
- Фиолетовая линия соответствует значению
noise_multiplier
0,1. - Розовая линия — это значение
noise_multipiler
0,3.