نسخه 0.20.0 کتابخانه Firebase/MLModelInterpreter
یک متد getLatestModelFilePath()
جدید را معرفی می کند که مکان را در دستگاه مدل های سفارشی دریافت می کند. میتوانید از این روش برای نمونهسازی مستقیم یک شی Interpreter
TensorFlow Lite استفاده کنید، که میتوانید بهجای بستهبندی ModelInterpreter
Firebase از آن استفاده کنید.
در آینده، این رویکرد ارجح است. از آنجایی که نسخه مفسر TensorFlow Lite دیگر با نسخه کتابخانه Firebase همراه نیست، انعطاف پذیری بیشتری برای ارتقاء به نسخه های جدید TensorFlow Lite در صورت تمایل دارید، یا آسان تر از ساخت های سفارشی TensorFlow Lite استفاده کنید.
این صفحه نشان می دهد که چگونه می توانید از ModelInterpreter
به Interpreter
TensorFlow Lite مهاجرت کنید.
1. وابستگی های پروژه را به روز کنید
فایل پادفایل پروژه خود را بهروزرسانی کنید تا شامل نسخه 0.20.0 کتابخانه Firebase/MLModelInterpreter
(یا جدیدتر) و کتابخانه TensorFlow Lite باشد:
قبل از
سویفت
pod 'Firebase/MLModelInterpreter', '0.19.0'
هدف-C
pod 'Firebase/MLModelInterpreter', '0.19.0'
بعد از
سویفت
pod 'Firebase/MLModelInterpreter', '~> 0.20.0'
pod 'TensorFlowLiteSwift'
هدف-C
pod 'Firebase/MLModelInterpreter', '~> 0.20.0'
pod 'TensorFlowLiteObjC'
2. یک مفسر TensorFlow Lite به جای Firebase ModelInterpreter ایجاد کنید
به جای ایجاد یک Firebase ModelInterpreter
، مکان مدل را در دستگاه با getLatestModelFilePath()
دریافت کنید و از آن برای ایجاد یک Interpreter
TensorFlow Lite استفاده کنید.
قبل از
سویفت
let remoteModel = CustomRemoteModel(
name: "your_remote_model" // The name you assigned in the Firebase console.
)
interpreter = ModelInterpreter.modelInterpreter(remoteModel: remoteModel)
هدف-C
// Initialize using the name you assigned in the Firebase console.
FIRCustomRemoteModel *remoteModel =
[[FIRCustomRemoteModel alloc] initWithName:@"your_remote_model"];
interpreter = [FIRModelInterpreter modelInterpreterForRemoteModel:remoteModel];
بعد از
سویفت
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?
}
}
هدف-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. کد آماده سازی ورودی و خروجی را به روز کنید
با ModelInterpreter
، هنگام اجرای آن، شکل ورودی و خروجی مدل را با ارسال یک شی ModelInputOutputOptions
به مفسر مشخص میکنید.
برای مفسر TensorFlow Lite، به جای آن، allocateTensors()
فراخوانی کنید تا فضا را برای ورودی و خروجی مدل تخصیص دهد، سپس داده های ورودی خود را در تانسورهای ورودی کپی کنید.
برای مثال، اگر مدل شما دارای شکل ورودی [1 224 224 3] مقادیر float
و شکل خروجی [1 1000] مقادیر float
است، این تغییرات را انجام دهید:
قبل از
سویفت
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
// ...
}
هدف-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
// ...
}];
بعد از
سویفت
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)
}
هدف-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. کد مدیریت خروجی را به روز کنید
در نهایت، به جای دریافت خروجی مدل با متد output()
شی ModelOutputs
، تانسور خروجی را از مفسر دریافت کنید و داده های آن را به هر ساختاری که برای مورد استفاده شما مناسب است تبدیل کنید.
به عنوان مثال، اگر در حال انجام طبقه بندی هستید، ممکن است تغییراتی مانند موارد زیر ایجاد کنید:
قبل از
سویفت
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)")
}
}
هدف-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);
}
بعد از
سویفت
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)
}
هدف-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]);
}