두 가지 모델 버전의 A/B 테스트

새 커스텀 모델 또는 AutoML Vision Edge 모델을 학습시킨 후 A/B 테스팅을 사용하면 이미 사용 중인 모델과 비교해서 실제 상황에서 새 모델 성능을 확인해 볼 수 있습니다. 새 모델이 테스팅에서 이전 모델보다 한 단계 개선된 것으로 확인되면 앱 업데이트 없이도 모든 사용자에게 손쉽게 새 모델을 적용할 수 있습니다.

이 페이지에서는 식물 이미지 검색 기능을 가상으로 구동하는 두 가지 버전의 모델을 A/B 테스트로 평가합니다. 사용자는 이 기능을 통해 커스텀 이미지 라벨 지정 모델을 사용하여 이미지에서 식물종을 파악할 수 있습니다.

방금 게시한 새로운 식물 라벨 지정 모델인 plant_labeler_v2와 현재 모델인 plant_labeler_v1을 비교하는 실험을 진행한다고 가정하겠습니다. 아래 단계에서는 실험을 설정하고 실행하여 그 결과를 바탕으로 조치를 취하는 방법을 보여줍니다.

1. 모델을 원격으로 구성 가능하도록 설정

모델의 A/B 테스팅을 위한 첫 번째 단계는 원격 구성 매개변수를 사용하도록 앱을 수정하여 사용되는 모델을 결정하는 것입니다. 처음에는 이 매개변수의 기본값을 앱에서 이미 사용 중인 모델로 설정하지만 원격 구성이 가능한 매개변수로 모델 이름을 제어하기 때문에 사용자에게 매번 앱 업데이트를 배포하지 않아도 여러 모델을 바꿔가며 실험할 수 있습니다.

따라서 plant_labeler_v1이라는 이름으로 현재 모델을 게시했다면 다음 예시와 같이 앱 초기화 코드에서 plant_labeler_v1plant_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);
                }
            }
        });

위의 코드는 나중에 실험의 활성화 이벤트로 사용할 커스텀 애널리틱스 이벤트를 로깅합니다. 활성화 이벤트는 사용자가 실험에 참여하기 전에 트리거해야 하는 이벤트입니다. 따라서 기기에서 커스텀 ML 모델의 다운로드를 마칠 때까지 사용자가 A/B 테스트에 기록되지 않습니다.

2. 목표 측정항목 결정

다음 단계는 모델의 성공을 어떻게 측정할지 결정하고 이 측정항목에 따라 여러 모델 버전의 성능을 테스트하는 데 필요한 데이터를 앱에서 수집하도록 하는 것입니다.

A/B 테스팅에는 수익, 일일 참여도, 사용자 유지 등 기본 제공 측정항목이 몇 가지 포함되어 있습니다. 이 측정항목은 주로 다양한 UX 흐름을 테스트하거나 매개변수를 미세 조정하는 데 유용하지만 모델 및 사용 사례를 평가할 때는 적합하지 않을 수도 있습니다. 이러한 경우에는 커스텀 애널리틱스 이벤트에 맞게 최적화해 보시기 바랍니다.

예로 든 가상의 식물 이미지 검색 기능에서는 각 결과의 모델 신뢰도 순으로 검색결과를 사용자에게 제공한다고 가정합니다. 모델의 정확성을 파악할 수 있는 방법 중 하나는 사용자가 첫 번째 검색결과를 여는 빈도를 살펴보는 것입니다.

어떤 모델이 상위 결과의 클릭수 극대화라는 목표를 달성하는 데 가장 효과적인지 테스트하려면 사용자가 결과 목록에서 첫 번째 항목을 탭할 때마다 커스텀 이벤트를 로깅하면 됩니다.

Kotlin+KTX

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

Java

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

궁극적으로 테스트할 측정항목은 앱에서 모델을 사용하는 방식에 따라 달라집니다.

이 시점에서 Play 스토어에 앱 배포가 가능합니다. 앱에서는 계속 원본 모델을 사용하지만 추가한 원격 구성 및 애널리틱스 코드 덕분에 Firebase Console만 사용하여 다양한 모델을 실험할 수 있습니다.

