גרסאות מפעיל TensorFlow Lite

מסמך זה מתאר את סכימת גירסאות ההפעלה של TensorFlow Lite. ניהול גרסאות אופ מאפשר למפתחים להוסיף פונקציונליות ופרמטרים חדשים לאופציות קיימות. בנוסף, הוא מבטיח את הדברים הבאים:

  • תאימות לאחור: יישום חדש של TensorFlow Lite אמור לטפל בקובץ דגם ישן.
  • תאימות קדימה: הטמעה הישנה של TensorFlow Lite צריכה לטפל בקובץ דגם חדש המיוצר על ידי גרסה חדשה של הממיר, כל עוד לא נעשה שימוש בתכונות חדשות.
  • זיהוי אי-תאימות קדימה: אם מימוש ישן של TensorFlow Lite קורא מודל חדש המכיל גרסה חדשה של הפעלה שאינה נתמכת, עליו לדווח על השגיאה.

דוגמה: הוספת הרחבה לתוך פיתול לעומק

שאר המסמך הזה מסביר את גירסת ההפעלה ב-TFLite על ידי מראה כיצד להוסיף פרמטרי הרחבה לפעולת הפיתול לעומק.

אין צורך בידע בהרחבה כדי להבין מסמך זה. ציין זאת:

  • 2 פרמטרים שלמים חדשים יתווספו: 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 ויישום ליבה

ב-TensorFlow Lite, יישום הליבה מנותק מהגדרת FlatBuffer. הגרעינים קוראים את הפרמטר ממבני C המוגדרים ב- lite/c/builtin_op_data.h .

פרמטר הפיתול המקורי לעומק הוא כדלקמן:

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;
}

אין צורך לבדוק את גרסת ה-op כאן. כאשר המימוש החדש קורא קובץ מודל ישן שבו חסרים גורמי התרחבות, הוא ישתמש ב-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 op

השלב הבא הוא לגרום ל-TFLite לאכלס את הגרסה המינימלית הנדרשת לביצוע הפעולה. בדוגמה זו, זה אומר:

  • אוכלוס גרסה=1 כאשר גורמי ההתרחבות הם כולם 1.
  • אכלס גרסה=2 אחרת.

שנה את הפונקציה GetBuiltinOperatorVersion עבור המפעיל ב- lite/tools/versioning/op_version.cc על ידי הוספת הגרסה החדשה למקרה של 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% מתאים לגרסת זמן הריצה הנוכחית המוגדרת ב- tensorflow/core/public/version.h .

יישום משלחת

TensorFlow Lite מספק ממשק API להאצלה המאפשר האצלת פעולות לממשקי חומרה. בפונקציית Prepare של הנציג, בדוק אם הגרסה נתמכת עבור כל צומת בקוד האצלה.

const int kMaxVersion = 1;
TfLiteNode* node;
TfLiteRegistration* registration = nullptr;
TF_LITE_ENSURE_STATUS(context->GetNodeAndRegistration(context, node_index, &node, &registration));

if (registration->version > kMaxVersion) {
  // Reject the node if the version isn't supported.
}

זה נדרש גם אם האצלה תומכת רק ב-ops של גרסה 1, כך שהאצלה יכולה לזהות אי-תאימות בעת קבלת גרסה גבוהה יותר.