Versi operator TensorFlow Lite

Dokumen ini menjelaskan skema pembuatan versi op TensorFlow Lite. Pembuatan versi op memungkinkan pengembang untuk menambahkan fungsionalitas dan parameter baru ke dalam operasi yang ada. Selain itu, ini menjamin hal-hal berikut:

  • Kompatibilitas mundur: Implementasi TensorFlow Lite baru harus menangani file model lama.
  • Kompatibilitas ke depan: Implementasi TensorFlow Lite lama harus menangani file model baru yang dihasilkan oleh konverter versi baru, selama tidak ada fitur baru yang digunakan.
  • Deteksi kompatibilitas ke depan: Jika implementasi TensorFlow Lite lama membaca model baru yang berisi versi baru dari operasi yang tidak didukung, itu akan melaporkan kesalahannya.

Contoh: Menambahkan dilatasi ke dalam konvolusi mendalam

Sisa dari dokumen ini menjelaskan versi op di TFLite dengan menunjukkan cara menambahkan parameter dilatasi ke operasi konvolusi yang mendalam.

Pengetahuan tentang pelebaran tidak diperlukan untuk memahami dokumen ini. Perhatikan bahwa:

  • 2 parameter integer baru akan ditambahkan: dilation_width_factor dan dilation_height_factor .
  • Kernel konvolusi mendalam lama yang tidak mendukung pelebaran sama dengan menyetel faktor pelebaran ke 1.

Ubah skema FlatBuffer

Untuk menambahkan parameter baru ke dalam operasi, ubah tabel opsi di lite/schema/schema.fbs .

Misalnya, tabel opsi konvolusi mendalam terlihat seperti ini:

table DepthwiseConv2DOptions {
  padding:Padding;
  stride_w:int;
  stride_h:int;
  depth_multiplier:int;
  fused_activation_function:ActivationFunctionType;
}

Saat menambahkan parameter baru:

  • Tambahkan komentar yang menunjukkan parameter mana yang didukung oleh versi mana.
  • Ketika implementasi baru mendapatkan nilai default untuk parameter yang baru ditambahkan, itu harus bekerja persis sama dengan implementasi lama.

Tabel akan seperti ini setelah parameter baru ditambahkan:

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

File lite/schema/schema_generated.h harus dibuat ulang untuk skema baru.

Ubah struktur C dan implementasi kernel

Di TensorFlow Lite, implementasi kernel dipisahkan dari definisi FlatBuffer. Kernel membaca parameter dari struktur C yang didefinisikan dalam lite/c/builtin_op_data.h .

Parameter konvolusi depthwise asli adalah sebagai berikut:

typedef struct {
  TfLitePadding padding;
  int stride_width;
  int stride_height;
  int depth_multiplier;
  TfLiteFusedActivation activation;
} TfLiteDepthwiseConvParams;

Seperti skema FlatBuffer, tambahkan komentar yang menunjukkan parameter mana yang didukung mulai dari versi mana. Hasilnya terlihat di bawah ini:

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;

Harap juga ubah implementasi kernel untuk membaca parameter yang baru ditambahkan dari struktur C. Detailnya dihilangkan di sini.

Ubah kode pembacaan FlatBuffer

Logika untuk membaca FlatBuffer dan menghasilkan struktur C ada di lite/core/api/flatbuffer_conversions.cc .

Perbarui file untuk menangani parameter baru, seperti yang ditunjukkan di bawah ini:

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

Tidak perlu memeriksa versi op di sini. Ketika implementasi baru membaca file model lama di mana faktor pelebaran hilang, itu akan menggunakan 1 sebagai nilai default, dan kernel baru akan bekerja secara konsisten dengan kernel lama.

Ubah pendaftaran kernel

MutableOpResolver (didefinisikan dalam lite/mutable_op_resolver.h ) menyediakan beberapa fungsi untuk mendaftarkan kernel op. Versi minimum dan maksimum adalah 1 secara default:

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

Operasi bawaan terdaftar di lite/kernels/register.cc . Dalam contoh ini, kami mengimplementasikan kernel op baru yang dapat menangani DepthwiseConv2D versi 1 dan 2, jadi kami perlu mengubah baris ini:

AddBuiltin(BuiltinOperator_DEPTHWISE_CONV_2D, Register_DEPTHWISE_CONV_2D());

ke:

AddBuiltin(BuiltinOperator_DEPTHWISE_CONV_2D, Register_DEPTHWISE_CONV_2D(),
             /* min_version = */ 1,
             /* max_version = */ 2);

Ubah versi operasi TFLite

Langkah selanjutnya adalah membuat TFLite mengisi versi minimum yang diperlukan untuk menjalankan operasi. Dalam contoh ini, artinya:

  • Isi versi=1 ketika faktor pelebaran semuanya 1.
  • Isi versi=2 sebaliknya.

Ubah fungsi GetBuiltinOperatorVersion untuk operator di lite/tools/versioning/op_version.cc dengan menambahkan versi baru ke kasus 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;

Perbarui peta versi operator

Langkah terakhir adalah menambahkan info versi baru ke dalam peta versi operator. Langkah ini diperlukan karena kita perlu membuat versi runtime minimum model yang diperlukan berdasarkan peta versi ini.

Untuk melakukan ini, Anda perlu menambahkan entri peta baru di lite/tools/versioning/runtime_version.cc .

Dalam contoh ini, Anda perlu menambahkan entri berikut ke op_version_map :

{ {BuiltinOperator_DEPTHWISE_CONV_2D, 2}, %CURRENT_RUNTIME_VERSION%}

di mana %CURRENT_RUNTIME_VERSION% sesuai dengan versi runtime saat ini yang ditentukan dalam tensorflow/core/public/version.h .

Pelaksanaan delegasi

TensorFlow Lite menyediakan API delegasi yang memungkinkan pendelegasian operasi ke backend perangkat keras. Dalam fungsi Prepare delegasi, periksa apakah versi didukung untuk setiap node dalam kode Delegasi.

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

Ini diperlukan meskipun delegasi hanya mendukung operasi versi 1, sehingga delegasi dapat mendeteksi ketidakcocokan saat mendapatkan operasi versi yang lebih tinggi.