Uygulamanız özel TensorFlow Lite modelleri kullanıyorsa modellerinizi dağıtmak için Firebase ML'yi kullanabilirsiniz. Modelleri Firebase ile dağıtarak, uygulamanızın ilk indirme boyutunu azaltabilir ve uygulamanızın yeni bir sürümünü yayınlamadan uygulamanızın ML modellerini güncelleyebilirsiniz. Remote Config ve A / B Testing ile, farklı kullanıcı gruplarına dinamik olarak farklı modeller sunabilirsiniz.
TensorFlow Lite modelleri
TensorFlow Lite modelleri, mobil cihazlarda çalışacak şekilde optimize edilmiş makine öğrenimi modelleridir. Bir TensorFlow Lite modeli almak için:
- Resmi TensorFlow Lite modellerinden biri gibi önceden oluşturulmuş bir model kullanın.
- TensorFlow modelini, Keras modelini veya somut işlevi TensorFlow Lite'a dönüştürün.
Sen başlamadan önce
- Henüz yapmadıysanız, Android projenize Firebase'i ekleyin .
- Firebase Android BoM'yi kullanarak, modülünüzde (uygulama düzeyinde) Gradle dosyasında (genellikle
app/build.gradle
)app/build.gradle
ML Özel Modeller Android kitaplığının bağımlılığınıapp/build.gradle
.Ayrıca, Firebase ML Özel Modellerini kurmanın bir parçası olarak TensorFlow Lite SDK'yı uygulamanıza eklemeniz gerekir.
dependencies { // Import the BoM for the Firebase platform implementation platform('com.google.firebase:firebase-bom:26.3.0') // Declare the dependency for the Firebase ML Custom Models library // When using the BoM, you don't specify versions in Firebase library dependencies implementation 'com.google.firebase:firebase-ml-model-interpreter'
// Also declare the dependency for the TensorFlow Lite library and specify its version implementation 'org.tensorflow:tensorflow-lite:2.3.0' }Firebase Android BoM'yi kullandığınızda , uygulamanız her zaman Firebase Android kitaplıklarının uyumlu sürümlerini kullanır.
(Alternatif) Bom kullanmadan Firebase kütüphane bağımlılıklarını beyan
Firebase BoM'yi kullanmamayı seçerseniz, bağımlılık satırında her Firebase kitaplık sürümünü belirtmeniz gerekir.
Uygulamanızda birden fazla Firebase kitaplığı kullanırsanız, kitaplık sürümlerini yönetmek için BoM'yi kullanmanızı önemle tavsiye ettiğimizi unutmayın; bu, tüm sürümlerin uyumlu olmasını sağlar.
dependencies { // Declare the dependency for the Firebase ML Custom Models library // When NOT using the BoM, you must specify versions in Firebase library dependencies implementation 'com.google.firebase:firebase-ml-model-interpreter:22.0.4'
// Also declare the dependency for the TensorFlow Lite library and specify its version implementation 'org.tensorflow:tensorflow-lite:2.3.0' } - Uygulamanızın manifestinde INTERNET izninin gerekli olduğunu belirtin:
<uses-permission android:name="android.permission.INTERNET" />
1. Modelinizi dağıtın
Firebase konsolunu veya Firebase Admin Python ve Node.js SDK'larını kullanarak özel TensorFlow modellerinizi dağıtın. Özel modelleri dağıtma ve yönetme konusuna bakın.
Firebase projenize özel bir model ekledikten sonra, belirlediğiniz adı kullanarak uygulamalarınızdaki modele başvurabilirsiniz. İstediğiniz zaman yeni bir TensorFlow Lite modeli yükleyebilirsiniz ve uygulamanız yeni modeli indirir ve uygulama bir sonraki yeniden başladığında onu kullanmaya başlar. Uygulamanızın modeli güncellemeye çalışması için gereken cihaz koşullarını tanımlayabilirsiniz (aşağıya bakın).
2. Modeli cihaza indirin
TensorFlow Lite modelinizi uygulamanızda kullanmak için öncelikle modelin en son sürümünü cihaza indirmek üzere Firebase ML SDK'yı kullanın. Model indirmeyi başlatmak için, modeli yüklediğinizde atadığınız adı ve indirmeye izin vermek istediğiniz koşulları belirterek model yöneticisinin download()
yöntemini çağırın. Model cihazda değilse veya modelin daha yeni bir sürümü mevcutsa görev, modeli Firebase'den eşzamansız olarak indirir.
Modelin indirildiğini onaylayana kadar, modelle ilgili işlevselliği devre dışı bırakmalısınız - örneğin, kullanıcı arayüzünüzün bir kısmını griye çevirin veya gizleyin -.
Java
FirebaseCustomRemoteModel remoteModel =
new FirebaseCustomRemoteModel.Builder("your_model").build();
FirebaseModelDownloadConditions conditions = new FirebaseModelDownloadConditions.Builder()
.requireWifi()
.build();
FirebaseModelManager.getInstance().download(remoteModel, conditions)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void v) {
// Download complete. Depending on your app, you could enable
// the ML feature, or switch from the local model to the remote
// model, etc.
}
});
Kotlin + KTX
val remoteModel = FirebaseCustomRemoteModel.Builder("your_model").build()
val conditions = FirebaseModelDownloadConditions.Builder()
.requireWifi()
.build()
FirebaseModelManager.getInstance().download(remoteModel, conditions)
.addOnCompleteListener {
// Download complete. Depending on your app, you could enable the ML
// feature, or switch from the local model to the remote model, etc.
}
Birçok uygulama indirme görevini kendi başlatma kodunda başlatır, ancak modeli kullanmanız gerekmeden önce bunu herhangi bir noktada yapabilirsiniz.
3. Bir TensorFlow Lite yorumlayıcısını başlatın
Modeli cihaza indirdikten sonra, model yöneticisinin getLatestModelFile()
yöntemini çağırarak model dosyası konumunu alabilirsiniz. Bir TensorFlow Lite yorumlayıcısını başlatmak için bu değeri kullanın:
Java
FirebaseCustomRemoteModel remoteModel = new FirebaseCustomRemoteModel.Builder("your_model").build();
FirebaseModelManager.getInstance().getLatestModelFile(remoteModel)
.addOnCompleteListener(new OnCompleteListener<File>() {
@Override
public void onComplete(@NonNull Task<File> task) {
File modelFile = task.getResult();
if (modelFile != null) {
interpreter = new Interpreter(modelFile);
}
}
});
Kotlin + KTX
val remoteModel = FirebaseCustomRemoteModel.Builder("your_model").build()
FirebaseModelManager.getInstance().getLatestModelFile(remoteModel)
.addOnCompleteListener { task ->
val modelFile = task.result
if (modelFile != null) {
interpreter = Interpreter(modelFile)
}
}
4. Giriş verileri üzerinde çıkarım yapın
Modelinizin giriş ve çıkış şekillerini alın
TensorFlow Lite model yorumlayıcısı girdi olarak alır ve çıktı olarak bir veya daha fazla çok boyutlu dizi üretir. Bu diziler byte
, int
, long
veya float
değerlerini içerir. Bir modele veri iletmeden veya sonucunu kullanmadan önce, modelinizin kullandığı dizilerin sayısını ve boyutlarını ("şekli") bilmeniz gerekir.
Modeli kendiniz oluşturduysanız veya modelin giriş ve çıkış formatı belgelenmişse, bu bilgiye zaten sahip olabilirsiniz. Modelinizin giriş ve çıkışının şeklini ve veri türünü bilmiyorsanız, modelinizi incelemek için TensorFlow Lite yorumlayıcısını kullanabilirsiniz. Örneğin:
Python
import tensorflow as tf interpreter = tf.lite.Interpreter(model_path="your_model.tflite") interpreter.allocate_tensors() # Print input shape and type inputs = interpreter.get_input_details() print('{} input(s):'.format(len(inputs))) for i in range(0, len(inputs)): print('{} {}'.format(inputs[i]['shape'], inputs[i]['dtype'])) # Print output shape and type outputs = interpreter.get_output_details() print('\n{} output(s):'.format(len(outputs))) for i in range(0, len(outputs)): print('{} {}'.format(outputs[i]['shape'], outputs[i]['dtype']))
Örnek çıktı:
1 input(s): [ 1 224 224 3] <class 'numpy.float32'> 1 output(s): [1 1000] <class 'numpy.float32'>
Yorumlayıcıyı çalıştırın
Modelinizin girdi ve çıktısının formatını belirledikten sonra, giriş verilerinizi alın ve modeliniz için doğru şeklin girdisini elde etmek için gerekli olan veriler üzerinde herhangi bir dönüşüm gerçekleştirin. Örneğin, giriş şekli [1 224 224 3]
kayan nokta değerlerine sahip bir görüntü sınıflandırma modeliniz varsa, aşağıdaki örnekte gösterildiği gibi bir Bitmap
nesnesinden bir girdi ByteBuffer
üretebilirsiniz:
Java
Bitmap bitmap = Bitmap.createScaledBitmap(yourInputImage, 224, 224, true);
ByteBuffer input = ByteBuffer.allocateDirect(224 * 224 * 3 * 4).order(ByteOrder.nativeOrder());
for (int y = 0; y < 224; y++) {
for (int x = 0; x < 224; x++) {
int px = bitmap.getPixel(x, y);
// Get channel values from the pixel value.
int r = Color.red(px);
int g = Color.green(px);
int b = Color.blue(px);
// Normalize channel values to [-1.0, 1.0]. This requirement depends
// on the model. For example, some models might require values to be
// normalized to the range [0.0, 1.0] instead.
float rf = (r - 127) / 255.0f;
float gf = (g - 127) / 255.0f;
float bf = (b - 127) / 255.0f;
input.putFloat(rf);
input.putFloat(gf);
input.putFloat(bf);
}
}
Kotlin + KTX
val bitmap = Bitmap.createScaledBitmap(yourInputImage, 224, 224, true)
val input = ByteBuffer.allocateDirect(224*224*3*4).order(ByteOrder.nativeOrder())
for (y in 0 until 224) {
for (x in 0 until 224) {
val px = bitmap.getPixel(x, y)
// Get channel values from the pixel value.
val r = Color.red(px)
val g = Color.green(px)
val b = Color.blue(px)
// Normalize channel values to [-1.0, 1.0]. This requirement depends on the model.
// For example, some models might require values to be normalized to the range
// [0.0, 1.0] instead.
val rf = (r - 127) / 255f
val gf = (g - 127) / 255f
val bf = (b - 127) / 255f
input.putFloat(rf)
input.putFloat(gf)
input.putFloat(bf)
}
}
Ardından, modelin çıktısını içerecek kadar büyük bir ByteBuffer
ayırın ve giriş arabelleğini ve çıktı arabelleğini TensorFlow Lite yorumlayıcısının run()
yöntemine iletin. Örneğin, [1 1000]
kayan nokta değerlerinin çıktı şekli için:
Java
int bufferSize = 1000 * java.lang.Float.SIZE / java.lang.Byte.SIZE;
ByteBuffer modelOutput = ByteBuffer.allocateDirect(bufferSize).order(ByteOrder.nativeOrder());
interpreter.run(input, modelOutput);
Kotlin + KTX
val bufferSize = 1000 * java.lang.Float.SIZE / java.lang.Byte.SIZE
val modelOutput = ByteBuffer.allocateDirect(bufferSize).order(ByteOrder.nativeOrder())
interpreter?.run(input, modelOutput)
Çıkışı nasıl kullanacağınız, kullandığınız modele bağlıdır.
Örneğin, bir sonraki adım olarak sınıflandırma yapıyorsanız, sonucun dizinlerini temsil ettikleri etiketlerle eşleyebilirsiniz:
Java
modelOutput.rewind();
FloatBuffer probabilities = modelOutput.asFloatBuffer();
try {
BufferedReader reader = new BufferedReader(
new InputStreamReader(getAssets().open("custom_labels.txt")));
for (int i = 0; i < probabilities.capacity(); i++) {
String label = reader.readLine();
float probability = probabilities.get(i);
Log.i(TAG, String.format("%s: %1.4f", label, probability));
}
} catch (IOException e) {
// File not found?
}
Kotlin + KTX
modelOutput.rewind()
val probabilities = modelOutput.asFloatBuffer()
try {
val reader = BufferedReader(
InputStreamReader(assets.open("custom_labels.txt")))
for (i in probabilities.capacity()) {
val label: String = reader.readLine()
val probability = probabilities.get(i)
println("$label: $probability")
}
} catch (e: IOException) {
// File not found?
}
Ek: Yerel olarak paketlenmiş bir modele geri dönün
Modelinizi Firebase ile barındırdığınızda, modelle ilgili herhangi bir işlev, uygulamanız modeli ilk kez indirene kadar kullanılamayacaktır. Bazı uygulamalar için bu iyi olabilir, ancak modeliniz temel işlevleri etkinleştirirse, modelinizin bir sürümünü uygulamanızla birlikte paketleyip mevcut en iyi sürümü kullanmak isteyebilirsiniz. Bunu yaparak, uygulamanızın ML özelliklerinin Firebase tarafından barındırılan model mevcut olmadığında çalışmasını sağlayabilirsiniz.
TensorFlow Lite modelinizi uygulamanızla paketlemek için:
Model dosyasını (genellikle
.tflite
veya.lite
biten) uygulamanızınassets/
klasörüne kopyalayın. (Önceapp/
klasörü sağ tıklayıp ardından Yeni> Klasör> Varlıklar Klasörü'nü tıklayarak klasörü oluşturmanız gerekebilir.)build.gradle
uygulamayı oluştururken modelleri sıkıştırmamasını sağlamak için uygulamanızınbuild.gradle
dosyasına aşağıdakileri ekleyin:android { // ... aaptOptions { noCompress "tflite", "lite" } }
Ardından, barındırılan model mevcut olmadığında yerel olarak paketlenmiş modeli kullanın:
Java
FirebaseCustomRemoteModel remoteModel =
new FirebaseCustomRemoteModel.Builder("your_model").build();
FirebaseModelManager.getInstance().getLatestModelFile(remoteModel)
.addOnCompleteListener(new OnCompleteListener<File>() {
@Override
public void onComplete(@NonNull Task<File> task) {
File modelFile = task.getResult();
if (modelFile != null) {
interpreter = new Interpreter(modelFile);
} else {
try {
InputStream inputStream = getAssets().open("your_fallback_model.tflite");
byte[] model = new byte[inputStream.available()];
inputStream.read(model);
ByteBuffer buffer = ByteBuffer.allocateDirect(model.length)
.order(ByteOrder.nativeOrder());
buffer.put(model);
interpreter = new Interpreter(buffer);
} catch (IOException e) {
// File not found?
}
}
}
});
Kotlin + KTX
val remoteModel = FirebaseCustomRemoteModel.Builder("your_model").build()
FirebaseModelManager.getInstance().getLatestModelFile(remoteModel)
.addOnCompleteListener { task ->
val modelFile = task.result
if (modelFile != null) {
interpreter = Interpreter(modelFile)
} else {
val model = assets.open("your_fallback_model.tflite").readBytes()
val buffer = ByteBuffer.allocateDirect(model.size).order(ByteOrder.nativeOrder())
buffer.put(model)
interpreter = Interpreter(buffer)
}
}
Ek: Model güvenliği
Firebase ML için TensorFlow Lite modellerinizi nasıl kullanılabilir hale getirdiğinizden bağımsız olarak Firebase ML, bunları yerel depolamada standart serileştirilmiş protobuf biçiminde depolar.
Teorik olarak bu, herkesin modelinizi kopyalayabileceği anlamına gelir. Bununla birlikte, pratikte, çoğu model o kadar uygulamaya özgüdür ve optimizasyonlarla karmaşık hale getirilir ki, risk, kodunuzu söküp yeniden kullanan rakiplerinkine benzer. Yine de, uygulamanızda özel bir model kullanmadan önce bu riskin farkında olmalısınız.
Android API düzey 21 (Lollipop) ve daha yeni sürümlerde model, otomatik yedeklemenin dışında bırakılan bir dizine indirilir.
Android API düzeyi 20 ve daha eski sürümlerde, model, uygulamaya özel dahili depolamada com.google.firebase.ml.custom.models
adlı bir dizine indirilir. BackupAgent
kullanarak dosya yedeklemeyi etkinleştirdiyseniz, bu dizini dışarıda bırakmayı seçebilirsiniz.