إذا كان تطبيقك يستخدم نماذج TensorFlow Lite المخصّصة، يمكنك استخدام تعلُّم الآلة في Firebase لنشر نماذجك. ومن خلال نشر النماذج من خلال Firebase، يمكنك تقليل حجم التنزيل الأولي لتطبيقك وتحديث نماذج تعلُّم الآلة الخاصة بتطبيقك بدون طرح إصدار جديد من تطبيقك. وباستخدام "الإعداد عن بُعد" و"اختبار A/B"، يمكنك عرض نماذج مختلفة ديناميكيًا لمجموعات مختلفة من المستخدمين.
طُرز TensorFlow Lite
نماذج TensorFlow Lite هي نماذج تعلُّم الآلة تم تحسينها لتعمل على الأجهزة الجوّالة. للحصول على نموذج TensorFlow Lite، اتّبِع الخطوات التالية:
- استخدِم نموذجًا مصمَّمًا مسبقًا، مثل أحد طُرز TensorFlow Lite الرسمية.
- حوِّل نموذج TensorFlow أو نموذج Keras أو دالة الخرسانة إلى TensorFlow Lite.
قبل البدء
- أضِف Firebase إلى مشروع Android إذا لم يسبق لك إجراء ذلك.
-
في ملف Gradle للوحدة (على مستوى التطبيق)
(عادةً
<project>/<app-module>/build.gradle.kts
أو<project>/<app-module>/build.gradle
)، أضِف الاعتمادية لمكتبة أدوات تنزيل نماذج تعلُّم الآلة من Firebase لنظام التشغيل Android. ننصح باستخدام بنود سياسة Android في Firebase للتحكّم في نُسَخ المكتبة.بالإضافة إلى ذلك، وكجزء من عملية إعداد أداة تنزيل نموذج تعلُّم الآلة من Firebase، يجب إضافة حزمة تطوير البرامج (SDK) TensorFlow Lite إلى تطبيقك.
dependencies { // Import the BoM for the Firebase platform implementation(platform("com.google.firebase:firebase-bom:33.1.1")) // Add the dependency for the Firebase ML model downloader library // When using the BoM, you don't specify versions in Firebase library dependencies implementation("com.google.firebase:firebase-ml-modeldownloader")
// Also add the dependency for the TensorFlow Lite library and specify its version implementation("org.tensorflow:tensorflow-lite:2.3.0") }باستخدام أداة إدارة قوائم التشغيل Android في Firebase، سيستخدم تطبيقك دائمًا الإصدارات المتوافقة من مكتبات Android في Firebase.
(بديل) إضافة ملحقات مكتبة Firebase بدون استخدام BoM
إذا اخترت عدم استخدام قائمة العناصر في Firebase، يجب تحديد كل إصدار من مكتبة Firebase في سطر الاعتمادية الخاص به.
يُرجى العِلم أنّه إذا كنت تستخدم مكتبات متعددة لمنصة Firebase في تطبيقك، ننصحك بشدّة باستخدام BoM لإدارة إصدارات المكتبة، ما يضمن توافق جميع الإصدارات.
dependencies { // Add the dependency for the Firebase ML model downloader library // When NOT using the BoM, you must specify versions in Firebase library dependencies implementation("com.google.firebase:firebase-ml-modeldownloader:25.0.0")
// Also add the dependency for the TensorFlow Lite library and specify its version implementation("org.tensorflow:tensorflow-lite:2.3.0") } - يُرجى توضيح أنّ إذن INTERNET مطلوب في بيان تطبيقك:
<uses-permission android:name="android.permission.INTERNET" />
1- نشر النموذج
انشر نماذج TensorFlow المخصّصة باستخدام وحدة تحكُّم Firebase أو حِزم تطوير البرامج (SDK) للمشرفين في Firebase وNode.js. يمكنك الاطّلاع على نشر النماذج المخصَّصة وإدارتها.
بعد إضافة نموذج مخصّص إلى مشروعك على Firebase، يمكنك الإشارة إلى النموذج في تطبيقاتك باستخدام الاسم الذي حدّدته. يمكنك في أي وقت تفعيل نموذج TensorFlow Lite الجديد وتنزيل النموذج الجديد على أجهزة المستخدمين من خلال الاتصال بالرقم getModel()
(انظر أدناه).
2- تنزيل النموذج على الجهاز وإعداد أداة الترجمة الفورية من TensorFlow Lite
لاستخدام نموذج TensorFlow Lite في تطبيقك، استخدِم أولاً حزمة تطوير البرامج (SDK) لتعلُّم الآلة في Firebase لتنزيل أحدث إصدار من النموذج على الجهاز. بعد ذلك، أنشئ مثيلاً للمترجم TensorFlow Lite باستخدام النموذج.لبدء تنزيل النموذج، استدعِ الطريقة getModel()
لأداة تنزيل النموذج، مع تحديد الاسم الذي حدّدته للنموذج عند تحميله، وما إذا كنت تريد تنزيل أحدث نموذج دائمًا، والشروط التي تريد السماح بالتنزيل بموجبها.
يمكنك الاختيار من بين ثلاثة سلوكيات للتنزيل:
نوع عملية التنزيل | الوصف |
---|---|
النموذج المحلي | الحصول على الطراز المحلي من الجهاز
إذا لم يتوفر نموذج محلي، سيتبع ذلك
مثل LATEST_MODEL . استخدِم
نوع التنزيل هذا إذا لم تكن مهتمًا
بالبحث عن تحديثات النماذج. على سبيل المثال، إذا كنت تستخدم ميزة "الإعداد عن بُعد" لاسترداد
أسماء النماذج، يتم دائمًا تحميل نماذج
بأسماء جديدة (إجراء يُنصح به). |
LOCAL_MODEL_UPDATE_IN_BACKGROUND | احصل على الطراز المحلي من الجهاز
وابدأ في تحديث الطراز في الخلفية.
إذا لم يتوفر نموذج محلي، سيتبع ذلك
مثل LATEST_MODEL . |
LATEST_MODEL | احصل على أحدث طراز. إذا كان النموذج المحلي هو أحدث إصدار، يتم عرض النموذج المحلي. أو قم بتنزيل أحدث إصدار. سيتم حظر هذا السلوك إلى أن يتم تنزيل أحدث إصدار (لا يُنصح به). لا تستخدم هذا السلوك إلا في الحالات التي تحتاج فيها صراحةً إلى أحدث إصدار. |
يجب إيقاف الوظائف المتعلّقة بالنموذج، على سبيل المثال، الظهور باللون الرمادي أو إخفاء جزء من واجهة المستخدم إلى أن تتأكد من تنزيل النموذج.
Kotlin+KTX
val conditions = CustomModelDownloadConditions.Builder()
.requireWifi() // Also possible: .requireCharging() and .requireDeviceIdle()
.build()
FirebaseModelDownloader.getInstance()
.getModel("your_model", DownloadType.LOCAL_MODEL_UPDATE_IN_BACKGROUND,
conditions)
.addOnSuccessListener { model: CustomModel? ->
// Download complete. Depending on your app, you could enable the ML
// feature, or switch from the local model to the remote model, etc.
// The CustomModel object contains the local path of the model file,
// which you can use to instantiate a TensorFlow Lite interpreter.
val modelFile = model?.file
if (modelFile != null) {
interpreter = Interpreter(modelFile)
}
}
Java
CustomModelDownloadConditions conditions = new CustomModelDownloadConditions.Builder()
.requireWifi() // Also possible: .requireCharging() and .requireDeviceIdle()
.build();
FirebaseModelDownloader.getInstance()
.getModel("your_model", DownloadType.LOCAL_MODEL_UPDATE_IN_BACKGROUND, conditions)
.addOnSuccessListener(new OnSuccessListener<CustomModel>() {
@Override
public void onSuccess(CustomModel model) {
// Download complete. Depending on your app, you could enable the ML
// feature, or switch from the local model to the remote model, etc.
// The CustomModel object contains the local path of the model file,
// which you can use to instantiate a TensorFlow Lite interpreter.
File modelFile = model.getFile();
if (modelFile != null) {
interpreter = new Interpreter(modelFile);
}
}
});
تبدأ العديد من التطبيقات مهمة التنزيل في رمز الإعداد الخاص بها، ولكن يمكنك إجراء ذلك في أي وقت قبل أن تحتاج إلى استخدام النموذج.
3- إجراء استنتاج على بيانات الإدخال
الحصول على أشكال المدخلات والمخرجات لنموذجك
يتعامل مترجم النموذج TensorFlow Lite كمدخلات ويتم إنتاجه كإخراج مصفوفة واحدة أو أكثر متعددة الأبعاد. تحتوي هذه المصفوفات على قيمة إما byte
أو int
أو long
أو float
. لكي تتمكّن من تمرير البيانات إلى نموذج أو استخدام نتيجته، يجب أن تعرف عدد المصفوفات التي يستخدمها نموذجك وأبعادها ("شكل") المصفوفات.
إذا كنت قد صمّمت النموذج بنفسك، أو إذا تم توثيق تنسيق الإدخال والمخرجات الخاصة بالنموذج، قد تكون لديك هذه المعلومات. إذا كنت لا تعرف شكل ونوع البيانات التي تُدخلها ومخرجات النموذج، يمكنك استخدام أداة الترجمة الفورية TensorFlow Lite لفحص النموذج. على سبيل المثال:
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']))
مثال على الإخراج:
1 input(s): [ 1 224 224 3] <class 'numpy.float32'> 1 output(s): [1 1000] <class 'numpy.float32'>
تشغيل ميزة "الترجمة الفورية"
بعد تحديد تنسيق مدخلات ومخرجات النموذج، احصل على بيانات المدخلات وأجرِ أي عمليات تحويل على البيانات الضرورية للحصول على مدخل بالشكل المناسب لنموذجك.على سبيل المثال، إذا كان لديك نموذج تصنيف صور به شكل إدخال [1 224 224 3]
من قيم النقطة العائمة، يمكنك إنشاء إدخال ByteBuffer
من كائن Bitmap
كما هو موضّح في المثال التالي:
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)
}
}
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);
}
}
بعد ذلك، خصِّص ByteBuffer
كبيرة بما يكفي لاحتواء مخرجات النموذج، ثم مرِّر المخزن المؤقت للإدخال والمخزن المؤقت للمخرجات إلى طريقة run()
الخاصة ببرنامج الترجمة TensorFlow Lite. على سبيل المثال، بالنسبة إلى شكل إخراج [1 1000]
لقيم النقطة العائمة:
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)
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
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?
}
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?
}
الملحق: أمان النموذج
بغض النظر عن كيفية إتاحة نماذج TensorFlow Lite لتعلُّم الآلة من Firebase، يخزّنها تعلُّم الآلة في Firebase بتنسيق النموذج الأوّلي المتسلسل العادي في مساحة التخزين المحلية.
ومن الناحية النظرية، يعني هذا أنه بإمكان أي شخص نسخ نموذجك. ومع ذلك، من الناحية العملية، تكون معظم النماذج خاصة بالتطبيق وتمّ تشويشها من خلال التحسينات، بحيث تكون المخاطر مماثلة لمخاطر قيام المنافسين بتفكيك الرمز البرمجي وإعادة استخدامه. ومع ذلك، يجب أن تكون على دراية بهذا الخطر قبل استخدام نموذج مخصّص في تطبيقك.
في المستوى 21 من واجهة برمجة تطبيقات Android (Lollipop) والإصدارات الأحدث، يتم تنزيل النموذج إلى دليل تم استبعاده من ميزة الاحتفاظ التلقائي بنسخة احتياطية.
في المستوى 20 من واجهة برمجة تطبيقات Android والإصدارات الأقدم، يتم تنزيل النموذج إلى دليل
باسم com.google.firebase.ml.custom.models
في وحدة التخزين الداخلية الخاصة بالتطبيق. إذا فعّلت الاحتفاظ بنسخة احتياطية من الملفات باستخدام BackupAgent
،
يمكنك اختيار استبعاد هذا الدليل.