Firebase'i TFLite destekli iOS Uygulamanıza ekleyin

1. Genel Bakış

Hedefler

Firebase ML, modelinizi kablosuz olarak dağıtmanızı sağlar. Bu, uygulama boyutunu küçük tutmanıza ve yalnızca gerektiğinde ML modelini indirmenize, birden fazla modelle denemeler yapmanıza veya tüm uygulamayı yeniden yayınlamak zorunda kalmadan ML modelinizi güncellemenize olanak tanır.

Bu kod laboratuvarında, statik bir TFLite modeli kullanan bir iOS uygulamasını, Firebase'den dinamik olarak sunulan bir modeli kullanan bir uygulamaya dönüştüreceksiniz. Şunları nasıl yapacağınızı öğreneceksiniz:

  1. TFLite modellerini Firebase ML'ye dağıtın ve bunlara uygulamanızdan erişin
  2. Modelle ilgili metrikleri Analytics ile günlüğe kaydedin
  3. Remote Config aracılığıyla hangi modelin yüklendiğini seçin
  4. A/B testi farklı modeller

Önkoşullar

Bu codelab'i başlatmadan önce yüklediğinizden emin olun:

  • Xcode 11 (veya üstü)
  • CocoaPods 1.9.1 (veya üstü)

2. Firebase konsol projesi oluşturun

Projeye Firebase ekleyin

  1. Firebase konsoluna gidin.
  2. Yeni Proje Oluştur'u seçin ve projenize "Firebase ML iOS Codelab" adını verin.

3. Örnek Projeyi Alın

Kodu İndir

Örnek projeyi klonlayarak ve proje dizininde pod update çalıştırarak başlayın:

git clone https://github.com/FirebaseExtended/codelab-digitclassifier-ios.git
cd codelab-digitclassifier-ios
pod install --repo-update

Git kurulu değilse, örnek projeyi GitHub sayfasından veya bu bağlantıya tıklayarak da indirebilirsiniz. Projeyi indirdikten sonra, Xcode'da çalıştırın ve nasıl çalıştığına dair bir fikir edinmek için rakam sınıflandırıcıyla oynayın.

Firebase'i kurun

Yeni bir Firebase projesi oluşturmak için belgeleri izleyin. Projenizi aldıktan sonra, projenizin GoogleService-Info.plist dosyasını Firebase konsolundan indirin ve Xcode projesinin kök dizinine sürükleyin.

f06cb08d48de7e10.png

Pod dosyanıza Firebase ekleyin ve pod kurulumunu çalıştırın.

pod 'Firebase/MLCommon'
pod 'FirebaseMLModelInterpreter', '0.20.0'

AppDelegate didFinishLaunchingWithOptions yönteminde, dosyanın en üstüne Firebase'i içe aktarın

import Firebase

Ve Firebase'i yapılandırmak için bir çağrı ekleyin.

FirebaseApp.configure()

Uygulamanın doğru yapılandırıldığından ve başlatıldığında çökmediğinden emin olmak için projeyi yeniden çalıştırın.

4. Firebase ML'ye bir model dağıtın

Firebase ML'ye bir model dağıtmak iki ana nedenden dolayı faydalıdır:

  1. Uygulama yükleme boyutunu küçük tutabilir ve yalnızca gerekirse modeli indirebiliriz
  2. Model düzenli olarak ve uygulamanın tamamından farklı bir sürüm döngüsüyle güncellenebilir

Uygulamamızdaki statik modeli, Firebase'den dinamik olarak indirilen bir modelle değiştirmeden önce, onu Firebase ML'ye dağıtmamız gerekiyor. Model, konsol aracılığıyla veya Firebase Admin SDK kullanılarak program aracılığıyla dağıtılabilir. Bu adımda konsol üzerinden dağıtım yapacağız.

İşleri basit tutmak için zaten uygulamamızda bulunan TensorFlow Lite modelini kullanacağız. Önce Firebase'i açın ve sol gezinme panelinde Makine Öğrenimi'ne tıklayın. Ardından "Özel"e gidin ve "Model Ekle" düğmesini tıklayın.

İstendiğinde, modele mnist_v1 gibi açıklayıcı bir ad verin ve dosyayı codelab proje dizininden yükleyin.

3c3c50e6ef12b3b.png

5. Modeli Firebase ML'den indirin

