Google 致力于为黑人社区推动种族平等。查看具体举措

A/B 测试一个模型的两个版本

在训练新的自定义模型或 AutoML Vision Edge 模型后,您可以使用 A/B 测试来查看新模型与您已经使用的模型相比在现实条件下的表现如何。在您确认您的新模型是一项改进之后,您可以轻松地向所有用户推出新模型,而无需更新应用程序。

此页面展示了如何进行 A/B 测试,以评估支持假设的可视化植物搜索功能的模型的两个版本。此功能使用自定义图像标记模型来帮助用户从它们的图像中识别植物物种。

假设您刚刚发布了一个新的植物标签模型plant_labeler_v2并且您想要运行一个实验,将它与您当前的模型进行比较,命名为plant_labeler_v1 。下面的步骤显示了如何设置实验、运行它以及对结果采取措施。

1. 使您的模型可远程配置

对您的模型进行 A/B 测试的第一步是修改您的应用程序以使用远程配置参数来确定它使用的模型。最初,您将此参数的默认值设置为您的应用程序已经使用的模型,但由于模型名称由远程配置参数控制,您可以更改和试验不同的模型,而无需将应用程序更新推送到您的应用程序。用户每次。

因此,如果您以名称plant_labeler_v1发布当前模型,则应在应用程序初始化代码中将plant_labeler_v1设置为plant_labeler_model参数的默认值,如下例所示:

科特林+KTX

val remoteConfig = FirebaseRemoteConfig.getInstance()

val remoteConfigDefaults = HashMap<String, Any>()
remoteConfigDefaults["plant_labeler_model"] = "plant_labeler_v1"
Tasks.await(remoteConfig.setDefaultsAsync(remoteConfigDefaults))

remoteConfig.fetchAndActivate().addOnSuccessListener { success ->
    if (success) {
      // Okay to get remote values.
      // ...
    }
}

爪哇

final FirebaseRemoteConfig remoteConfig = FirebaseRemoteConfig.getInstance();

Map<String, Object> remoteConfigDefaults = new HashMap<>();
remoteConfigDefaults.put("plant_labeler_model", "plant_labeler_v1");
Tasks.await(remoteConfig.setDefaultsAsync(remoteConfigDefaults));

remoteConfig.fetchAndActivate().addOnSuccessListener(
        new OnSuccessListener<Boolean>() {
            @Override
            public void onSuccess(Boolean success) {
                if (success) {
                  // Okay to get remote values.
                  // ...
                }
            }
        });

然后,更改模型设置代码以加载由plant_labeler_model参数指定的模型:

科特林+KTX

val rcValue = remoteConfig.getValue("plant_labeler_model")
val remoteModelName = rcValue.asString()

// ...

val remoteModel = FirebaseRemoteModel.Builder(remoteModelName)
        .enableModelUpdates(true)
        .setInitialDownloadConditions(initialConditions)
        .setUpdatesDownloadConditions(updateConditions)
        .build()
FirebaseModelManager.getInstance().registerRemoteModel(remoteModel)

// Optionally configure a local model:
// https://firebase.google.com/docs/ml/android/label-images-with-automl#configure-a-local-model-source
// https://firebase.google.com/docs/ml/android/use-custom-models#configure_a_local_model

爪哇

FirebaseRemoteConfigValue rcValue = remoteConfig.getValue("plant_labeler_model");
String remoteModelName = rcValue.asString();

// ...

FirebaseRemoteModel remoteModel = new FirebaseRemoteModel.Builder(remoteModelName)
        .enableModelUpdates(true)
        .setInitialDownloadConditions(initialConditions)
        .setUpdatesDownloadConditions(updateConditions)
        .build();
FirebaseModelManager.getInstance().registerRemoteModel(remoteModel);

// Optionally configure a local model:
// https://firebase.google.com/docs/ml/android/label-images-with-automl#configure-a-local-model-source
// https://firebase.google.com/docs/ml/android/use-custom-models#configure_a_local_model

现在您的应用程序使用远程配置参数来确定要加载的模型,您只需发布新模型并将其名称分配给远程配置参数即可更改模型。此功能允许 A/B 测试将不同的模型分配给不同的用户,以便进行比较。

在继续之前,还要在模型下载代码中添加以下内容:

科特林+KTX

FirebaseModelManager.getInstance().downloadRemoteModelIfNeeded(remoteModel)
    .addOnSuccessListener {
        // If the model downloaded was specified by a remote parameter, log an
        // event, which will be our experiment's activation event.
        if (rcValue.source == FirebaseRemoteConfig.VALUE_SOURCE_REMOTE) {
            FirebaseAnalytics.getInstance(this).logEvent("nondefault_model_downloaded", null)
        }
    }

