Android Kit'i kullanarak cihaz üzerinde çıkarım yapmak için TensorFlow Lite modeli.
ML Kit, TensorFlow Lite modellerini yalnızca iOS 9 ve sonraki sürümleri çalıştıran cihazlarda kullanabilir daha yeni.
Başlamadan önce
- Firebase'i uygulamanıza henüz eklemediyseniz başlangıç kılavuzundaki adımlara bakın.
- ML Kit kitaplıklarını Podfile'ınıza ekleyin:
pod 'Firebase/MLModelInterpreter', '6.25.0'
. Projenizin kapsüllerini yükledikten veya güncelledikten sonra Xcode.xcworkspace
kullanarak projenize dahil olabilir. - Uygulamanızda Firebase'i içe aktarın:
Swift
import Firebase
Objective-C
@import Firebase;
- Kullanmak istediğiniz TensorFlow modelini TensorFlow Lite biçimine dönüştürün. Görüntüleyin TOCO: TensorFlow Lite Dönüşüm Optimize Edici.
Modelinizi barındırın veya paketleyin
Uygulamanızda çıkarım için TensorFlow Lite modelini kullanmadan önce modeli ML Kit'te kullanılabilir hale getirmelidir. ML Kit, TensorFlow Lite'ı kullanabilir Firebase kullanılarak uzaktan barındırılan, uygulama ikili programıyla paket halinde sunulan veya her iki model de kullanılabilir.
Firebase'de bir model barındırarak bir model yayınlamadan güncelleyebilirsiniz. ve Remote Config ve A/B Testing özelliklerini kullanarak Farklı kullanıcı gruplarına dinamik olarak farklı modeller sunar.
Modeli Firebase'de barındırarak değil, yalnızca Firebase'de barındırarak sağlamayı seçerseniz uygulamanızla birlikte paket haline getirirseniz uygulamanızın başlangıçtaki indirme boyutunu küçültebilirsiniz. Bununla birlikte, modelin uygulamanızla birlikte pakette olmadığı durumlarda, uygulamanız, uygulamanızı indirene kadar modelle ilgili işlevleri ilk kez devreye giriyor.
Modelinizi uygulamanızla paket haline getirerek uygulamanızın makine öğrenimi özelliklerinin etkin olmasını sağlayabilirsiniz. Firebase tarafından barındırılan model kullanılamadığında çalışmaya devam eder.
Firebase'de modelleri barındırma
TensorFlow Lite modelinizi Firebase'de barındırmak için:
- Firebase konsolunun Makine Öğrenimi Kiti bölümünde Özel sekmesi.
- Özel model ekle (veya Başka bir model ekle) seçeneğini tıklayın.
- Firebase'inizde modelinizi tanımlamak için kullanılacak bir ad belirtin
açın, ardından TensorFlow Lite model dosyasını yükleyin (genellikle
.tflite
veya.lite
).
Firebase projenize özel model ekledikten sonra, modeliniz olmalıdır. İstediğiniz zaman yeni bir TensorFlow Lite modelini çıkarırsanız uygulamanız yeni modeli indirir ve Uygulama yeniden başlatıldığında bunu kullanmaya başlayabilirsiniz. Cihazı tanımlayabilirsiniz. uygulamanızın modeli güncellemeyi denemesi için gereken koşullar (aşağıya bakın).
Modelleri uygulama ile paketleme
TensorFlow Lite modelinizi uygulamanızla paketlemek için model dosyasını (genellikle
.tflite
veya .lite
ile biten) Xcode projenize ekleyebilirsiniz.
Bunu yaparken paket kaynaklarını kopyalayın. Model dosyası
uygulama paketinden ve ML Kit'te kullanılabilir.
Modeli yükleme
TensorFlow Lite modelinizi uygulamanızda kullanmak için öncelikle ML Kit'i modelinizin mevcut olduğu konumlar: Firebase'i uzaktan kullanma, ya da her ikisi birden olabilir. Hem yerel hem de uzak model belirtirseniz aşağıdakileri yapabilirsiniz: varsa uzak modeli kullanın ve yerel olarak depolanan modelle ilişkilidir.
Firebase tarafından barındırılan bir modeli yapılandırma
Modelinizi Firebase ile barındırdıysanız bir CustomRemoteModel
nesnesi oluşturun.
modeli yayınlarken atadığınız adı belirtin:
Swift
let remoteModel = CustomRemoteModel(
name: "your_remote_model" // The name you assigned in the Firebase console.
)
Objective-C
// Initialize using the name you assigned in the Firebase console.
FIRCustomRemoteModel *remoteModel =
[[FIRCustomRemoteModel alloc] initWithName:@"your_remote_model"];
Ardından, model indirme görevinizi başlatın ve çalıştırmayı istediğiniz koşulları indirmeye izin vermek istiyorsunuz. Model cihazda yoksa veya sürümü kullanılabiliyorsa görev, yeni bir sürümün yüklü olduğu modeliniz:
Swift
let downloadConditions = ModelDownloadConditions(
allowsCellularAccess: true,
allowsBackgroundDownloading: true
)
let downloadProgress = ModelManager.modelManager().download(
remoteModel,
conditions: downloadConditions
)
Objective-C
FIRModelDownloadConditions *downloadConditions =
[[FIRModelDownloadConditions alloc] initWithAllowsCellularAccess:YES
allowsBackgroundDownloading:YES];
NSProgress *downloadProgress =
[[FIRModelManager modelManager] downloadRemoteModel:remoteModel
conditions:downloadConditions];
Birçok uygulama, indirme görevini başlatma kodunda başlatır ancak bu nedenle, herhangi bir noktada modeli kullanabilirsiniz.
Yerel model yapılandırma
Modeli uygulamanızla paketlediyseniz bir CustomLocalModel
nesnesi oluşturun,
TensorFlow Lite modelinin dosya adını belirtin:
Swift
guard let modelPath = Bundle.main.path(
forResource: "your_model",
ofType: "tflite",
inDirectory: "your_model_directory"
) else { /* Handle error. */ }
let localModel = CustomLocalModel(modelPath: modelPath)
Objective-C
NSString *modelPath = [NSBundle.mainBundle pathForResource:@"your_model"
ofType:@"tflite"
inDirectory:@"your_model_directory"];
FIRCustomLocalModel *localModel =
[[FIRCustomLocalModel alloc] initWithModelPath:modelPath];
Modelinizden çevirmen oluşturma
Model kaynaklarınızı yapılandırdıktan sonra
ModelInterpreter
bir nesne çıkarmayı deneyin.
Yalnızca yerel olarak paketlenmiş bir modeliniz varsa CustomLocalModel
öğesini iletmeniz yeterlidir
nesnesini (modelInterpreter(localModel:)
) çağırın:
Swift
let interpreter = ModelInterpreter.modelInterpreter(localModel: localModel)
Objective-C
FIRModelInterpreter *interpreter =
[FIRModelInterpreter modelInterpreterForLocalModel:localModel];
Uzaktan barındırılan bir modeliniz varsa bu modelin
indiremezsiniz. Model indirme işleminin durumunu kontrol edebilirsiniz.
model yöneticisinin isModelDownloaded(remoteModel:)
yöntemini kullanarak görevi tamamlayın.
Çevirmeni çalıştırmadan önce bunu onaylamanız gerekse de
hem uzaktan barındırılan hem de yerel olarak paketlenen
ModelInterpreter
örneğini örneklendirirken şu kontrolü gerçekleştirmek mantıklıdır:
yerel modelden ve yerel makine öğreniminden
modelini kullanmanız gerekir.
Swift
var interpreter: ModelInterpreter
if ModelManager.modelManager().isModelDownloaded(remoteModel) {
interpreter = ModelInterpreter.modelInterpreter(remoteModel: remoteModel)
} else {
interpreter = ModelInterpreter.modelInterpreter(localModel: localModel)
}
Objective-C
FIRModelInterpreter *interpreter;
if ([[FIRModelManager modelManager] isModelDownloaded:remoteModel]) {
interpreter = [FIRModelInterpreter modelInterpreterForRemoteModel:remoteModel];
} else {
interpreter = [FIRModelInterpreter modelInterpreterForLocalModel:localModel];
}
Yalnızca uzaktan barındırılan bir modeliniz varsa modelle ilgili ayarını devre dışı bırakmanız gerekir. (örneğin, kullanıcı arayüzünüzün bir kısmını devre dışı bırakan veya gizleyen) modelin indirildiğini onaylayın.
Varsayılana gözlemleyiciler ekleyerek model indirme durumunu öğrenebilirsiniz.
Bildirim Merkezi. Gözlemcide self
için zayıf bir referans kullandığınızdan emin olun
biraz zaman alabilir ve kaynak nesne
indirme tamamlandığında serbest bırakılır. Örneğin:
Swift
NotificationCenter.default.addObserver( forName: .firebaseMLModelDownloadDidSucceed, object: nil, queue: nil ) { [weak self] notification in guard let strongSelf = self, let userInfo = notification.userInfo, let model = userInfo[ModelDownloadUserInfoKey.remoteModel.rawValue] as? RemoteModel, model.name == "your_remote_model" else { return } // The model was downloaded and is available on the device } NotificationCenter.default.addObserver( forName: .firebaseMLModelDownloadDidFail, object: nil, queue: nil ) { [weak self] notification in guard let strongSelf = self, let userInfo = notification.userInfo, let model = userInfo[ModelDownloadUserInfoKey.remoteModel.rawValue] as? RemoteModel else { return } let error = userInfo[ModelDownloadUserInfoKey.error.rawValue] // ... }
Objective-C
__weak typeof(self) weakSelf = self; [NSNotificationCenter.defaultCenter addObserverForName:FIRModelDownloadDidSucceedNotification object:nil queue:nil usingBlock:^(NSNotification *_Nonnull note) { if (weakSelf == nil | note.userInfo == nil) { return; } __strong typeof(self) strongSelf = weakSelf; FIRRemoteModel *model = note.userInfo[FIRModelDownloadUserInfoKeyRemoteModel]; if ([model.name isEqualToString:@"your_remote_model"]) { // The model was downloaded and is available on the device } }]; [NSNotificationCenter.defaultCenter addObserverForName:FIRModelDownloadDidFailNotification object:nil queue:nil usingBlock:^(NSNotification *_Nonnull note) { if (weakSelf == nil | note.userInfo == nil) { return; } __strong typeof(self) strongSelf = weakSelf; NSError *error = note.userInfo[FIRModelDownloadUserInfoKeyError]; }];
Modelin giriş ve çıkışını belirtin
Ardından, model yorumlayıcının giriş ve çıkış biçimlerini yapılandırın.
TensorFlow Lite modeli girdi olarak alır ve bir veya daha fazla çıkış olarak üretir
çok boyutlu diziler. Bu diziler byte
,
int
, long
veya float
değerleri. Şunu yapmalısınız:
ML Kit'ini, kullandığınız dizilerin sayısı ve boyutlarıyla ("şekli")
en iyi uygulamalardan bahsedeceğiz.
Modelinizin giriş ve çıkışının şeklini ve veri türünü bilmiyorsanız modelinizi incelemek için TensorFlow Lite Python yorumlayıcısını kullanabilirsiniz. Örneğin:
import tensorflow as tf interpreter = tf.lite.Interpreter(model_path="my_model.tflite") interpreter.allocate_tensors() # Print input shape and type print(interpreter.get_input_details()[0]['shape']) # Example: [1 224 224 3] print(interpreter.get_input_details()[0]['dtype']) # Example: <class 'numpy.float32'> # Print output shape and type print(interpreter.get_output_details()[0]['shape']) # Example: [1 1000] print(interpreter.get_output_details()[0]['dtype']) # Example: <class 'numpy.float32'>
Modelinizin giriş ve çıkışının biçimini belirledikten sonra
uygulamanızın model çevirmeni için
ModelInputOutputOptions
nesnesini tanımlayın.
Örneğin, kayan noktalı görüntü sınıflandırma modeli için
NBir grubu temsil eden Float
değerlerinden oluşan x224x224x3 dizisi
N 224x224 üç kanallı (RGB) resimler ve aşağıdakilerin bir listesi olarak üretilebilir:
Her biri resmin üyesi olma olasılığını temsil eden 1.000 Float
değeri
kategoriden birini seçmeniz gerekir.
Böyle bir model için model çevirmeninin giriş ve çıkışını yapılandırırsınız. aşağıdaki gibidir:
Swift
let ioOptions = ModelInputOutputOptions() do { try ioOptions.setInputFormat(index: 0, type: .float32, dimensions: [1, 224, 224, 3]) try ioOptions.setOutputFormat(index: 0, type: .float32, dimensions: [1, 1000]) } catch let error as NSError { print("Failed to set input or output format with error: \(error.localizedDescription)") }
Objective-C
FIRModelInputOutputOptions *ioOptions = [[FIRModelInputOutputOptions alloc] init]; NSError *error; [ioOptions setInputFormatForIndex:0 type:FIRModelElementTypeFloat32 dimensions:@[@1, @224, @224, @3] error:&error]; if (error != nil) { return; } [ioOptions setOutputFormatForIndex:0 type:FIRModelElementTypeFloat32 dimensions:@[@1, @1000] error:&error]; if (error != nil) { return; }
Giriş verilerinde çıkarım yap
Son olarak, modeli kullanarak çıkarım yapmak, giriş verilerinizi almak,
dönüşüm işlemlerini daha verimli şekilde gerçekleştirebilir ve
Verileri içeren Data
nesnesi.
Örneğin, modeliniz görüntüleri işliyorsa ve modelinizin giriş boyutları varsa
[BATCH_SIZE, 224, 224, 3]
kayan nokta değerinden dolayı
resmin renk değerlerini, aşağıdaki örnekte olduğu gibi bir kayan nokta aralığına ayarlayın:
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 } let inputs = ModelInputs() var inputData = Data() do { for row in 0 ..< 224 { for col in 0 ..< 224 { let offset = 4 * (col * context.width + row) // (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) } } try inputs.addInput(inputData) } catch let error { print("Failed to add input: \(error)") }
Objective-C
CGImageRef image = // Your input image long imageWidth = CGImageGetWidth(image); long imageHeight = CGImageGetHeight(image); CGContextRef context = CGBitmapContextCreate(nil, imageWidth, imageHeight, 8, imageWidth * 4, CGColorSpaceCreateDeviceRGB(), kCGImageAlphaNoneSkipFirst); CGContextDrawImage(context, CGRectMake(0, 0, imageWidth, imageHeight), image); UInt8 *imageData = CGBitmapContextGetData(context); FIRModelInputs *inputs = [[FIRModelInputs alloc] init]; NSMutableData *inputData = [[NSMutableData alloc] initWithCapacity:0]; for (int row = 0; row < 224; row++) { for (int col = 0; col < 224; col++) { long offset = 4 * (col * imageWidth + row); // 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. // (Ignore offset 0, the unused alpha channel) Float32 red = imageData[offset+1] / 255.0f; Float32 green = imageData[offset+2] / 255.0f; Float32 blue = imageData[offset+3] / 255.0f; [inputData appendBytes:&red length:sizeof(red)]; [inputData appendBytes:&green length:sizeof(green)]; [inputData appendBytes:&blue length:sizeof(blue)]; } } [inputs addInput:inputData error:&error]; if (error != nil) { return nil; }
Model girişinizi hazırladıktan sonra (ve modelin,
varsa, giriş ve giriş/çıkış seçeneklerini
model çevirmeninizin run(inputs:options:completion:)
yöntemidir.
Swift
interpreter.run(inputs: inputs, options: ioOptions) { outputs, error in guard error == nil, let outputs = outputs else { return } // Process outputs // ... }
Objective-C
[interpreter runWithInputs:inputs options:ioOptions completion:^(FIRModelOutputs * _Nullable outputs, NSError * _Nullable error) { if (error != nil || outputs == nil) { return; } // Process outputs // ... }];
Oluşturulan nesnenin output(index:)
yöntemini çağırarak çıktıyı alabilirsiniz
hatası döndürülür. Örneğin:
Swift
// Get first and only output of inference with a batch size of 1 let output = try? outputs.output(index: 0) as? [[NSNumber]] let probabilities = output??[0]
Objective-C
// Get first and only output of inference with a batch size of 1 NSError *outputError; NSArray *probabilites = [outputs outputAtIndex:0 error:&outputError][0];
Sonucu nasıl kullanacağınız, kullandığınız modele bağlıdır.
Örneğin, sınıflandırma yapıyorsanız, bir sonraki adım olarak sonucun dizinlerini, temsil ettikleri etiketlerle eşleştirir. Bir modelinizin her bir kategorisi için etiket dizeleri içeren metin dosyası; dünyanın dört bir yanındaki etiket dizelerini çıkış olasılıklarına bağlayacak şekilde takip etmek için:
Swift
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 0 ..< labels.count { if let probability = probabilities?[i] { print("\(labels[i]): \(probability)") } }
Objective-C
NSError *labelReadError = nil; NSString *labelPath = [NSBundle.mainBundle pathForResource:@"retrained_labels" ofType:@"txt"]; NSString *fileContents = [NSString stringWithContentsOfFile:labelPath encoding:NSUTF8StringEncoding error:&labelReadError]; if (labelReadError != nil || fileContents == NULL) { return; } NSArray<NSString *> *labels = [fileContents componentsSeparatedByString:@"\n"]; for (int i = 0; i < labels.count; i++) { NSString *label = labels[i]; NSNumber *probability = probabilites[i]; NSLog(@"%@: %f", label, probability.floatValue); }
Ek: Model güvenliği
TensorFlow Lite modellerinizi kullanıcılara nasıl sunduğunuz fark etmeksizin ML Kit, ML Kit, bu dosyaları standart serileştirilmiş protobuf biçiminde depolar. yerel depolama.
Teoride bu, herkesin modelinizi kopyalayabileceği anlamına gelir. Ancak, pratikte çoğu model, uygulamaya özgüdür ve her bir model rakiplerin parçalarının parçalarının sökülüp parçalarının parçalarının kodunuzu tekrarlamanız gerekir. Yine de, anahtar kelimeleri kullanmadan önce bu riskin farkında olmalısınız. bir model oluşturabilirsiniz.