TFLite modelleri nispeten büyüyebileceğinden, uzak modeli Firebase'den uygulamanıza ne zaman indireceğinizi seçmek zor olabilir. İdeal olarak, uygulama başlatıldığında modeli hemen yüklemekten kaçınmak istiyoruz, çünkü modelimiz yalnızca bir özellik için kullanılıyorsa ve kullanıcı bu özelliği hiç kullanmıyorsa, sebepsiz yere önemli miktarda veri indirmiş oluruz. Ayrıca sadece wifi'ye bağlıyken modelleri getirme gibi indirme seçeneklerini de ayarlayabiliriz. Modelin ağ bağlantısı olmasa bile kullanılabilir olduğundan emin olmak istiyorsanız, modeli uygulamanın bir parçası olarak yedek olarak da paketlemelisiniz.

Basitlik adına, varsayılan paketlenmiş modeli kaldıracağız ve uygulama başladığında her zaman Firebase'den bir model indireceğiz. Bu şekilde, rakam tanımayı çalıştırırken, çıkarımın Firebase'den sağlanan modelle çalıştığından emin olabilirsiniz.

ModelDownloader.swift dosyasının en üstünde, ModelDownloader.swift modülünü içe aktarın.

import Firebase

Ardından aşağıdaki yöntemleri uygulayın.

static func downloadModel(named name: String,
                          completion: @escaping (RemoteModel?, DownloadError?) -> Void) {
  guard FirebaseApp.app() != nil else {
    completion(nil, .firebaseNotInitialized)
    return
  }
  guard success == nil && failure == nil else {
    completion(nil, .downloadInProgress)
    return
  }

  let remoteModel = CustomRemoteModel(name: name)
  let conditions = ModelDownloadConditions(allowsCellularAccess: true,
                                           allowsBackgroundDownloading: true)

  success = NotificationCenter.default.addObserver(forName: .firebaseMLModelDownloadDidSucceed,
                                                   object: nil,
                                                   queue: nil) { (notification) in
    defer { success = nil; failure = nil }
    guard let userInfo = notification.userInfo,
        let model = userInfo[ModelDownloadUserInfoKey.remoteModel.rawValue] as? RemoteModel
    else {
      completion(nil, .downloadReturnedEmptyModel)
      return
    }
    guard model.name == name else {
      completion(nil, .downloadReturnedWrongModel)
      return
    }
    completion(model, nil)
  }
  failure = NotificationCenter.default.addObserver(forName: .firebaseMLModelDownloadDidFail,
                                                   object: nil,
                                                   queue: nil) { (notification) in
    defer { success = nil; failure = nil }
    guard let userInfo = notification.userInfo,
        let error = userInfo[ModelDownloadUserInfoKey.error.rawValue] as? Error
    else {
      completion(nil, .mlkitError(underlyingError: DownloadError.unknownError))
      return
    }
    completion(nil, .mlkitError(underlyingError: error))
  }
  ModelManager.modelManager().download(remoteModel, conditions: conditions)
}

// Attempts to fetch the model from disk, downloading the model if it does not already exist.
static func fetchModel(named name: String,
                       completion: @escaping (String?, DownloadError?) -> Void) {
  let remoteModel = CustomRemoteModel(name: name)
  if ModelManager.modelManager().isModelDownloaded(remoteModel) {
    ModelManager.modelManager().getLatestModelFilePath(remoteModel) { (path, error) in
      completion(path, error.map { DownloadError.mlkitError(underlyingError: $0) })
    }
  } else {
    downloadModel(named: name) { (model, error) in
      guard let model = model else {
        let underlyingError = error ?? DownloadError.unknownError
        let compositeError = DownloadError.mlkitError(underlyingError: underlyingError)
        completion(nil, compositeError)
        return
      }
      ModelManager.modelManager().getLatestModelFilePath(model) { (path, pathError) in
        completion(path, error.map { DownloadError.mlkitError(underlyingError: $0) })
      }
    }
  }
}

ViewController.swift viewDidLoad dosyasında, DigitClassifier başlatma çağrısını yeni model indirme yöntemimizle değiştirin.

// Download the model from Firebase
print("Fetching model...")
ModelDownloader.fetchModel(named: "mnist_v1") { (filePath, error) in
  guard let path = filePath else {
    if let error = error {
      print(error)
    }
    return
  }
  print("Model download complete")

  // Initialize a DigitClassifier instance
  DigitClassifier.newInstance(modelPath: path) { result in
    switch result {
    case let .success(classifier):
      self.classifier = classifier
    case .error(_):
      self.resultLabel.text = "Failed to initialize."
    }
  }
}

