Firebase/MLModelInterpreter
kitaplığının 0.20.0 sürümü, özel modellerin aygıtındaki konumu alan yeni bir getLatestModelFilePath()
yöntemini sunar. Firebase'in ModelInterpreter
sarmalayıcısı yerine kullanabileceğiniz bir TensorFlow Lite Interpreter
nesnesini doğrudan başlatmak için bu yöntemi kullanabilirsiniz.
İleriye dönük olarak, bu tercih edilen yaklaşımdır. TensorFlow Lite yorumlayıcı sürümü artık Firebase kitaplığı sürümüyle birleştirilmediğinden, istediğiniz zaman TensorFlow Lite'ın yeni sürümlerine yükseltmek veya özel TensorFlow Lite yapılarını daha kolay kullanmak için daha fazla esnekliğe sahipsiniz.
Bu sayfa, ModelInterpreter
kullanmaktan TensorFlow Lite Interpreter
nasıl geçiş yapabileceğinizi gösterir.
1. Proje bağımlılıklarını güncelleyin
Firebase/MLModelInterpreter
kitaplığının (veya daha yenisinin) ve TensorFlow Lite kitaplığının 0.20.0 sürümünü içerecek şekilde projenizin Pod dosyasını güncelleyin:
Önce
Süratli
pod 'Firebase/MLModelInterpreter', '0.19.0'
Amaç-C
pod 'Firebase/MLModelInterpreter', '0.19.0'
Sonrasında
Süratli
pod 'Firebase/MLModelInterpreter', '~> 0.20.0'
pod 'TensorFlowLiteSwift'
Amaç-C
pod 'Firebase/MLModelInterpreter', '~> 0.20.0'
pod 'TensorFlowLiteObjC'
2. Firebase ModelInterpreter yerine bir TensorFlow Lite yorumlayıcısı oluşturun
Firebase ModelInterpreter
oluşturmak yerine getLatestModelFilePath()
ile modelin cihazdaki konumunu alın ve bunu bir TensorFlow Lite Interpreter
oluşturmak için kullanın.
Önce
Süratli
let remoteModel = CustomRemoteModel(
name: "your_remote_model" // The name you assigned in the Firebase console.
)
interpreter = ModelInterpreter.modelInterpreter(remoteModel: remoteModel)
Amaç-C
// Initialize using the name you assigned in the Firebase console.
FIRCustomRemoteModel *remoteModel =
[[FIRCustomRemoteModel alloc] initWithName:@"your_remote_model"];
interpreter = [FIRModelInterpreter modelInterpreterForRemoteModel:remoteModel];
Sonrasında
Süratli
let remoteModel = CustomRemoteModel(
name: "your_remote_model" // The name you assigned in the Firebase console.
)
ModelManager.modelManager().getLatestModelFilePath(remoteModel) { (remoteModelPath, error) in
guard error == nil, let remoteModelPath = remoteModelPath else { return }
do {
interpreter = try Interpreter(modelPath: remoteModelPath)
} catch {
// Error?
}
}
Amaç-C
FIRCustomRemoteModel *remoteModel =
[[FIRCustomRemoteModel alloc] initWithName:@"your_remote_model"];
[[FIRModelManager modelManager] getLatestModelFilePath:remoteModel
completion:^(NSString * _Nullable filePath,
NSError * _Nullable error) {
if (error != nil || filePath == nil) { return; }
NSError *tfError = nil;
interpreter = [[TFLInterpreter alloc] initWithModelPath:filePath error:&tfError];
}];
3. Girdi ve çıktı hazırlama kodunu güncelleyin
ModelInterpreter
ile, çalıştırdığınızda yorumlayıcıya bir ModelInputOutputOptions
nesnesi ileterek modelin girdi ve çıktı şekillerini belirtirsiniz.
TensorFlow Lite yorumlayıcısı için bunun yerine allocateTensors()
u çağırarak modelin giriş ve çıkışına yer ayırın, ardından giriş verilerinizi giriş tensörlerine kopyalayın.
Örneğin, modelinizin giriş şekli [1 224 224 3] float
değerlere ve çıkış şekli [1 1000] float
değerlere sahipse şu değişiklikleri yapın:
Önce
Süratli
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)")
}
let inputs = ModelInputs()
do {
let inputData = Data()
// Then populate with input data.
try inputs.addInput(inputData)
} catch let error {
print("Failed to add input: \(error)")
}
interpreter.run(inputs: inputs, options: ioOptions) { outputs, error in
guard error == nil, let outputs = outputs else { return }
// Process outputs
// ...
}
Amaç-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; }
FIRModelInputs *inputs = [[FIRModelInputs alloc] init];
NSMutableData *inputData = [[NSMutableData alloc] initWithCapacity:0];
// Then populate with input data.
[inputs addInput:inputData error:&error];
if (error != nil) { return; }
[interpreter runWithInputs:inputs
options:ioOptions
completion:^(FIRModelOutputs * _Nullable outputs,
NSError * _Nullable error) {
if (error != nil || outputs == nil) {
return;
}
// Process outputs
// ...
}];
Sonrasında
Süratli
do {
try interpreter.allocateTensors()
let inputData = Data()
// Then populate with input data.
try interpreter.copy(inputData, toInputAt: 0)
try interpreter.invoke()
} catch let err {
print(err.localizedDescription)
}
Amaç-C
NSError *error = nil;
[interpreter allocateTensorsWithError:&error];
if (error != nil) { return; }
TFLTensor *input = [interpreter inputTensorAtIndex:0 error:&error];
if (error != nil) { return; }
NSMutableData *inputData = [[NSMutableData alloc] initWithCapacity:0];
// Then populate with input data.
[input copyData:inputData error:&error];
if (error != nil) { return; }
[interpreter invokeWithError:&error];
if (error != nil) { return; }
4. Çıkış işleme kodunu güncelleyin
Son olarak, ModelOutputs
nesnesinin output()
yöntemiyle modelin çıktısını almak yerine, yorumlayıcıdan çıktı tensörünü alın ve verilerini kullanım durumunuz için uygun olan yapıya dönüştürün.
Örneğin, sınıflandırma yapıyorsanız aşağıdaki gibi değişiklikler yapabilirsiniz:
Önce
Süratli
let output = try? outputs.output(index: 0) as? [[NSNumber]]
let probabilities = output?[0]
guard let labelPath = Bundle.main.path(
forResource: "custom_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)")
}
}
Amaç-C
// Get first and only output of inference with a batch size of 1
NSError *error;
NSArray *probabilites = [outputs outputAtIndex:0 error:&error][0];
if (error != nil) { return; }
NSString *labelPath = [NSBundle.mainBundle pathForResource:@"retrained_labels"
ofType:@"txt"];
NSString *fileContents = [NSString stringWithContentsOfFile:labelPath
encoding:NSUTF8StringEncoding
error:&error];
if (error != 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);
}
Sonrasında
Süratli
do {
// After calling interpreter.invoke():
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: "custom_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])")
}
} catch let err {
print(err.localizedDescription)
}
Amaç-C
NSError *error = nil;
TFLTensor *output = [interpreter outputTensorAtIndex:0 error:&error];
if (error != nil) { return; }
NSData *outputData = [output dataWithError:&error];
if (error != nil) { return; }
Float32 probabilities[outputData.length / 4];
[outputData getBytes:&probabilities length:outputData.length];
NSString *labelPath = [NSBundle.mainBundle pathForResource:@"custom_labels"
ofType:@"txt"];
NSString *fileContents = [NSString stringWithContentsOfFile:labelPath
encoding:NSUTF8StringEncoding
error:&error];
if (error != nil || fileContents == nil) { return; }
NSArray<NSString *> *labels = [fileContents componentsSeparatedByString:@"\n"];
for (int i = 0; i < labels.count; i++) {
NSLog(@"%@: %f", labels[i], probabilities[i]);
}