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參數的默認值,如下例所示:

Kotlin+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.
      // ...
    }
}

Java

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參數指定的模型:

Kotlin+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

Java

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 測試將不同的模型分配給不同的用戶,以便進行比較。

在繼續之前,還要在模型下載代碼中添加以下內容:

Kotlin+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)
        }
    }

Java

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 事件進行優化。

以假設的視覺植物搜索功能為例,假設您按照模型對每個結果的置信度的順序向用戶呈現搜索結果。了解模型準確性的一種方法是查看用戶打開第一個搜索結果的頻率。

為了測試哪個模型最好地實現了最大化頂部結果點擊的目標,​​您將在用戶點擊結果列表中的第一項時記錄一個自定義事件。

Kotlin+KTX

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

Java

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 group ,創建一個plant_labeler_model參數並將其設置為plant_labeler_v1 。分配到控制組的用戶將使用舊模型。 (不要將參數設置為(no change) ,因為在您的應用程序中,您正在測試您正在使用遠程值。)

      對於Experimental plant labeler 變體,將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並更新捆綁模型(如果您使用一個)。不過,您的用戶已經在使用最新型號,因此您可以在方便時將此更新作為已發布應用程序的一部分推送,例如下次進行功能更新時。