爪哇

FirebaseModelManager.getInstance().downloadRemoteModelIfNeeded(remoteModel)
        .addOnSuccessListener(new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void aVoid) {
                // If the model downloaded was specified by a remote parameter, log an
                // event, which will be our experiment's activation event.
                if (rcValue.getSource() == FirebaseRemoteConfig.VALUE_SOURCE_REMOTE) {
                    FirebaseAnalytics.getInstance(YourActivity.this)
                            .logEvent("nondefault_model_downloaded", null);
                }
            }
        });

上面的代码记录了一个自定义 Analytics 事件,您稍后将使用该事件作为实验的激活事件.激活事件是用户在被视为实验的一部分之前必须触发的事件。这可确保用户在设备完成下载自定义 ML 模型之前不会被记录在您的 A/B 测试中。

2. 确定目标指标

下一步是决定如何衡量模型的成功,并确保您的应用程序正在收集必要的数据,以根据该指标测试模型的不同版本的表现。

A/B 测试有几个内置指标,包括收入、每日参与度和用户保留率。这些指标通常可用于测试不同的 UX 流程或微调参数,但对于评估您的模型和用例可能没有意义。在这种情况下,您可以尝试针对自定义 Analytics 事件进行优化。

以假设的可视化植物搜索功能为例,假设您按照模型对每个结果的置信度的顺序向用户呈现搜索结果。了解模型准确性的一种方法是查看用户打开第一个搜索结果的频率。

为了测试哪个模型最能实现最大化结果点击的目标,每当用户点击结果列表中的第一项时,您将记录一个自定义事件。

科特林+KTX

FirebaseAnalytics.getInstance(this).logEvent("first_result_opened", null)

爪哇

FirebaseAnalytics.getInstance(YourActivity.this).logEvent("first_result_opened", null);

您测试的指标最终取决于您的应用如何使用您的模型。

此时,您可以将您的应用部署到 Play 商店。您的应用将继续使用您的原始模型,但您添加的远程配置和分析代码将允许您仅使用 Firebase 控制台来试验不同的模型。

3. 运行 A/B 测试实验

现在您的应用已掌握在您的用户手中并且正在收集分析数据,创建一个 A/B 测试实验来测试使用新模型而不是当前模型的效果。

创建实验:

  1. 在 Firebase 控制台的“事件”页面上,确认您正在记录相关的 Analytics 事件:激活事件和目标指标。

    您的应用需要在每个事件出现在 Firebase 控制台之前至少记录一次。

  2. 在 Firebase 控制台中,打开A/B 测试部分。

  3. 创建一个新实验:

    1. 单击创建实验 > 远程配置

    2. 定位部分:

      • 从列表中选择您的应用
      • 指定要在实验中包含的用户数量
      • 选择您开始记录的激活事件(在本例中为nondefault_model_downloaded
    3. 目标部分,从目标指标列表中选择您在上一部分中确定的目标指标(在本例中为first_result_opened ),然后选择您想要跟踪的任何其他指标,例如购买收入或无崩溃用户。

    4. 变体部分,定义两个变体:

      • 控制组(自动创建)
      • 实验植物贴标机

      对于Control 组,创建一个plant_labeler_model参数并将其设置为plant_labeler_v1 。分配到控制组的用户将使用旧模型。 (不要将参数设置为(no change) ,因为在您的应用程序中,您正在测试您正在使用远程值。)

      对于实验植物标签变体,将plant_labeler_model参数设置为plant_labeler_v2 (假设您以该名称发布了新模型)。分配给此变体的用户将使用新模型。

    A/B 测试配置屏幕

开始实验并让它运行几天或更长时间,直到 A/B 测试宣布领导者。如果实验无法确定领导者,您可能需要将实验扩展到更多用户

4. 向所有用户推出获胜的变体

A/B 测试结果卡

在 A/B 测试收集了足够的信息来宣布领先者(在这种情况下,是最大化搜索结果点击次数的变体)之后,您可以决定是否向所有用户推出获胜变体(或其他变体)。

Firebase 控制台A/B 测试部分,打开已完成实验的详细信息视图。在此视图中,您可以查看每个变体根据您的目标指标和您选择的任何次要指标的表现。使用此信息,您可以决定是推出主要变体还是其他变体。

要向所有用户推出变体,请点击实验详细信息页面上的 > 推出变体。执行此操作后,所有用户的plant_labeler_model参数的值将是plant_labeler_v2

在未来的应用程序更新中,您应该将plant_labeler_model参数的默认值更改为plant_labeler_v2并更新捆绑模型(如果使用)。不过,您的用户已经在使用最新模型,因此您可以在方便时将此更新作为已发布应用程序的一部分推送,例如在您下次进行功能更新时。