Uygulamanızı yeniden çalıştırın. Birkaç saniye sonra, Xcode'da uzak modelin başarıyla indirildiğini belirten bir oturum açmalısınız. Bir rakam çizmeyi deneyin ve uygulamanın davranışının değişmediğini onaylayın.

6. Model doğruluğunu ölçmek için kullanıcı geri bildirimini ve dönüşümü izleyin

Model tahminleriyle ilgili kullanıcı geri bildirimlerini izleyerek modelin doğruluğunu ölçeceğiz. Bir kullanıcı "evet"i tıklarsa, bu tahminin doğru olduğunu gösterecektir.

Modelimizin doğruluğunu izlemek için bir Analytics olayı kaydedebiliriz. İlk olarak, projede kullanılmadan önce Podfile'a Analytics eklemeliyiz:

pod 'Firebase/Analytics'

Ardından ViewController.swift dosyanın en üstündeki Firebase'i içe aktarın

import Firebase

Ve correctButtonPressed yöntemine aşağıdaki kod satırını ekleyin.

Analytics.logEvent("correct_inference", parameters: nil)

Uygulamayı tekrar çalıştırın ve bir rakam çizin. Çıkarımın doğru olduğuna dair geri bildirim göndermek için "Evet" düğmesine birkaç kez basın.

Hata ayıklama analizi

Genel olarak, uygulamanız tarafından günlüğe kaydedilen olaylar, yaklaşık bir saatlik bir süre içinde gruplandırılır ve birlikte yüklenir. Bu yaklaşım, pili son kullanıcıların cihazlarında korur ve ağ veri kullanımını azaltır. Ancak, analitik uygulamanızı doğrulama amacıyla (ve analitiklerinizi DebugView raporunda görüntülemek için), olayları minimum gecikmeyle yüklemek için geliştirme cihazınızda Hata Ayıklama modunu etkinleştirebilirsiniz.

Geliştirme cihazınızda Analitik Hata Ayıklama modunu etkinleştirmek için Xcode'da aşağıdaki komut satırı bağımsız değişkenini belirtin:

-FIRDebugEnabled

Uygulamayı tekrar çalıştırın ve bir rakam çizin. Çıkarımın doğru olduğuna dair geri bildirim göndermek için "Evet" düğmesine birkaç kez basın. Artık Firebase konsolundaki hata ayıklama görünümü aracılığıyla günlük olaylarını neredeyse gerçek zamanlı olarak görüntüleyebilirsiniz. Sol gezinme çubuğundan Analytics > DebugView'a tıklayın.

5276199a086721fd.png

7. Firebase Performance ile çıkarım süresini takip edin

Modelinizi test ederken, geliştirme cihazlarında yapılan performans ölçümleri, modelin kullanıcılarınızın elinde nasıl performans göstereceğini yakalamak için yeterli değildir, çünkü kullanıcılarının uygulamanızı hangi donanım üzerinde çalıştıracağını söylemek zor. Neyse ki, modelinizin performansının daha iyi bir resmini elde etmek için modelinizin performansını Firebase Performance ile kullanıcıların cihazlarında ölçebilirsiniz.

Çıkarımı çalıştırmak için geçen süreyi ölçmek için önce Firebase'i DigitClassifier.swift'e aktarın:

import Firebase

Ardından, sınıflandırma yönteminde bir performans izlemesi başlatın ve çıkarım tamamlandığında izlemeyi durdurun. Aşağıdaki kod satırlarını doğrudan yöntem bildiriminin altına değil, DispatchQueue.global.async kapanışının içine eklediğinizden emin olun.

let inferenceTrace = Performance.startTrace(name: "tflite inference")
defer {
  inferenceTrace?.stop()
}

Merak ediyorsanız, performans izlemelerinizin günlüğe kaydedildiğini doğrulamak için buradaki talimatlar aracılığıyla hata ayıklama günlüğünü etkinleştirebilirsiniz. Bir süre sonra performans izleri Firebase Konsolunda da görünecektir.

8. Firebase ML'ye ikinci bir model dağıtın

