Персонализация на устройстве (On-Device Personalization, ODP) предназначена для защиты информации конечных пользователей от приложений. Приложения используют ODP для персонализации своих продуктов и услуг для конечных пользователей, но они не смогут увидеть точные настройки, сделанные для пользователя (если только не будет прямого взаимодействия вне ODP между приложением и конечным пользователем). Для приложений, использующих модели машинного обучения или статистический анализ, ODP предоставляет набор сервисов и алгоритмов, обеспечивающих надлежащую анонимизацию с использованием соответствующих механизмов дифференциальной конфиденциальности. Для получения более подробной информации см. пояснение к персонализации на устройстве .
ODP запускает код разработчика в IsolatedProcess , который не имеет прямого доступа к сети, локальным дискам или другим службам, работающим на устройстве, но имеет доступ к следующим локально сохраняемым источникам данных:
-
RemoteData— неизменяемые данные типа «ключ-значение», загружаемые с удаленных серверных частей, управляемых разработчиками (если применимо). -
LocalData— Изменяемые данные в формате ключ-значение, сохраняемые локально разработчиком, если таковые имеются. -
UserData— Пользовательские данные, предоставляемые платформой.
Поддерживаются следующие форматы вывода:
- Постоянный вывод: Эти выходные данные могут быть использованы в дальнейшей локальной обработке для получения отображаемых результатов, обучения модели с помощью федеративного обучения или статистического анализа на разных устройствах с помощью федеративной аналитики.
- Отображаемый результат:
- Разработчики могут возвращать HTML-код, отрисованный ODP, в
WebViewрасположенном внутриSurfaceView. Отрисованное там содержимое не будет видно вызывающему приложению. - Разработчики могут встраивать предоставленные ODP URL-адреса событий в HTML-вывод, чтобы запускать регистрацию и обработку взаимодействий пользователя с отображаемым HTML. ODP перехватывает запросы к этим URL-адресам и вызывает код для генерации данных, которые записываются в таблицу
EVENTS.
- Разработчики могут возвращать HTML-код, отрисованный ODP, в
Клиентские приложения и SDK могут вызывать ODP для отображения HTML-контента в SurfaceView с помощью API ODP. Контент, отображаемый в SurfaceView , не виден вызывающему приложению. Клиентское приложение или SDK может быть иным, чем то, которое разрабатывается с использованием ODP.
Сервис ODP управляет клиентским приложением, которое хочет использовать ODP для отображения персонализированного контента в своем пользовательском интерфейсе. Он загружает контент из предоставленных разработчиком конечных точек и запускает логику для постобработки загруженных данных. Он также выступает посредником во всех коммуникациях между IsolatedProcess и другими сервисами и приложениями.
Клиентские приложения используют методы класса OnDevicePersonalizationManager для взаимодействия с кодом разработчика, выполняющимся в IsolatedProcess . Код разработчика, выполняющийся в IsolatedProcess расширяет класс IsolatedService и реализует интерфейс IsolatedWorker . IsolatedService должен создавать экземпляр IsolatedWorker для каждого запроса.
На следующей диаграмме показана взаимосвязь между методами в классах OnDevicePersonalizationManager и IsolatedWorker .
OnDevicePersonalizationManager и IsolatedWorker . Клиентское приложение вызывает ODP, используя метод execute с именованным IsolatedService . Служба ODP перенаправляет вызов методу onExecute класса IsolatedWorker . IsolatedWorker возвращает записи для сохранения и контент для отображения. Служба ODP записывает сохраненные данные в таблицу REQUESTS или EVENTS и возвращает клиентскому приложению непрозрачную ссылку на отображаемый контент. Клиентское приложение может использовать эту непрозрачную ссылку в последующем вызове requestSurfacePackage для отображения любого контента в своем пользовательском интерфейсе.
Постоянный выход
Сервис ODP сохраняет запись в таблице REQUESTS после того, как реализация метода onExecute выполненная разработчиком, возвращает результат. Каждая запись в таблице REQUESTS содержит некоторые общие данные для каждого запроса, генерируемые сервисом ODP, и список возвращаемых Rows . Каждая Row содержит список пар (key, value) . Каждое значение представляет собой скаляр, строку или двоичный объект. Числовые значения могут быть представлены после агрегации, а строковые или двоичные данные — после применения локальной или централизованной дифференциальной конфиденциальности. Разработчики также могут записывать последующие события взаимодействия с пользователем в таблицу EVENTS — каждая запись в таблице EVENTS связана со строкой в таблице REQUESTS . Сервис ODP прозрачно регистрирует метку времени и имя пакета вызывающего приложения и APK-файл разработчика ODP с каждой записью.
Прежде чем начать
Прежде чем начать разработку с использованием ODP, необходимо настроить манифест пакета и включить режим разработчика.
Настройки манифеста пакета
Для использования ODP требуется следующее:
- Тег
<property>в файлеAndroidManifest.xml, указывающий на XML-ресурс в пакете, содержащий информацию о конфигурации ODP. - В файле
AndroidManifest.xmlдолжен быть тег<service>, который идентифицирует класс, расширяющийIsolatedService, как показано в следующем примере. Сервис в теге<service>должен иметьexportedатрибуты иisolatedProcessустановленный вtrue. - В XML-ресурсе, указанном на шаге 1, должен присутствовать тег
<service>, который идентифицирует класс службы из шага 2. Тег<service>также должен содержать дополнительные настройки, специфичные для ODP, внутри самого тега, как показано во втором примере.
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 binds to. -->
<service android:name="com.example.odpsample.SampleService"
android:exported="true" android:isolatedProcess="true" />
</application>
</manifest>
Манифест, специфичный для ODP, в XML-ресурсе
В XML-файле ресурсов, указанном в теге <property> , также должен быть объявлен класс службы в теге <service> и указан URL-адрес конечной точки, с которой ODP будет загружать контент для заполнения таблицы RemoteData , как показано в следующем примере. Если вы используете функции федеративных вычислений, вам также необходимо указать URL-адрес конечной точки сервера федеративных вычислений, к которому будет подключаться клиент федеративных вычислений.
<!-- Contents of res/xml/OdpSettings.xml -->
<on-device-personalization>
<!-- Name of the service subclass -->
<service name="com.example.odpsample.SampleService">
<!-- If this tag is present, ODP will periodically poll this URL and
download content to populate REMOTE_DATA. Developers that do not need to
download content from their servers can skip this tag. -->
<download-settings url="https://example.com/get" />
<!-- If you want to use federated compute feature to train a model, you
need to specify this tag. -->
<federated-compute-settings url="https://fcpserver.example.com/" />
</service>
</on-device-personalization>
Включить режим разработчика
Включите режим разработчика, следуя инструкциям в разделе «Включение параметров разработчика » документации Android Studio.
Настройки переключателя и флага
В ODP имеется набор переключателей и флагов, используемых для управления определенными функциями:
- _global_kill switch : глобальный переключатель для всех функций ODP; установите значение false, чтобы использовать ODP.
- _federated_compute_kill_switch: _ переключатель, управляющий всеми функциями обучения (федеративного обучения) ODP; установите значение false, чтобы использовать обучение.
- _caller_app_allow list : управляет тем, кому разрешено вызывать ODP; приложения (имя пакета, [необязательно] сертификат) можно добавить сюда или установить значение * для разрешения всех.
- Список _isolated_service_allow : определяет, какие службы могут запускаться в изолированном процессе службы.
Для настройки всех параметров и флагов для использования ODP без ограничений можно выполнить следующие команды:
# Set flags and killswitches
adb shell device_config set_sync_disabled_for_tests persistent
adb shell device_config put on_device_personalization global_kill_switch false
adb shell device_config put on_device_personalization federated_compute_kill_switch false
adb shell device_config put on_device_personalization caller_app_allow_list \"*\"
adb shell device_config put on_device_personalization isolated_service_allow_list \"*\"
API на стороне устройства
Ознакомьтесь с документацией по Android API для ODP.
Взаимодействие с IsolatedService
Класс IsolatedService — это абстрактный базовый класс, который все разработчики, планирующие работать с ODP, должны расширять и объявлять в манифесте пакета как работающий в изолированном процессе. Служба ODP запускает этот класс в изолированном процессе и отправляет ему запросы. IsolatedService получает запросы от службы ODP и создает IsolatedWorker для обработки запроса.
Разработчикам необходимо реализовать методы интерфейса IsolatedWorker для обработки запросов клиентского приложения, завершения загрузки и событий, запускаемых отрендеренным HTML-кодом. Все эти методы имеют реализации по умолчанию, не выполняющие никаких действий, поэтому разработчики могут пропустить реализацию тех методов, которые им не нужны.
Класс OnDevicePersonalizationManager предоставляет API для взаимодействия приложений и SDK с реализованным разработчиком IsolatedService , работающим в изолированном процессе. Ниже приведены некоторые предполагаемые варианты использования:
Сгенерируйте HTML-контент для отображения в SurfaceView.
Для генерации контента для отображения с помощью OnDevicePersonalizationManager#execute вызывающее приложение может использовать возвращенный объект SurfacePackageToken в последующем вызове requestSurfacePackage , чтобы запросить отображение результата в SurfaceView .
В случае успеха вызывается приемник с объектом SurfacePackage для представления, отображаемого службой ODP. Клиентские приложения должны вставить SurfacePackage в SurfaceView в своей иерархии представлений.
Когда приложение выполняет вызов requestSurfacePackage с SurfacePackageToken возвращенным предыдущим вызовом OnDevicePersonalizationManager#execute , служба ODP вызывает IsolatedWorker#onRender для получения фрагмента HTML-кода, который будет отображен внутри рамочного окна. На этом этапе разработчик не имеет доступа к LocalData или UserData . Это предотвращает встраивание потенциально конфиденциальных UserData в URL-адреса получения ресурсов в сгенерированном HTML. Разработчики могут использовать IsolatedService#getEventUrlProvider для генерации URL-адресов отслеживания, которые будут включены в сгенерированный HTML. После рендеринга HTML служба ODP перехватывает запросы к этим URL-адресам и вызывает IsolatedWorker#onEvent . При реализации onRender() можно вызвать getRemoteData() .
Отслеживание событий внутри HTML-контента
Класс EventUrlProvider предоставляет API для генерации URL-адресов отслеживания событий, которые разработчики могут включать в свой HTML-код. При рендеринге HTML-кода ODP вызовет IsolatedWorker#onEvent с полезной нагрузкой URL-адреса события.
Сервис ODP перехватывает запросы к URL-адресам событий, сгенерированным ODP, внутри отображаемого HTML-кода, вызывает IsolatedWorker#onEvent и записывает возвращенную EventLogRecord в таблицу EVENTS .
Запись устойчивых результатов
С помощью OnDevicePersonalizationManager#execute служба может записывать данные в постоянное хранилище (таблицы REQUESTS и EVENTS ). Вот записи, которые можно записывать в эти таблицы:
- Объект
RequestLogRecord, который будет добавлен в таблицуREQUESTS. - Список объектов
EventLogRecord, которые будут добавлены в таблицуEVENTS, каждый из которых содержит указатель на ранее созданный объектRequestLogRecord.
Сохраненные результаты, хранящиеся в памяти устройства, могут быть использованы в федеративном обучении для тренировки модели.
Управление задачами обучения на устройстве
Сервис ODP вызывает IsolatedWorker#onTrainingExample когда запускается задача обучения с использованием федеративных вычислений и требуется получить примеры обучения, предоставленные разработчиками, использующими ODP. При реализации onTrainingExample() можно вызвать getRemoteData() , getLocalData() , getUserData() и getLogReader() .
Для планирования или отмены заданий федеративных вычислений можно использовать класс FederatedComputeScheduler , который предоставляет API для всех ODP IsolatedService . Каждое задание федеративных вычислений можно идентифицировать по его имени.
Перед тем как запланировать новое задание федеративных вычислений:
- Задача с таким именем популяции уже должна быть создана на удаленном федеративном вычислительном сервере.
- URL-адрес конечной точки федеративного вычислительного сервера должен быть уже указан в настройках манифеста пакета с помощью тега
federated-compute-settings.
Взаимодействие с постоянным выводом
В следующем разделе описывается, как взаимодействовать с постоянными выходными данными в ODP.
Прочитайте локальные таблицы
Класс LogReader предоставляет API для чтения таблиц REQUESTS и EVENTS . Эти таблицы содержат данные, записанные IsolatedService во время вызовов onExecute() или onEvent() . Данные в этих таблицах могут использоваться для обучения моделей с помощью федеративного обучения или для статистического анализа на разных устройствах с помощью федеративной аналитики.
Взаимодействие с загруженным контентом
В следующем разделе описывается, как взаимодействовать с загруженным контентом в ODP.
Загрузка контента с серверов
Сервис ODP периодически загружает контент по URL-адресу, указанному в манифесте пакета IsolatedService , и вызывает onDownloadCompleted после завершения загрузки. Загрузка представляет собой JSON-файл, содержащий пары ключ-значение.
Разработчики, использующие ODP, могут выбирать, какое подмножество загруженного контента следует добавить в таблицу RemoteData , а какое удалить. Разработчики не могут изменять загруженный контент — это гарантирует, что таблица RemoteData не будет содержать никаких пользовательских данных. Кроме того, разработчики могут свободно заполнять таблицу LocalData по своему усмотрению; например, они могут кэшировать некоторые предварительно вычисленные результаты.
Формат запроса на загрузку
ODP периодически опрашивает конечную точку URL, указанную в манифесте пакета разработчика, чтобы получить содержимое для заполнения таблицы RemoteData .
Ожидается, что конечная точка вернет JSON-ответ, как описано далее. JSON-ответ должен содержать syncToken , идентифицирующий версию отправляемых данных, а также список пар ключ-значение для заполнения. Значение syncToken должно представлять собой метку времени в секундах, ограниченную часовым интервалом UTC. В рамках запроса на загрузку ODP предоставляет syncToken предыдущей завершенной загрузки и страну устройства в качестве параметров syncToken и country в URL-адресе загрузки. Сервер может использовать предыдущий syncToken для реализации инкрементальной загрузки.
Скачать файл в формате
Загруженный файл представляет собой JSON-файл со следующей структурой. Ожидается, что JSON-файл будет содержать syncToken для идентификации версии загружаемых данных. syncToken должен представлять собой метку времени UTC с ограничением по часам и должен превышать syncToken предыдущей загрузки. Если syncToken не соответствует обоим требованиям, загруженный контент отбрасывается без обработки.
Поле contents представляет собой список кортежей (key, data, encoding). Ожидается, что key будет строкой в кодировке UTF-8. Поле encoding является необязательным параметром, определяющим способ кодирования поля data — оно может быть установлено либо на "utf8", либо на "base64", и по умолчанию предполагается "utf8". Поле key преобразуется в объект String , а поле data — в массив байтов перед вызовом метода onDownloadCompleted().
{
// syncToken must be a UTC timestamp clamped to an hour boundary, and must be
// greater than the syncToken of the previously completed download.
"syncToken": <timeStampInSecRoundedToUtcHour>,
"contents": [
// List of { key, data } pairs.
{ "key": "key1",
"data": "data1"
},
{ "key": "key2",
"data": "data2",
"encoding": "base64"
},
// ...
]
}
API на стороне сервера
В этом разделе описывается, как взаимодействовать с API федеративного вычислительного сервера.
API федеративных вычислительных серверов
Для планирования задания федеративных вычислений на стороне клиента необходимо создать задачу с именем для заполнения на удаленном сервере федеративных вычислений. В этом разделе мы рассмотрим, как создать такую задачу на сервере федеративных вычислений.
При создании новой задачи в Task Builder разработчики ODP должны предоставить два набора файлов:
- Сохраненная модель tff.learning.models.FunctionalModel получена путем вызова API-функции tff.learning.models.save_functional_model . Пример можно найти в нашем репозитории на GitHub.
- Файл fcp_server_config.json содержит политики, настройки федеративного обучения и настройки дифференциальной конфиденциальности. Ниже приведен пример файла fcp_server_config.json:
{
# Task execution mode.
mode: TRAINING_AND_EVAL
# Identifies the set of client devices that participate.
population_name: "mnist_cnn_task"
policies {
# Policy for sampling on-device examples. It is checked every
# time a device is attempting to start a new training.
min_separation_policy {
# The minimum separation required between two successful
# consective task executions. If a client successfully contributes
# to a task at index `x`, the earliest they can contribute again
# is at index `(x + minimum_separation)`. This is required by
# DP.
minimum_separation: 1
}
data_availability_policy {
# The minimum number of examples on a device to be considered
# eligible for training.
min_example_count: 1
}
# Policy for releasing training results to developers adopting ODP.
model_release_policy {
# The maximum number of training rounds.
num_max_training_rounds: 512
}
}
# Federated learning setups. They are applied inside Task Builder.
federated_learning {
# Use federated averaging to build federated learning process.
# Options you can choose:
# * FED_AVG: Federated Averaging algorithm
# (https://arxiv.org/abs/2003.00295)
# * FED_SGD: Federated SGD algorithm
# (https://arxiv.org/abs/1602.05629)
type: FED_AVG
learning_process {
# 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.02
# Optimizer used at server side training. Options you can choose:
# * ADAM
# * SGD
server_optimizer: SGD
# Learning rate used at server side training.
server_learning_rate: 1.0
runtime_config {
# Number of participating devices for each round of training.
report_goal: 2
}
metrics {
name: "sparse_categorical_accuracy"
}
}
evaluation {
# A checkpoint selector controls how checkpoints are chosen for
# evaluation. One evaluation task typically runs per training
# task, and on each round of execution, the eval task
# randomly picks one checkpoint from the past 24 hours that has
# been selected for evaluation by these rules.
# Every_k_round and every_k_hour are definitions of quantization
# buckets which each checkpoint is placed in for selection.
checkpoint_selector: "every_1_round"
# The percentage of a populate that should delicate to this
# evaluation task.
evaluation_traffic: 0.2
# Number of participating devices for each round of evaluation.
report_goal: 2
}
}
# Differential Privacy setups. They are enforced inside the Task
# Builder.
differential_privacy {
# * fixed_gaussian: DP-SGD with fixed clipping norm described in
# "Learning Differentially Private Recurrent
# Language Models"
# (https://arxiv.org/abs/1710.06963).
type: FIXED_GAUSSIAN
# The value of the clipping norm.
clip_norm: 0.1
# Noise multiplier for the Gaussian noise.
noise_multiplier: 0.1
}
}
Больше примеров вы найдете в нашем репозитории на GitHub.
После подготовки этих двух входных данных запустите Task Builder для создания артефактов и генерации новых задач. Более подробные инструкции доступны в нашем репозитории GitHub.