إذا كان تطبيقك يستخدم نماذج TensorFlow Lite المخصصة ، فيمكنك استخدام Firebase ML لنشر نماذجك. من خلال نشر النماذج باستخدام Firebase ، يمكنك تقليل حجم التنزيل الأولي لتطبيقك وتحديث نماذج ML الخاصة بتطبيقك دون إصدار إصدار جديد من تطبيقك. وباستخدام Remote Config و A / B Testing ، يمكنك تقديم نماذج مختلفة بشكل ديناميكي لمجموعات مختلفة من المستخدمين.
المتطلبات الأساسية
- مكتبة
MLModelDownloader
متاحة فقط لـ Swift. - يعمل TensorFlow Lite فقط على الأجهزة التي تعمل بنظام iOS 9 والإصدارات الأحدث.
نماذج TensorFlow Lite
نماذج TensorFlow Lite هي نماذج ML تم تحسينها للتشغيل على الأجهزة المحمولة. للحصول على نموذج TensorFlow Lite:
- استخدم نموذجًا تم إنشاؤه مسبقًا ، مثل أحد نماذج TensorFlow Lite الرسمية .
- قم بتحويل نموذج TensorFlow أو نموذج Keras أو دالة ملموسة إلى TensorFlow Lite.
قبل ان تبدأ
لاستخدام TensorFlowLite مع Firebase ، يجب عليك استخدام CocoaPods نظرًا لأن TensorFlowLite لا يدعم حاليًا التثبيت مع Swift Package Manager. راجع دليل تثبيت CocoaPods للحصول على إرشادات حول كيفية تثبيت MLModelDownloader
.
بمجرد التثبيت ، قم باستيراد Firebase و TensorFlowLite لاستخدامهما.
سويفت
import FirebaseMLModelDownloader
import TensorFlowLite
1. نشر النموذج الخاص بك
انشر نماذج TensorFlow المخصصة باستخدام إما وحدة تحكم Firebase أو Firebase Admin Python و Node.js SDK. راجع نشر النماذج المخصصة وإدارتها .
بعد إضافة نموذج مخصص إلى مشروع Firebase ، يمكنك الرجوع إلى النموذج في تطبيقاتك باستخدام الاسم الذي حددته. في أي وقت ، يمكنك نشر نموذج TensorFlow Lite جديد وتنزيل النموذج الجديد على أجهزة المستخدمين عن طريق استدعاء getModel()
(انظر أدناه).
2. قم بتنزيل النموذج على الجهاز وتهيئة مترجم TensorFlow Lite
لاستخدام نموذج TensorFlow Lite في تطبيقك ، استخدم أولاً Firebase ML SDK لتنزيل أحدث إصدار من النموذج على الجهاز. لبدء تنزيل النموذج ، اتصل getModel()
تنزيل النموذج ، مع تحديد الاسم الذي قمت بتعيينه للنموذج عند تحميله ، وما إذا كنت تريد دائمًا تنزيل أحدث طراز ، والشروط التي تريد بموجبها السماح بالتنزيل.
يمكنك الاختيار من بين ثلاثة سلوكيات للتنزيل:
نوع التنزيل | وصف |
---|---|
localModel | احصل على النموذج المحلي من الجهاز. إذا لم يكن هناك نموذج محلي متاح ، فهذا يتصرف مثل latestModel . استخدم نوع التنزيل هذا إذا لم تكن مهتمًا بالتحقق من تحديثات الطراز. على سبيل المثال ، أنت تستخدم Remote Config لاسترداد أسماء النماذج ودائمًا ما تقوم بتحميل النماذج بأسماء جديدة (مستحسن). |
localModelUpdateInBackground | احصل على النموذج المحلي من الجهاز وابدأ في تحديث النموذج في الخلفية. إذا لم يكن هناك نموذج محلي متاح ، فهذا يتصرف مثل latestModel . |
latestModel | احصل على أحدث طراز. إذا كان النموذج المحلي هو أحدث إصدار ، يتم إرجاع النموذج المحلي. خلاف ذلك ، قم بتنزيل أحدث طراز. سيتم حظر هذا السلوك حتى يتم تنزيل أحدث إصدار (غير مستحسن). استخدم هذا السلوك فقط في الحالات التي تحتاج فيها صراحة إلى أحدث إصدار. |
يجب عليك تعطيل الوظائف المتعلقة بالنموذج - على سبيل المثال ، اللون الرمادي أو إخفاء جزء من واجهة المستخدم الخاصة بك - حتى تؤكد تنزيل النموذج.
سويفت
let conditions = ModelDownloadConditions(allowsCellularAccess: false)
ModelDownloader.modelDownloader()
.getModel(name: "your_model",
downloadType: .localModelUpdateInBackground,
conditions: conditions) { result in
switch (result) {
case .success(let customModel):
do {
// 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.
let interpreter = try Interpreter(modelPath: customModel.path)
} catch {
// Error. Bad model file?
}
case .failure(let error):
// Download was unsuccessful. Don't enable ML features.
print(error)
}
}
تبدأ العديد من التطبيقات مهمة التنزيل في كود التهيئة الخاص بها ، ولكن يمكنك القيام بذلك في أي وقت قبل أن تحتاج إلى استخدام النموذج.
3. إجراء الاستدلال على بيانات الإدخال
احصل على أشكال الإدخال والإخراج الخاصة بنموذجك
يأخذ مترجم نموذج TensorFlow Lite كمدخلات وينتج كإخراج مصفوفة واحدة أو أكثر من المصفوفات متعددة الأبعاد. تحتوي هذه المصفوفات على قيم byte
أو int
أو long
أو قيم float
. قبل أن تتمكن من تمرير البيانات إلى نموذج أو استخدام نتائجه ، يجب أن تعرف عدد المصفوفات التي يستخدمها النموذج وأبعادها ("الشكل").
إذا قمت ببناء النموذج بنفسك ، أو إذا تم توثيق تنسيق الإدخال والإخراج الخاص بالنموذج ، فقد تكون لديك هذه المعلومات بالفعل. إذا كنت لا تعرف شكل ونوع البيانات لإدخال وإخراج النموذج الخاص بك ، يمكنك استخدام مترجم TensorFlow Lite لفحص النموذج الخاص بك. فمثلا:
بايثون
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]
قيم الفاصلة العائمة ، فقد تضطر إلى قياس قيم لون الصورة إلى نطاق فاصلة عائمة كما في المثال التالي :
سويفت
let image: CGImage = // Your input image
guard let context = CGContext(
data: nil,
width: image.width, height: image.height,
bitsPerComponent: 8, bytesPerRow: image.width * 4,
space: CGColorSpaceCreateDeviceRGB(),
bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue
) else {
return false
}
context.draw(image, in: CGRect(x: 0, y: 0, width: image.width, height: image.height))
guard let imageData = context.data else { return false }
var inputData = Data()
for row in 0 ..< 224 {
for col in 0 ..< 224 {
let offset = 4 * (row * context.width + col)
// (Ignore offset 0, the unused alpha channel)
let red = imageData.load(fromByteOffset: offset+1, as: UInt8.self)
let green = imageData.load(fromByteOffset: offset+2, as: UInt8.self)
let blue = imageData.load(fromByteOffset: offset+3, as: UInt8.self)
// Normalize channel values to [0.0, 1.0]. This requirement varies
// by model. For example, some models might require values to be
// normalized to the range [-1.0, 1.0] instead, and others might
// require fixed-point values or the original bytes.
var normalizedRed = Float32(red) / 255.0
var normalizedGreen = Float32(green) / 255.0
var normalizedBlue = Float32(blue) / 255.0
// Append normalized values to Data object in RGB order.
let elementSize = MemoryLayout.size(ofValue: normalizedRed)
var bytes = [UInt8](repeating: 0, count: elementSize)
memcpy(&bytes, &normalizedRed, elementSize)
inputData.append(&bytes, count: elementSize)
memcpy(&bytes, &normalizedGreen, elementSize)
inputData.append(&bytes, count: elementSize)
memcpy(&ammp;bytes, &normalizedBlue, elementSize)
inputData.append(&bytes, count: elementSize)
}
}
ثم انسخ NSData
إلى المترجم وقم بتشغيلها:
سويفت
try interpreter.allocateTensors()
try interpreter.copy(inputData, toInputAt: 0)
try interpreter.invoke()
يمكنك الحصول على ناتج النموذج عن طريق استدعاء output(at:)
. تعتمد طريقة استخدامك للإخراج على النموذج الذي تستخدمه.
على سبيل المثال ، إذا كنت تقوم بالتصنيف ، كخطوة تالية ، يمكنك تعيين فهارس النتيجة إلى التسميات التي تمثلها:
سويفت
let output = try interpreter.output(at: 0)
let probabilities =
UnsafeMutableBufferPointer<Float32>.allocate(capacity: 1000)
output.data.copyBytes(to: probabilities)
guard let labelPath = Bundle.main.path(forResource: "retrained_labels", ofType: "txt") else { return }
let fileContents = try? String(contentsOfFile: labelPath)
guard let labels = fileContents?.components(separatedBy: "\n") else { return }
for i in labels.indices {
print("\(labels[i]): \(probabilities[i])")
}
الملحق: نموذج الأمن
بغض النظر عن كيفية إتاحة نماذج TensorFlow Lite الخاصة بك لـ Firebase ML ، يقوم Firebase ML بتخزينها بتنسيق protobuf القياسي المتسلسل في التخزين المحلي.
من الناحية النظرية ، هذا يعني أنه يمكن لأي شخص نسخ نموذجك. ومع ذلك ، من الناحية العملية ، تكون معظم النماذج خاصة بالتطبيق ومبهمة من خلال التحسينات بحيث تكون المخاطر مماثلة لتلك الخاصة بالمنافسين الذين يقومون بتفكيك التعليمات البرمجية الخاصة بك وإعادة استخدامها. ومع ذلك ، يجب أن تكون على دراية بهذه المخاطر قبل استخدام نموذج مخصص في تطبيقك.