इस दस्तावेज़ में, LiteRT के ऑपरेटिंग वर्शन के स्कीमा के बारे में बताया गया है. ऑपरेशन के वर्शन के हिसाब से, डेवलपर मौजूदा ऑपरेशन में नई सुविधाएं और पैरामीटर जोड़ सकते हैं. इसके अलावा, इससे ये चीज़ें भी पक्का होती हैं:
- पुराने सिस्टम के साथ काम करने की सुविधा: नए LiteRT लागू करने पर, वह पुरानी मॉडल फ़ाइल को मैनेज कर सकता है.
- फ़ॉरवर्ड कम्पैटिबिलिटी: जब तक कोई नई सुविधा इस्तेमाल नहीं की जाती, तब तक LiteRT के पुराने वर्शन को कन्वर्टर के नए वर्शन से जनरेट की गई नई मॉडल फ़ाइल को मैनेज करना चाहिए.
- काम न करने वाले वर्शन का पता लगाने की सुविधा: अगर कोई पुराना LiteRT लागू करने वाला टूल, ऐसा नया मॉडल पढ़ता है जिसमें किसी ऐसे ऑपरेशन का नया वर्शन शामिल है जो काम नहीं करता, तो उसे गड़बड़ी की सूचना देनी चाहिए.
उदाहरण: डेप्थ-वाइज़ कॉन्वोल्यूशन में डाइलेशन जोड़ना
इस दस्तावेज़ के बाकी हिस्से में, TFLite में ऑपरेशन के वर्शन के बारे में बताया गया है. इसमें, डेप्थ-वाइज़ कन्वोल्यूशन ऑपरेशन में डाइलेशन पैरामीटर जोड़ने का तरीका बताया गया है.
इस दस्तावेज़ को समझने के लिए, डाइलेशन के बारे में जानकारी होना ज़रूरी नहीं है. ध्यान दें कि:
- दो नए इंटिजर पैरामीटर जोड़े जाएंगे:
dilation_width_factor
औरdilation_height_factor
. - ऐसे पुराने डेप्थ-वाइज़ कन्वोल्यूशन कर्नेल जिनमें डाइलेशन की सुविधा काम नहीं करती, वे डाइलेशन फ़ैक्टर को 1 पर सेट करने के बराबर होते हैं.
FlatBuffer स्कीमा बदलना
किसी ऑपरेशन में नए पैरामीटर जोड़ने के लिए, lite/schema/schema.fbs
में विकल्पों की टेबल बदलें.
उदाहरण के लिए, डेप्थ-वाइज़ कॉन्वोल्यूशन की विकल्प टेबल इस तरह दिखती है:
table DepthwiseConv2DOptions {
padding:Padding;
stride_w:int;
stride_h:int;
depth_multiplier:int;
fused_activation_function:ActivationFunctionType;
}
नए पैरामीटर जोड़ते समय:
- टिप्पणियां जोड़ें, ताकि यह पता चल सके कि किस वर्शन में कौनसे पैरामीटर काम करते हैं.
- जब नए लागू किए गए टैग में, जोड़े गए नए पैरामीटर के लिए डिफ़ॉल्ट वैल्यू मिलती हैं, तो यह पुराने टैग की तरह ही काम करना चाहिए.
नए पैरामीटर जोड़ने के बाद, टेबल इस तरह दिखेगी:
table DepthwiseConv2DOptions {
// Parameters for DepthwiseConv version 1 or above.
padding:Padding;
stride_w:int;
stride_h:int;
depth_multiplier:int;
fused_activation_function:ActivationFunctionType;
// Parameters for DepthwiseConv version 2 or above.
dilation_w_factor:int = 1;
dilation_h_factor:int = 1;
}
नए स्कीमा के लिए, lite/schema/schema_generated.h
फ़ाइल को फिर से जनरेट करना चाहिए.
C स्ट्रक्चर और कर्नेल लागू करने का तरीका बदलना
LiteRT में, कर्नेल को लागू करने की प्रोसेस को FlatBuffer की परिभाषा से अलग किया गया है. कर्नेल, lite/c/builtin_op_data.h
में तय किए गए C स्ट्रक्चर से पैरामीटर पढ़ते हैं.
ओरिजनल डेप्थ-वाइज़ कन्वोल्यूशन पैरामीटर इस तरह का होता है:
typedef struct {
TfLitePadding padding;
int stride_width;
int stride_height;
int depth_multiplier;
TfLiteFusedActivation activation;
} TfLiteDepthwiseConvParams;
FlatBuffer स्कीमा की तरह ही, टिप्पणियां जोड़ें. इनसे यह पता चलता है कि किस वर्शन से कौनसे पैरामीटर काम करते हैं. नतीजा यहां दिख रहा है:
typedef struct {
// Parameters for DepthwiseConv version 1 or above.
TfLitePadding padding;
int stride_width;
int stride_height;
int depth_multiplier;
TfLiteFusedActivation activation;
// Parameters for DepthwiseConv version 2 or above.
int dilation_width_factor;
int dilation_height_factor;
} TfLiteDepthwiseConvParams;
C स्ट्रक्चर से जोड़े गए नए पैरामीटर पढ़ने के लिए, कृपया कर्नेल लागू करने का तरीका भी बदलें. यहां जानकारी नहीं दी गई है.
FlatBuffer कोड को पढ़ने का तरीका बदलना
FlatBuffer को पढ़ने और C स्ट्रक्चर बनाने का लॉजिक,
lite/core/api/flatbuffer_conversions.cc
में है.
नए पैरामीटर को मैनेज करने के लिए, फ़ाइल को अपडेट करें. इसके लिए, यहां दिया गया तरीका अपनाएं:
TfLiteStatus ParseDepthwiseConv2D(const Operator* op,
ErrorReporter* error_reporter,
BuiltinDataAllocator* allocator,
void** builtin_data) {
CheckParsePointerParams(op, error_reporter, allocator, builtin_data);
SafeBuiltinDataAllocator safe_allocator(allocator);
std::unique_ptr<TfLiteDepthwiseConvParams,
SafeBuiltinDataAllocator::BuiltinDataDeleter>
params = safe_allocator.Allocate<TfLiteDepthwiseConvParams>();
TF_LITE_ENSURE(error_reporter, params != nullptr);
const DepthwiseConv2DOptions* schema_params =
op->builtin_options_as_DepthwiseConv2DOptions();
if (schema_params != nullptr) {
params->padding = ConvertPadding(schema_params->padding());
params->stride_width = schema_params->stride_w();
params->stride_height = schema_params->stride_h();
params->depth_multiplier = schema_params->depth_multiplier();
params->activation =
ConvertActivation(schema_params->fused_activation_function());
params->dilation_width_factor = schema_params->dilation_w_factor();
params->dilation_height_factor = schema_params->dilation_h_factor();
}
*builtin_data = params.release();
return kTfLiteOk;
}
यहां ओपी वर्शन की जांच करने की ज़रूरत नहीं है. जब नया लागू करने का तरीका, ऐसी पुरानी मॉडल फ़ाइल को पढ़ता है जिसमें डाइलेशन फ़ैक्टर मौजूद नहीं होते, तो वह डिफ़ॉल्ट वैल्यू के तौर पर 1 का इस्तेमाल करेगा. साथ ही, नया केरल पुराने केरल के साथ लगातार काम करेगा.
कर्नेल रजिस्ट्रेशन बदलना
MutableOpResolver (lite/mutable_op_resolver.h
में बताया गया है), ऑपरेशन के कोर को रजिस्टर करने के लिए कुछ फ़ंक्शन उपलब्ध कराता है. डिफ़ॉल्ट रूप से, वर्शन की कम से कम और ज़्यादा से ज़्यादा संख्या 1 होती है:
void AddBuiltin(tflite::BuiltinOperator op, TfLiteRegistration* registration,
int min_version = 1, int max_version = 1);
void AddCustom(const char* name, TfLiteRegistration* registration,
int min_version = 1, int max_version = 1);
पहले से मौजूद ऑपरेशन, lite/kernels/register.cc
में रजिस्टर किए गए हैं. इस उदाहरण में, हमने एक नया ऑपरेटिंग सिस्टम केर्नेल लागू किया है, जो DepthwiseConv2D
के वर्शन 1 और 2 को मैनेज कर सकता है. इसलिए, हमें इस लाइन को बदलना होगा:
AddBuiltin(BuiltinOperator_DEPTHWISE_CONV_2D, Register_DEPTHWISE_CONV_2D());
इससे बदलें:
AddBuiltin(BuiltinOperator_DEPTHWISE_CONV_2D, Register_DEPTHWISE_CONV_2D(),
/* min_version = */ 1,
/* max_version = */ 2);
TFLite ऑपरेशन का वर्शन बदलना
अगला चरण, TFLite को ऑपरेशन को लागू करने के लिए ज़रूरी कम से कम वर्शन को पॉप्युलेट करना है. इस उदाहरण में इसका मतलब है:
- जब सभी डाइलेशन फ़ैक्टर 1 हों, तो version=1 पॉप्युलेट करें.
- अगर ऐसा नहीं है, तो version=2 को पॉप्युलेट करें.
lite/tools/versioning/op_version.cc
में ऑपरेटर के लिए GetBuiltinOperatorVersion
फ़ंक्शन में बदलाव करें. इसके लिए, DepthwiseConv2D
के केस में नया वर्शन जोड़ें:
case BuiltinOperator_DEPTHWISE_CONV_2D:
auto depthwise_conv_params =
reinterpret_cast<TfLiteDepthwiseConvParams*>(op_sig.builtin_data);
TFLITE_DCHECK(depthwise_conv_params != nullptr);
if (depthwise_conv_params->dilation_width_factor != 1 ||
depthwise_conv_params->dilation_height_factor != 1) {
return 2;
}
return 1;
ऑपरेटर के वर्शन का मैप अपडेट करना
आखिरी चरण में, ऑपरेटर वर्शन मैप में नए वर्शन की जानकारी जोड़ें. यह चरण ज़रूरी है, क्योंकि हमें इस वर्शन मैप के आधार पर, मॉडल का कम से कम ज़रूरी रनटाइम वर्शन जनरेट करना होगा.
ऐसा करने के लिए, आपको lite/tools/versioning/runtime_version.cc
में मैप की नई एंट्री जोड़नी होगी.
इस उदाहरण में, आपको op_version_map
में यह एंट्री जोड़नी होगी:
{ {BuiltinOperator_DEPTHWISE_CONV_2D, 2}, %CURRENT_RUNTIME_VERSION%}
यहां %CURRENT_RUNTIME_VERSION%
, release_version.h में बताए गए मौजूदा रनटाइम वर्शन से मेल खाता है.
डेलिगेशन लागू करना
LiteRT, एक ऐसा एपीआई उपलब्ध कराता है जिसकी मदद से, ऑपरेशन को हार्डवेयर बैकएंड को सौंपा जा सकता है. डेलिगेट के Prepare
फ़ंक्शन में, देखें कि क्या वर्शन, डेलिगेशन कोड में मौजूद हर नोड के लिए काम करता है.
const int kMaxVersion = 1;
TfLiteNode* node;
TfLiteRegistration* registration = nullptr;
TF_LITE_ENSURE_STATUS(context->GetNodeAndRegistration(context, node_index, &node, ®istration));
if (registration->version > kMaxVersion) {
// Reject the node if the version isn't supported.
}
यह तब भी ज़रूरी है, जब डिलीगेशन सिर्फ़ वर्शन 1 के ऑपरेशन के साथ काम करता हो. इससे, डिलीगेशन को किसी नए वर्शन के ऑपरेशन के साथ काम न करने का पता चल सकता है.