3. A/B 테스팅 실험 진행

이제 사용자에게 앱을 배포했고 애널리틱스 데이터를 수집하고 있으니 현재 모델이 아닌 새 모델을 사용했을 때의 효과를 테스트하는 A/B 테스팅 실험을 만듭니다.

실험 생성 방법은 다음과 같습니다.

  1. Firebase Console의 이벤트 페이지에서 관련 애널리틱스 이벤트, 즉 활성화 이벤트와 목표 측정항목을 로깅하는지 확인합니다.

    이벤트가 Firebase Console에 표시되려면 앱에서 각 이벤트를 적어도 한 번씩은 로깅해야 합니다.

  2. Firebase Console에서 A/B 테스팅 섹션을 엽니다.

  3. 다음 안내에 따라 새 실험을 만듭니다.

    1. 실험 만들기 > 원격 구성을 클릭합니다.

    2. 타겟팅 섹션에서 다음과 같이 수행합니다.

      • 목록에서 앱을 선택합니다.
      • 실험에 포함할 사용자 수를 지정합니다.
      • 로깅을 시작한 활성화 이벤트를 선택합니다(이 예시에서는 nondefault_model_downloaded입니다).
    3. 목표 섹션에 있는 목표 측정항목 목록에서 이전 섹션을 통해 결정한 목표 측정항목(이 예시에서는 first_result_opened입니다)을 선택하고 구매 수익 또는 오류를 경험하지 않은 사용자 등 추적할 측정항목을 추가로 선택합니다.

    4. 변수 섹션에서 변수 2개를 정의합니다.

      • 통제그룹(자동으로 생성됨)
      • 실험용 식물 라벨러

      통제그룹에 대한 plant_labeler_model 매개변수를 만들고 plant_labeler_v1으로 설정합니다. 통제그룹에 할당된 사용자는 이전 모델을 사용하게 됩니다. 앱에서 원격 값을 사용하는지 테스트 중이므로 매개변수를 (no change)로 설정하면 안 됩니다.

      실험용 식물 라벨러 변수에서는 plant_labeler_model 매개변수를 plant_labeler_v2(이 이름으로 새 모델을 게시한 경우)로 설정합니다. 이 대안에 할당된 사용자는 새 모델을 사용하게 됩니다.

    A/B 테스트 구성 화면

실험을 시작하고, A/B 테스팅에서 최우수 대안이 판명될 때까지 며칠 정도 실행합니다. 실험에서 선두 주자가 판명되지 않은 경우 더 많은 사용자를 대상으로 실험을 확대해야 할 수 있습니다.

4. 가장 우수한 변수를 모든 사용자에게 적용

A/B 테스트 결과 카드

A/B 테스팅에서 최우수 대안, 즉 상위 검색결과 클릭수가 극대화된 대안을 판명하기에 충분한 정보가 수집되었으면 가장 우수한 대안(또는 다른 대안)을 모든 사용자에게 적용할지 여부를 결정합니다.

Firebase ConsoleA/B 테스팅 섹션에서 완료된 실험의 세부정보 뷰를 엽니다. 뷰에서 목표 측정항목 및 선택한 보조 측정항목에 따른 각 대안의 성과를 확인할 수 있습니다. 이 정보를 근거로 선두를 기록한 변수 또는 다른 변수의 전체 적용 여부를 결정할 수 있습니다.

모든 사용자에게 변수를 적용하려면 실험의 세부정보 페이지에서 > 변수 적용을 클릭합니다. 그러면 모든 사용자의 plant_labeler_model 매개변수 값이 plant_labeler_v2가 됩니다.

이후의 앱 업데이트에서는 plant_labeler_model 매개변수의 기본값을 plant_labeler_v2로 변경하고 번들 모델을 사용하는 경우 번들 모델을 업데이트해야 합니다. 사용자가 이미 최신 모델을 사용 중이므로 다음 기능 업데이트 시기 등 편의에 따라 언제든지 게시된 앱의 일부로 업데이트를 푸시하면 됩니다.