Eski özel model API'sinden geçiş yapın

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 tercih edilen yaklaşım budur. TensorFlow Lite yorumlayıcı sürümü artık Firebase kitaplık sürümüyle bağlantılı olmadığından, istediğiniz zaman TensorFlow Lite'ın yeni sürümlerine yükseltme yapma veya özel TensorFlow Lite yapılarını daha kolay kullanma konusunda daha fazla esnekliğe sahip olursunuz.

Bu sayfada ModelInterpreter kullanımından TensorFlow Lite Interpreter nasıl geçiş yapabileceğiniz gösterilmektedir.

1. Proje bağımlılıklarını güncelleyin

Projenizin Pod dosyasını Firebase/MLModelInterpreter kitaplığının (veya daha yenisinin) ve TensorFlow Lite kitaplığının 0.20.0 sürümünü içerecek şekilde 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 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. Giriş ve çıkış hazırlık kodunu güncelleyin

ModelInterpreter ile, çalıştırdığınızda yorumlayıcıya bir ModelInputOutputOptions nesnesi ileterek modelin giriş ve çıkış şekillerini belirtirsiniz.

TensorFlow Lite yorumlayıcısı için, bunun yerine modelin girişi ve çıkışı için yer ayırmak üzere allocateTensors() öğesini çağırırsınız, ardından giriş verilerinizi giriş tensörlerine kopyalarsınız.

Örneğin, modelinizin giriş şekli [1 224 224 3] float değerlerden ve çıkış şekli ise [1 1000] float değerlerinden oluşuyorsa ş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. Çıktı 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]);
}