หากแอปใช้แบบกำหนดเอง 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 เพื่อใช้งาน
Swift
import FirebaseMLModelDownloader
import TensorFlowLite
1. ทำให้โมเดลใช้งานได้
ทำให้โมเดล TensorFlow ที่กำหนดเองใช้งานได้โดยใช้คอนโซล Firebase หรือ SDK ของ Python และ Node.js ของผู้ดูแลระบบ Firebase โปรดดู จัดการและทำให้โมเดลที่กำหนดเองใช้งานได้
หลังจากเพิ่มรูปแบบที่กำหนดเองลงในโปรเจ็กต์ Firebase แล้ว คุณสามารถอ้างอิง
ในแอปของคุณโดยใช้ชื่อที่คุณระบุ คุณสามารถติดตั้งใช้งานได้ตลอดเวลา
โมเดล TensorFlow Lite ใหม่และดาวน์โหลดโมเดลใหม่ไปยังผู้ใช้ อุปกรณ์โดย
กำลังโทรหา getModel()
(ดูด้านล่าง)
2. ดาวน์โหลดโมเดลลงในอุปกรณ์และเริ่มต้นอินเทอร์พรีเตอร์ของ TensorFlow Lite
หากต้องการใช้โมเดล TensorFlow Lite ในแอป ให้ใช้ Firebase ML SDK ก่อน เพื่อดาวน์โหลดโมเดลเวอร์ชันล่าสุดลงในอุปกรณ์หากต้องการเริ่มดาวน์โหลดโมเดล ให้เรียกเมธอด getModel()
ของโปรแกรมดาวน์โหลดโมเดล
ระบุชื่อที่คุณกำหนดให้กับโมเดลเมื่ออัปโหลด ไม่ว่าคุณจะ
ต้องการดาวน์โหลดรุ่นล่าสุดเสมอ และเงื่อนไขที่คุณ
ต้องการอนุญาตให้ดาวน์โหลด
คุณเลือกพฤติกรรมการดาวน์โหลดได้ 3 แบบดังนี้
ประเภทการดาวน์โหลด | คำอธิบาย |
---|---|
localModel
|
รับโมเดลในเครื่องจากอุปกรณ์
หากไม่มีโมเดลในเครื่อง
ลักษณะการทำงานเหมือน latestModel ใช้ร่างคำตอบนี้
ประเภทการดาวน์โหลดหากคุณไม่สนใจ
กำลังตรวจหาการอัปเดตโมเดล ตัวอย่างเช่น
คุณกำลังใช้การกำหนดค่าระยะไกลเพื่อดึงข้อมูล
ชื่อโมเดลและคุณจะอัปโหลดโมเดลเสมอ
ภายใต้ชื่อใหม่ (แนะนำ) |
localModelUpdateInBackground
|
รับโมเดลในเครื่องจากอุปกรณ์และ
เริ่มอัปเดตโมเดลในเบื้องหลัง
หากไม่มีโมเดลในเครื่อง
ลักษณะการทำงานเหมือน latestModel |
latestModel
|
ดาวน์โหลดรุ่นล่าสุด หากโมเดลในเครื่องคือ เวอร์ชันล่าสุด จะแสดงผลลัพธ์เป็น โมเดล หรือไม่เช่นนั้น ให้ดาวน์โหลดแอปล่าสุด โมเดล ระบบจะบล็อกลักษณะการทำงานนี้จนกว่า มีการดาวน์โหลดเวอร์ชันล่าสุด (ไม่ใช่ แนะนำ) ใช้ลักษณะการทำงานนี้ใน ในกรณีที่คุณต้องการข้อมูลล่าสุด เวอร์ชัน |
คุณควรปิดใช้ฟังก์ชันการทำงานที่เกี่ยวข้องกับโมเดล เช่น เป็นสีเทาหรือ ซ่อนบางส่วนของ UI จนกว่าคุณจะยืนยันว่าดาวน์โหลดโมเดลแล้ว
Swift
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 เพื่อตรวจสอบโมเดล เช่น
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]
ค่า คุณอาจต้องปรับขนาด
ค่าสีของรูปภาพเป็นช่วงจุดลอยตัวในตัวอย่างต่อไปนี้
Swift
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
ไปยังล่ามแล้วเรียกใช้ดังนี้
Swift
try interpreter.allocateTensors()
try interpreter.copy(inputData, toInputAt: 0)
try interpreter.invoke()
คุณรับเอาต์พุตของโมเดลได้โดยเรียกใช้เมธอด output(at:)
ของล่าม
วิธีที่คุณใช้เอาต์พุตจะขึ้นอยู่กับโมเดลที่คุณใช้
ตัวอย่างเช่น ถ้าคุณกำลังแยกประเภท ในขั้นตอนถัดไป คุณอาจ แมปดัชนีของผลลัพธ์กับป้ายกำกับที่แสดง:
Swift
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 จัดเก็บไว้ในรูปแบบ Protocol Buf มาตรฐานแบบอนุกรมใน ที่จัดเก็บข้อมูลในตัวเครื่อง
ในทางทฤษฎี หมายความว่าทุกคนสามารถคัดลอกโมเดลของคุณได้ อย่างไรก็ตาม ในทางปฏิบัติ โมเดลส่วนใหญ่จะมีความเฉพาะเจาะจงกับแอปพลิเคชันโดยเฉพาะและทำให้ยากต่อการอ่าน (Obfuscate) ด้วย การเพิ่มประสิทธิภาพที่มีความเสี่ยงคล้ายกับการถอดแยกชิ้นส่วนของคู่แข่งและ การนำโค้ดของคุณมาใช้ซ้ำ อย่างไรก็ตาม คุณควรตระหนักถึงความเสี่ยงนี้ก่อนที่จะใช้ โมเดลที่กำหนดเองในแอปของคุณ