Firebase/MLModelInterpreter
लाइब्रेरी के वर्शन 0.20.0 में एक नया getLatestModelFilePath()
तरीका जोड़ा गया है, जिससे कस्टम मॉडल वाले डिवाइस की जगह की जानकारी मिलती है. इस तरीके का इस्तेमाल करके, सीधे TensorFlow Lite
Interpreter
ऑब्जेक्ट को इंस्टैंशिएट किया जा सकता है. इसका इस्तेमाल, Firebase के ModelInterpreter
रैपर के बजाय किया जा सकता है.
आने वाले समय में, यह तरीका अपनाना बेहतर होगा. TensorFlow Lite के इंटरप्रिटर वर्शन को अब Firebase लाइब्रेरी के वर्शन के साथ जोड़ा नहीं गया है. इसलिए, अब जब चाहें, TensorFlow Lite के नए वर्शन पर अपग्रेड किया जा सकता है. इसके अलावा, कस्टम TensorFlow Lite बिल्ड का इस्तेमाल करना भी आसान हो गया है.
इस पेज पर बताया गया है कि ModelInterpreter
का इस्तेमाल करने से,
TensorFlow Lite Interpreter
पर माइग्रेट कैसे किया जा सकता है.
1. प्रोजेक्ट डिपेंडेंसी अपडेट करना
अपने प्रोजेक्ट की Podfile को अपडेट करें, ताकि Firebase/MLModelInterpreter
लाइब्रेरी का 0.20.0 वर्शन (या इसके बाद का वर्शन) और TensorFlow Lite लाइब्रेरी शामिल की जा सके:
इससे पहले
Swift
pod 'Firebase/MLModelInterpreter', '0.19.0'
Objective-C
pod 'Firebase/MLModelInterpreter', '0.19.0'
इसके बाद
Swift
pod 'Firebase/MLModelInterpreter', '~> 0.20.0'
pod 'TensorFlowLiteSwift'
Objective-C
pod 'Firebase/MLModelInterpreter', '~> 0.20.0'
pod 'TensorFlowLiteObjC'
2. Firebase ModelInterpreter के बजाय, TensorFlow Lite इंटरप्रेटर बनाना
Firebase ModelInterpreter
बनाने के बजाय, getLatestModelFilePath()
की मदद से डिवाइस पर मॉडल की जगह की जानकारी पाएं और इसका इस्तेमाल TensorFlow Lite Interpreter
बनाने के लिए करें.
इससे पहले
Swift
let remoteModel = CustomRemoteModel(
name: "your_remote_model" // The name you assigned in the Firebase console.
)
interpreter = ModelInterpreter.modelInterpreter(remoteModel: remoteModel)
Objective-C
// Initialize using the name you assigned in the Firebase console.
FIRCustomRemoteModel *remoteModel =
[[FIRCustomRemoteModel alloc] initWithName:@"your_remote_model"];
interpreter = [FIRModelInterpreter modelInterpreterForRemoteModel:remoteModel];
इसके बाद
Swift
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?
}
}
Objective-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
वैल्यू है, तो ये बदलाव करें:
इससे पहले
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)")
}
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
// ...
}
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; }
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
// ...
}];
इसके बाद
Swift
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)
}
Objective-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. आउटपुट को हैंडल करने वाला कोड अपडेट करना
आखिर में, ModelOutputs
ऑब्जेक्ट के output()
तरीके से मॉडल का आउटपुट पाने के बजाय, इंटरप्रेटर से आउटपुट टेंसर पाएं और उसके डेटा को उस स्ट्रक्चर में बदलें जो आपके इस्तेमाल के उदाहरण के लिए सही हो.
उदाहरण के लिए, अगर डेटा को अलग-अलग कैटगरी में बांटा जा रहा है, तो इनमें बदलाव किए जा सकते हैं:
इससे पहले
Swift
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)")
}
}
Objective-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);
}
इसके बाद
Swift
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)
}
Objective-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]);
}