Modelinizin daha iyi bir model mimarisine sahip olan veya daha büyük veya güncellenmiş bir veri kümesi üzerinde eğitilmiş bir sürüm gibi yeni bir sürümünü bulduğunuzda, mevcut modelimizi yeni sürümle değiştirme konusunda cazip gelebiliriz. Bununla birlikte, testte iyi performans gösteren bir model, üretimde mutlaka eşit derecede iyi performans göstermez. Bu nedenle, orijinal modelimiz ile yenisini karşılaştırmak için üretimde A/B testi yapalım.

Firebase Model Management API'yi Etkinleştir

Bu adımda, Python kodunu kullanarak TensorFlow Lite modelimizin yeni bir sürümünü dağıtmak için Firebase Model Management API'sini etkinleştireceğiz.

ML modellerinizi depolamak için bir paket oluşturun

Firebase Konsolunuzda Depolama'ya gidin ve Başlayın'a tıklayın. fbbea78f0eb3dc9f.png

Kovanızı kurmak için diyaloğu takip edin.

19517c0d6d2aa14d.png

Firebase ML API'yi etkinleştirin

Google Cloud Console'da Firebase ML API sayfasına gidin ve Etkinleştir'i tıklayın.

2414fd5cced6c984.png Sorulduğunda Rakam Sınıflandırıcı uygulamasını seçin.

Şimdi daha büyük bir veri kümesi kullanarak modelin yeni bir sürümünü eğiteceğiz ve ardından onu Firebase Admin SDK'yı kullanarak doğrudan eğitim not defterinden programlı olarak dağıtacağız.

Hizmet hesabı için özel anahtarı indirin

Firebase Admin SDK'sını kullanmadan önce bir hizmet hesabı oluşturmamız gerekecek. Bu bağlantıyı tıklayarak Firebase konsolunun Hizmet Hesapları panelini açın ve Firebase Yönetici SDK'sı için yeni bir hizmet hesabı oluşturmak üzere düğmeyi tıklayın. İstendiğinde, Yeni Özel Anahtar Oluştur düğmesini tıklayın. Colab not defterinden isteklerimizin kimliğini doğrulamak için hizmet hesabı anahtarını kullanacağız.

c3b95de1e5508516.png

Artık yeni modeli eğitip dağıtabiliriz.

  1. Bu ortak çalışma not defterini açın ve kendi Drive'ınız altında bir kopyasını oluşturun.
  2. İlk hücreyi "Geliştirilmiş bir TensorFlow Lite modeli eğitin" solundaki oynat düğmesine tıklayarak çalıştırın. Bu yeni bir modeli eğitecek ve biraz zaman alabilir.
  3. İkinci hücreyi çalıştırmak, bir dosya yükleme istemi oluşturacaktır. Hizmet hesabınızı oluştururken Firebase Konsolundan indirdiğiniz json dosyasını yükleyin.

71e847c6a85423b3.png

  1. Son iki hücreyi çalıştırın.

Colab notebook'u çalıştırdıktan sonra Firebase konsolunda ikinci bir model görmelisiniz. İkinci modelin mnist_v2 olarak adlandırıldığından emin olun.

c316683bb4d75d57.png

9. Remote Config aracılığıyla bir model seçin

Artık iki ayrı modelimiz olduğuna göre, çalışma zamanında hangi modelin indirileceğini seçmek için bir parametre ekleyeceğiz. İstemcinin aldığı parametrenin değeri, istemcinin hangi modeli indireceğini belirleyecektir. İlk olarak, Firebase konsolunu açın ve sol gezinme menüsündeki Remote Config düğmesine tıklayın. Ardından, "Parametre Ekle" düğmesine tıklayın.

Yeni parametre model_name olarak adlandırın ve ona varsayılan bir mnist_v1 değeri verin. Güncellemeleri uygulamak için Değişiklikleri Yayınla'ya tıklayın. Remote config parametresine modelin adını koyarak, test etmek istediğimiz her model için yeni bir parametre eklemeden birden fazla modeli test edebiliriz.

Parametreyi ekledikten sonra Konsolda görmelisiniz:

699b3fd32acce887.png

Kodumuzda, uzak modeli yüklerken bir çek eklememiz gerekecek. Parametreyi Remote Config'den aldığımızda, ilgili ada sahip uzak modeli getireceğiz; aksi takdirde mnist_v1 yüklemeyi deneyeceğiz. Remote Config'i kullanmadan önce, Podfile'de bir bağımlılık olarak belirterek onu projemize eklemeliyiz:

