Executar testes A/B com duas versões de um modelo

Depois de treinar um novo modelo personalizado ou o modelo do AutoML Vision Edge, é possível usar o A/B Testing para comparar o desempenho do novo modelo em condições reais com o do modelo que você já usa. Depois de confirmar que seu novo modelo é uma melhoria, ele poderá ser implantado facilmente para todos os usuários, sem a necessidade de uma atualização do app.

Veja nesta página como realizar um teste A/B para avaliar duas versões de um modelo que potencializa um recurso hipotético de pesquisa visual de plantas. Nele, um modelo de rotulagem de imagens personalizado permite que os usuários usem imagens para identificar espécies de plantas.

Suponha que você acabou de publicar um novo modelo de rotulagem de plantas, plant_labeler_v2, e quer executar um experimento que o compare com seu modelo atual, chamado plant_labeler_v1. Veja nas etapas abaixo como configurar e executar o experimento e tomar medidas em relação aos resultados.

1. Possibilitar a configuração remota do seu modelo

Ao fazer um teste A/B nos seus modelos, a primeira etapa é alterar o app para que use um parâmetro do Remote Config a fim de determinar qual modelo vai ser usado. Primeiro, defina o valor padrão desse parâmetro como o modelo que o app já usa. Como o nome do modelo é controlado por um parâmetro de configuração remota, é possível alterar e fazer experimentos com vários modelos sem a necessidade de enviar atualizações do app para os usuários.

Assim, ao publicar seu modelo atual com o nome plant_labeler_v1, você define, no código de inicialização do app, plant_labeler_v1 como valor padrão do parâmetro plant_labeler_model. Veja no exemplo a seguir:

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.
                  // ...
                }
            }
        });

Em seguida, altere o código de configuração do modelo para carregar o modelo especificado pelo parâmetro 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

Agora que o app usa um parâmetro Remote Config para determinar qual modelo carregar, é possível mudar o modelo. Basta publicar um novo modelo e atribuir o nome dele ao parâmetro Remote Config. Com esse recurso, o A/B Testing atribui modelos diferentes a usuários diferentes para compará-los.

Antes de continuar, faça também a seguinte adição ao download do código do modelo:

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

O código acima registra um evento personalizado no Analytics que você vai usar adiante como o evento de ativação do experimento. O usuário precisa acionar o evento de ativação antes de ser considerado para fazer parte do experimento. Isso garante que os usuários não sejam registrados no Teste A/B até que o dispositivo conclua o download do seu modelo de ML personalizado.

2. Determinar uma métrica de meta

A próxima etapa é decidir como mensurar o sucesso do seu modelo e verificar se o aplicativo está coletando os dados necessários para testar o desempenho de diferentes versões do modelo de acordo com essa métrica.

O A/B Testing tem várias métricas integradas, como "Receita", "Engajamento diário" e "Retenção de usuários". Essas métricas costumam ser úteis para testar diferentes fluxos de UX ou ajustar parâmetros, mas podem não ser adequadas para avaliar seu modelo e caso de uso. Nesses casos, otimize um evento personalizado no Analytics em vez de usar métricas.

Por exemplo, no recurso hipotético de pesquisa visual de plantas, suponha que você apresentou os resultados da pesquisa ao usuário na ordem de confiança do modelo em cada resultado. Observe a frequência com que os usuários abriram o primeiro resultado da pesquisa para verificar a precisão do seu modelo.

Para testar qual modelo melhor cumpriu o objetivo de maximizar cliques nos resultados principais, registre um evento personalizado sempre que um usuário tocar no primeiro item da lista.

Kotlin+KTX

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

Java

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

A métrica a ser testada depende, basicamente, da maneira que o aplicativo usa seu modelo.

Neste ponto, é possível implantar o aplicativo na Play Store. O app vai continuar usando seu modelo original, mas o código do Remote Config e do Analytics que você adicionou vai permitir a realização de experimentos com modelos diferentes usando apenas o Console do Firebase.

3. Realizar um experimento A/B Testing

Agora que seu aplicativo está nas mãos dos usuários e coletando dados de análise, crie um experimento do A/B Testing para avaliar o efeito do novo modelo no lugar do modelo atual.

Para criar o experimento:

  1. Na página Eventos do console do Firebase, verifique se você registrou os eventos relevantes do Google Analytics: o evento de ativação e a métrica de meta.

    É preciso que seu aplicativo registre cada evento pelo menos uma vez para que ele apareça no Console do Firebase.

  2. No console do Firebase, abra a seção A/B Testing.

  3. Crie um novo experimento:

    1. Clique em Criar experimento > Remote Config.

    2. Na seção Segmentação, siga as etapas a seguir:

      • Escolha seu aplicativo na lista.
      • Especifique quantos usuários você quer incluir no experimento.
      • Selecione o evento de ativação que você começou a registrar (neste exemplo, nondefault_model_downloaded)
    3. Na seção Metas, escolha a métrica determinada na seção anterior (neste exemplo, first_result_opened) na lista de métricas de meta e selecione as outras que você quer rastrear, como "Receita de compra" ou "Usuários sem falhas".

    4. Na seção Variantes, defina as duas a seguir:

      • Grupo de controle (criado automaticamente)
      • Rotulador de plantas experimental

      Para o grupo de controle, crie um parâmetro plant_labeler_model e defina-o como plant_labeler_v1. Os usuários atribuídos a esse grupo utilizarão o modelo antigo. Não defina o parâmetro como (no change) porque, no seu aplicativo, você está testando se está usando um valor remoto.

      Para a variante Rotulador de plantas experimental, defina o parâmetro plant_labeler_model como plant_labeler_v2 (supondo que você tenha publicado seu novo modelo com esse nome). Os usuários atribuídos a essa variante usarão o novo modelo.

    Tela de configuração do teste A/B

Inicie e execute o experimento por vários dias ou mais, até que A/B Testing declare um líder. Talvez seja necessário expandir a experiência para mais usuários se o experimento não puder determinar um líder.

4. Implementar a variante vencedora para todos os usuários

Card de resultados do teste A/B

Depois que o A/B Testing coletar informações suficientes para apresentar um líder (neste caso, a variante que maximizou os cliques nos principais resultados da pesquisa), você decidirá se quer distribuir a variante vencedora, ou qualquer outra, para todos os usuários.

Na seção A/B Testing do console Firebase, abra a visualização de detalhes do experimento concluído. Nela, você verá o desempenho de cada variante de acordo com a métrica da meta e outras métricas secundárias selecionadas. Com essas informações, você pode optar pela distribuição da variante líder ou de outra variante.

Para lançar uma variante para todos os usuários, clique em > Lançar variante na página de detalhes do experimento. Depois de fazer isso, o valor do parâmetro plant_labeler_model será plant_labeler_v2 para todos os usuários.

Em uma futura atualização do app, altere o valor padrão do parâmetro plant_labeler_model para plant_labeler_v2 e atualize o modelo agrupado, caso você use um. No entanto, seus usuários já usarão o modelo mais recente. Assim, você vai poder enviar a atualização como parte do app publicado sempre que for conveniente, como quando você fizer uma atualização de recursos.