pod 'Firebase/RemoteConfig'

pod kurulumunu çalıştırın ve Xcode projesini yeniden açın. ModelDownloader.swift fetchParameterizedModel yöntemini uygulayın.

static func fetchParameterizedModel(completion: @escaping (String?, DownloadError?) -> Void) {
  RemoteConfig.remoteConfig().fetchAndActivate { (status, error) in
    DispatchQueue.main.async {
      if let error = error {
        let compositeError = DownloadError.mlkitError(underlyingError: error)
        completion(nil, compositeError)
        return
      }

      let modelName: String
      if let name = RemoteConfig.remoteConfig().configValue(forKey: "model_name").stringValue {
        modelName = name
      } else {
        let defaultName = "mnist_v1"
        print("Unable to fetch model name from config, falling back to default \(defaultName)")
        modelName = defaultName
      }

      fetchModel(named: modelName, completion: completion)
    }
  }
}

Son olarak, ViewController.swift fetchModel çağrısını az önce uyguladığımız yeni yöntemle değiştirin.

// Download the model from Firebase
print("Fetching model...")
ModelDownloader.fetchParameterizedModel { (filePath, error) in
  guard let path = filePath else {
    if let error = error {
      print(error)
    }
    return
  }
  print("Model download complete")

  // Initialize a DigitClassifier instance
  DigitClassifier.newInstance(modelPath: path) { result in
    switch result {
    case let .success(classifier):
      self.classifier = classifier
    case .error(_):
      self.resultLabel.text = "Failed to initialize."
    }
  }
}

Uygulamayı yeniden çalıştırın ve modeli doğru şekilde yüklediğinden emin olun.

10. A/B İki modeli test edin

Son olarak, iki modelimizden hangisinin daha iyi performans gösterdiğini görmek için Firebase'in yerleşik A/B Testi davranışını kullanabiliriz. Firebase konsolunda Analytics -> Etkinlikler'e gidin. correct_inference etkinliği gösteriliyorsa, bunu bir "Dönüşüm etkinliği" olarak işaretleyin, değilse, Analytics -> Dönüşüm Etkinlikleri'ne gidebilir ve "Yeni Bir Dönüşüm Etkinliği Oluştur" seçeneğini tıklayabilir ve correct_inference.

Şimdi Firebase konsolunda "Remote Config"e gidin, az önce eklediğimiz "model_name" parametresindeki daha fazla seçenek menüsünden "A/B testi" düğmesini seçin.

fad5ea36969d2aeb.png

Aşağıdaki menüde varsayılan adı kabul edin.

d7c006669ace6e40.png

Açılır menüden uygulamanızı seçin ve hedefleme ölçütlerini etkin kullanıcıların %50'si olarak değiştirin.

6246dd7c660b53fb.png

correct_inference olayını daha önce bir dönüşüm olarak ayarlayabildiyseniz, bu olayı izlenecek birincil metrik olarak kullanın. Aksi takdirde, etkinliğin Analytics'te görünmesini beklemek istemiyorsanız, correct_inference manuel olarak ekleyebilirsiniz.

1ac9c94fb3159271.png

Son olarak, Varyantlar ekranında, kontrol grubu varyantınızı mnist_v1 kullanacak ve Varyant A grubunuzu mnist_v2 kullanacak şekilde ayarlayın.

e4510434f8da31b6.png

Sağ alt köşedeki Gözden Geçir düğmesini tıklayın.

Tebrikler, iki ayrı modeliniz için başarıyla bir A/B testi oluşturdunuz! A/B testi şu anda taslak durumundadır ve herhangi bir zamanda "Denemeyi Başlat" düğmesine tıklanarak başlatılabilir.

A/B testine daha yakından bakmak için A/B Testi belgelerine bakın.

11. Sonuç

Bu codelab'de, uygulamanızdaki statik olarak paketlenmiş bir tflite varlığını Firebase'den dinamik olarak yüklenmiş bir TFLite modeliyle nasıl değiştireceğinizi öğrendiniz. TFLite ve Firebase hakkında daha fazla bilgi edinmek için diğer TFLite örneklerine ve Firebase başlangıç ​​kılavuzlarına göz atın.

Sorunuz mu var?

Sorunları Bildir