LiteRT দিয়ে শুরু করুন

এই নির্দেশিকা আপনাকে ইনপুট ডেটার উপর ভিত্তি করে ভবিষ্যদ্বাণী করার জন্য ডিভাইসে একটি LiteRT (Lite Runtime-এর জন্য সংক্ষিপ্ত) মডেল চালানোর প্রক্রিয়ার সাথে পরিচয় করিয়ে দেয়। এটি LiteRT ইন্টারপ্রেটারের সাহায্যে অর্জন করা হয়, যা ন্যূনতম লোড, প্রারম্ভিকতা এবং কার্যকর করার লেটেন্সি নিশ্চিত করতে একটি স্ট্যাটিক গ্রাফ অর্ডারিং এবং একটি কাস্টম (কম-ডাইনামিক) মেমরি বরাদ্দকারী ব্যবহার করে।

LiteRT অনুমান সাধারণত নিম্নলিখিত পদক্ষেপগুলি অনুসরণ করে:

  1. একটি মডেল লোড করা হচ্ছে : .tflite মডেলটিকে মেমরিতে লোড করুন, যার মধ্যে মডেলের এক্সিকিউশন গ্রাফ রয়েছে৷

  2. তথ্য রূপান্তর : প্রত্যাশিত বিন্যাস এবং মাত্রা ইনপুট তথ্য রূপান্তর. মডেলের জন্য কাঁচা ইনপুট ডেটা সাধারণত মডেল দ্বারা প্রত্যাশিত ইনপুট ডেটা বিন্যাসের সাথে মেলে না৷ উদাহরণস্বরূপ, মডেলের সাথে সামঞ্জস্যপূর্ণ হতে আপনাকে একটি চিত্রের আকার পরিবর্তন করতে বা চিত্র বিন্যাস পরিবর্তন করতে হতে পারে।

  3. চলমান অনুমান : ভবিষ্যদ্বাণী করতে LiteRT মডেলটি চালান। এই ধাপে মডেলটি চালানোর জন্য LiteRT API ব্যবহার করা জড়িত। এতে দোভাষী তৈরি করা এবং টেনসর বরাদ্দ করার মতো কয়েকটি ধাপ জড়িত।

  4. ইন্টারপ্রেটিং আউটপুট : আউটপুট টেনসরগুলিকে অর্থপূর্ণ উপায়ে ব্যাখ্যা করুন যা আপনার অ্যাপ্লিকেশনে কার্যকর। উদাহরণস্বরূপ, একটি মডেল শুধুমাত্র সম্ভাব্যতার একটি তালিকা দিতে পারে। প্রাসঙ্গিক বিভাগে সম্ভাব্যতা ম্যাপ করা এবং আউটপুট ফর্ম্যাট করা আপনার উপর নির্ভর করে।

এই নির্দেশিকা বর্ণনা করে কিভাবে LiteRT দোভাষী অ্যাক্সেস করতে হয় এবং C++, Java, এবং Python ব্যবহার করে একটি অনুমান সম্পাদন করতে হয়।

সমর্থিত প্ল্যাটফর্ম

টেনসরফ্লো ইনফারেন্স এপিআইগুলি বেশিরভাগ সাধারণ মোবাইল এবং এমবেডেড প্ল্যাটফর্মের জন্য প্রদান করা হয় যেমন Android , iOS এবং Linux , একাধিক প্রোগ্রামিং ভাষায়

বেশিরভাগ ক্ষেত্রে, API ডিজাইন ব্যবহারের সুবিধার চেয়ে কর্মক্ষমতার জন্য একটি অগ্রাধিকার প্রতিফলিত করে। LiteRT ছোট ডিভাইসে দ্রুত অনুমানের জন্য ডিজাইন করা হয়েছে, তাই APIs সুবিধার খরচে অপ্রয়োজনীয় অনুলিপিগুলি এড়ায়।

সমস্ত লাইব্রেরি জুড়ে, LiteRT API আপনাকে মডেল লোড করতে, ইনপুট ফিড করতে এবং অনুমান আউটপুট পুনরুদ্ধার করতে দেয়।

অ্যান্ড্রয়েড প্ল্যাটফর্ম

অ্যান্ড্রয়েডে, জাভা বা C++ API ব্যবহার করে LiteRT অনুমান করা যেতে পারে। Java APIs সুবিধা প্রদান করে এবং সরাসরি আপনার Android কার্যকলাপ ক্লাসের মধ্যে ব্যবহার করা যেতে পারে। C++ APIগুলি আরও নমনীয়তা এবং গতি প্রদান করে, কিন্তু Java এবং C++ স্তরগুলির মধ্যে ডেটা সরানোর জন্য JNI র‍্যাপার লেখার প্রয়োজন হতে পারে।

আরও তথ্যের জন্য C++ এবং Java বিভাগগুলি দেখুন, অথবা Android quickstart অনুসরণ করুন।

iOS প্ল্যাটফর্ম

iOS-এ, LiteRT সুইফট এবং অবজেক্টিভ-সি iOS লাইব্রেরিতে পাওয়া যায়। আপনি উদ্দেশ্য-সি কোডে সরাসরি C API ব্যবহার করতে পারেন।

Swift , Objective-C , এবং C API বিভাগগুলি দেখুন, অথবা iOS কুইকস্টার্ট অনুসরণ করুন।

লিনাক্স প্ল্যাটফর্ম

লিনাক্স প্ল্যাটফর্মে, আপনি C++ এ উপলব্ধ LiteRT API ব্যবহার করে অনুমান চালাতে পারেন।

একটি মডেল লোড করুন এবং চালান

একটি LiteRT মডেল লোড করা এবং চালানোর জন্য নিম্নলিখিত পদক্ষেপগুলি জড়িত:

  1. মেমরিতে মডেল লোড করা হচ্ছে।
  2. একটি বিদ্যমান মডেলের উপর ভিত্তি করে একটি Interpreter তৈরি করা।
  3. ইনপুট টেনসর মান সেট করা হচ্ছে।
  4. invoking inferences.
  5. আউটপুট টেনসর মান।

অ্যান্ড্রয়েড (জাভা)

LiteRT এর সাথে অনুমান চালানোর জন্য Java API প্রাথমিকভাবে Android এর সাথে ব্যবহারের জন্য ডিজাইন করা হয়েছে, তাই এটি একটি Android লাইব্রেরি নির্ভরতা হিসাবে উপলব্ধ: com.google.ai.edge.litert

জাভাতে, আপনি একটি মডেল লোড করতে এবং ড্রাইভ মডেল অনুমান করতে Interpreter ক্লাস ব্যবহার করবেন। অনেক ক্ষেত্রে, এটি আপনার প্রয়োজন একমাত্র API হতে পারে।

আপনি FlatBuffers ( .tflite ) ফাইল ব্যবহার করে একটি Interpreter শুরু করতে পারেন:

public Interpreter(@NotNull File modelFile);

অথবা একটি MappedByteBuffer সঙ্গে:

public Interpreter(@NotNull MappedByteBuffer mappedByteBuffer);

উভয় ক্ষেত্রেই, আপনাকে অবশ্যই একটি বৈধ LiteRT মডেল প্রদান করতে হবে অথবা API থ্রো IllegalArgumentException . আপনি যদি একটি Interpreter শুরু করার জন্য MappedByteBuffer ব্যবহার করেন, তাহলে এটি অবশ্যই Interpreter সারাজীবনের জন্য অপরিবর্তিত থাকবে।

একটি মডেলে অনুমান চালানোর পছন্দের উপায় হল স্বাক্ষর ব্যবহার করা - Tensorflow 2.5 থেকে রূপান্তরিত মডেলগুলির জন্য উপলব্ধ

try (Interpreter interpreter = new Interpreter(file_of_tensorflowlite_model)) {
  Map<String, Object> inputs = new HashMap<>();
  inputs.put("input_1", input1);
  inputs.put("input_2", input2);
  Map<String, Object> outputs = new HashMap<>();
  outputs.put("output_1", output1);
  interpreter.runSignature(inputs, outputs, "mySignature");
}

runSignature পদ্ধতিতে তিনটি আর্গুমেন্ট লাগে:

  • ইনপুট : স্বাক্ষরে ইনপুট নাম থেকে ইনপুট অবজেক্টে ইনপুটগুলির জন্য মানচিত্র।

  • আউটপুট : স্বাক্ষরে আউটপুট নাম থেকে আউটপুট ডেটাতে আউটপুট ম্যাপিংয়ের জন্য মানচিত্র।

  • স্বাক্ষরের নাম (ঐচ্ছিক): স্বাক্ষরের নাম (মডেলের একক স্বাক্ষর থাকলে খালি রাখা যেতে পারে)।

মডেলের একটি সংজ্ঞায়িত স্বাক্ষর না থাকলে অনুমান চালানোর আরেকটি উপায়। শুধু Interpreter.run() কল করুন। যেমন:

try (Interpreter interpreter = new Interpreter(file_of_a_tensorflowlite_model)) {
  interpreter.run(input, output);
}

run() পদ্ধতি শুধুমাত্র একটি ইনপুট নেয় এবং শুধুমাত্র একটি আউটপুট প্রদান করে। সুতরাং আপনার মডেলের একাধিক ইনপুট বা একাধিক আউটপুট থাকলে, পরিবর্তে ব্যবহার করুন:

interpreter.runForMultipleInputsOutputs(inputs, map_of_indices_to_outputs);

এই ক্ষেত্রে, inputs প্রতিটি এন্ট্রি একটি ইনপুট টেনসরের সাথে মিলে যায় এবং map_of_indices_to_outputs ম্যাপ সূচকগুলি আউটপুট টেনসরের সংশ্লিষ্ট আউটপুট ডেটার সাথে।

উভয় ক্ষেত্রেই, টেনসর সূচকগুলি আপনি মডেল তৈরি করার সময় LiteRT রূপান্তরকারীকে যে মানগুলি দিয়েছিলেন তার সাথে সঙ্গতিপূর্ণ হওয়া উচিত। সচেতন থাকুন যে input টেনসরের ক্রম অবশ্যই LiteRT কনভার্টারে প্রদত্ত অর্ডারের সাথে মেলে।

Interpreter ক্লাস আপনার জন্য একটি অপারেশন নাম ব্যবহার করে যেকোন মডেল ইনপুট বা আউটপুটের সূচক পেতে সুবিধাজনক ফাংশন প্রদান করে:

public int getInputIndex(String opName);
public int getOutputIndex(String opName);

যদি opName মডেলে একটি বৈধ অপারেশন না হয়, তাহলে এটি একটি IllegalArgumentException নিক্ষেপ করে।

এছাড়াও সতর্ক থাকুন যে Interpreter সম্পদের মালিক। মেমরি লিক এড়াতে, সংস্থানগুলিকে ব্যবহার করার পরে ছেড়ে দিতে হবে:

interpreter.close();

জাভা সহ একটি উদাহরণ প্রকল্পের জন্য, Android অবজেক্ট সনাক্তকরণ উদাহরণ অ্যাপটি দেখুন।

সমর্থিত ডেটা প্রকার

LiteRT ব্যবহার করার জন্য, ইনপুট এবং আউটপুট টেনসরগুলির ডেটা প্রকারগুলি অবশ্যই নিম্নলিখিত আদিম প্রকারগুলির মধ্যে একটি হতে হবে:

  • float
  • int
  • long
  • byte

String প্রকারগুলিও সমর্থিত, তবে সেগুলি আদিম প্রকারের চেয়ে আলাদাভাবে এনকোড করা হয়৷ বিশেষ করে, একটি স্ট্রিং টেনসরের আকৃতি টেনসরের স্ট্রিংগুলির সংখ্যা এবং বিন্যাস নির্দেশ করে, প্রতিটি উপাদান নিজেই একটি পরিবর্তনশীল দৈর্ঘ্যের স্ট্রিং। এই অর্থে, টেনসরের (বাইট) আকার শুধুমাত্র আকৃতি এবং টাইপ থেকে গণনা করা যায় না, এবং ফলস্বরূপ স্ট্রিংগুলিকে একক, সমতল ByteBuffer আর্গুমেন্ট হিসাবে প্রদান করা যায় না।

যদি Integer এবং Float মতো বক্সযুক্ত প্রকারগুলি সহ অন্যান্য ডেটা প্রকারগুলি ব্যবহার করা হয়, তাহলে একটি IllegalArgumentException নিক্ষেপ করা হবে৷

ইনপুট

প্রতিটি ইনপুট সমর্থিত আদিম প্রকারের একটি অ্যারে বা মাল্টি-ডাইমেনশনাল অ্যারে বা উপযুক্ত আকারের একটি কাঁচা ByteBuffer হওয়া উচিত। যদি ইনপুট একটি অ্যারে বা মাল্টি-ডাইমেনশনাল অ্যারে হয়, তাহলে সংশ্লিষ্ট ইনপুট টেনসরটি অনুমান করার সময় অ্যারের মাত্রায় পরোক্ষভাবে আকার পরিবর্তন করা হবে। যদি ইনপুটটি একটি বাইটবাফার হয়, তাহলে অনুমান চালানোর আগে কলারের প্রথমে সংশ্লিষ্ট ইনপুট টেনসরের ( Interpreter.resizeInput() মাধ্যমে) ম্যানুয়ালি আকার পরিবর্তন করা উচিত।

ByteBuffer ব্যবহার করার সময়, সরাসরি বাইট বাফার ব্যবহার করতে পছন্দ করুন, কারণ এটি Interpreter অপ্রয়োজনীয় কপি এড়াতে দেয়। যদি ByteBuffer একটি সরাসরি বাইট বাফার হয়, তাহলে এর অর্ডার অবশ্যই ByteOrder.nativeOrder() হতে হবে। এটি একটি মডেল অনুমানের জন্য ব্যবহার করার পরে, মডেল অনুমান শেষ না হওয়া পর্যন্ত এটি অবশ্যই অপরিবর্তিত থাকবে।

আউটপুট

প্রতিটি আউটপুট সমর্থিত আদিম প্রকারের একটি অ্যারে বা মাল্টি-ডাইমেনশনাল অ্যারে বা উপযুক্ত আকারের বাইটবাফার হওয়া উচিত। উল্লেখ্য যে কিছু মডেলের গতিশীল আউটপুট রয়েছে, যেখানে আউটপুট টেনসরের আকার ইনপুটের উপর নির্ভর করে পরিবর্তিত হতে পারে। বিদ্যমান জাভা ইনফারেন্স API এর সাথে এটি পরিচালনা করার কোন সহজ উপায় নেই, তবে পরিকল্পিত এক্সটেনশনগুলি এটিকে সম্ভব করবে।

iOS (সুইফট)

সুইফট এপিআই Cocoapods থেকে TensorFlowLiteSwift Pod-এ উপলব্ধ।

প্রথমে আপনাকে TensorFlowLite মডিউল আমদানি করতে হবে।

import TensorFlowLite
// Getting model path
guard
  let modelPath = Bundle.main.path(forResource: "model", ofType: "tflite")
else {
  // Error handling...
}

do {
  // Initialize an interpreter with the model.
  let interpreter = try Interpreter(modelPath: modelPath)

  // Allocate memory for the model's input `Tensor`s.
  try interpreter.allocateTensors()

  let inputData: Data  // Should be initialized

  // input data preparation...

  // Copy the input data to the input `Tensor`.
  try self.interpreter.copy(inputData, toInputAt: 0)

  // Run inference by invoking the `Interpreter`.
  try self.interpreter.invoke()

  // Get the output `Tensor`
  let outputTensor = try self.interpreter.output(at: 0)

  // Copy output to `Data` to process the inference results.
  let outputSize = outputTensor.shape.dimensions.reduce(1, {x, y in x * y})
  let outputData =
        UnsafeMutableBufferPointer<Float32>.allocate(capacity: outputSize)
  outputTensor.data.copyBytes(to: outputData)

  if (error != nil) { /* Error handling... */ }
} catch error {
  // Error handling...
}

iOS (উদ্দেশ্য-সি)

অবজেক্টিভ-সি এপিআই Cocoapods থেকে LiteRTObjC পডে উপলব্ধ।

প্রথমে, আপনাকে TensorFlowLiteObjC মডিউল আমদানি করতে হবে।

@import TensorFlowLite;
NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model"
                                                      ofType:@"tflite"];
NSError *error;

// Initialize an interpreter with the model.
TFLInterpreter *interpreter = [[TFLInterpreter alloc] initWithModelPath:modelPath
                                                                  error:&error];
if (error != nil) { /* Error handling... */ }

// Allocate memory for the model's input `TFLTensor`s.
[interpreter allocateTensorsWithError:&error];
if (error != nil) { /* Error handling... */ }

NSMutableData *inputData;  // Should be initialized
// input data preparation...

// Get the input `TFLTensor`
TFLTensor *inputTensor = [interpreter inputTensorAtIndex:0 error:&error];
if (error != nil) { /* Error handling... */ }

// Copy the input data to the input `TFLTensor`.
[inputTensor copyData:inputData error:&error];
if (error != nil) { /* Error handling... */ }

// Run inference by invoking the `TFLInterpreter`.
[interpreter invokeWithError:&error];
if (error != nil) { /* Error handling... */ }

// Get the output `TFLTensor`
TFLTensor *outputTensor = [interpreter outputTensorAtIndex:0 error:&error];
if (error != nil) { /* Error handling... */ }

// Copy output to `NSData` to process the inference results.
NSData *outputData = [outputTensor dataWithError:&error];
if (error != nil) { /* Error handling... */ }

অবজেক্টিভ-সি কোডে C API

অবজেক্টিভ-সি এপিআই প্রতিনিধিদের সমর্থন করে না। উদ্দেশ্য-সি কোড সহ প্রতিনিধিদের ব্যবহার করার জন্য, আপনাকে সরাসরি অন্তর্নিহিত C API-কে কল করতে হবে।

#include "tensorflow/lite/c/c_api.h"
TfLiteModel* model = TfLiteModelCreateFromFile([modelPath UTF8String]);
TfLiteInterpreterOptions* options = TfLiteInterpreterOptionsCreate();

// Create the interpreter.
TfLiteInterpreter* interpreter = TfLiteInterpreterCreate(model, options);

// Allocate tensors and populate the input tensor data.
TfLiteInterpreterAllocateTensors(interpreter);
TfLiteTensor* input_tensor =
    TfLiteInterpreterGetInputTensor(interpreter, 0);
TfLiteTensorCopyFromBuffer(input_tensor, input.data(),
                           input.size() * sizeof(float));

// Execute inference.
TfLiteInterpreterInvoke(interpreter);

// Extract the output tensor data.
const TfLiteTensor* output_tensor =
    TfLiteInterpreterGetOutputTensor(interpreter, 0);
TfLiteTensorCopyToBuffer(output_tensor, output.data(),
                         output.size() * sizeof(float));

// Dispose of the model and interpreter objects.
TfLiteInterpreterDelete(interpreter);
TfLiteInterpreterOptionsDelete(options);
TfLiteModelDelete(model);

সি++

LiteRT এর সাথে অনুমান চালানোর জন্য C++ API Android, iOS এবং Linux প্ল্যাটফর্মের সাথে সামঞ্জস্যপূর্ণ। iOS-এ C++ API শুধুমাত্র বেজেল ব্যবহার করার সময় উপলব্ধ।

C++ এ, মডেলটি FlatBufferModel ক্লাসে সংরক্ষণ করা হয়। এটি একটি LiteRT মডেলকে এনক্যাপসুলেট করে এবং মডেলটি কোথায় সংরক্ষণ করা হয় তার উপর নির্ভর করে আপনি এটিকে কয়েকটি ভিন্ন উপায়ে তৈরি করতে পারেন:

class FlatBufferModel {
  // Build a model based on a file. Return a nullptr in case of failure.
  static std::unique_ptr<FlatBufferModel> BuildFromFile(
      const char* filename,
      ErrorReporter* error_reporter);

  // Build a model based on a pre-loaded flatbuffer. The caller retains
  // ownership of the buffer and should keep it alive until the returned object
  // is destroyed. Return a nullptr in case of failure.
  static std::unique_ptr<FlatBufferModel> BuildFromBuffer(
      const char* buffer,
      size_t buffer_size,
      ErrorReporter* error_reporter);
};

এখন যেহেতু আপনার কাছে মডেলটি একটি FlatBufferModel অবজেক্ট হিসাবে রয়েছে, আপনি এটিকে একটি Interpreter মাধ্যমে কার্যকর করতে পারেন। একটি একক FlatBufferModel একসাথে একাধিক Interpreter ব্যবহার করতে পারে৷

Interpreter API-এর গুরুত্বপূর্ণ অংশগুলি নীচের কোড স্নিপেটে দেখানো হয়েছে। এটা উল্লেখ করা উচিত যে:

  • স্ট্রিং তুলনা (এবং স্ট্রিং লাইব্রেরির উপর কোনো নির্দিষ্ট নির্ভরতা) এড়াতে টেনসরগুলিকে পূর্ণসংখ্যা দ্বারা প্রতিনিধিত্ব করা হয়।
  • সমবর্তী থ্রেড থেকে একটি দোভাষী অ্যাক্সেস করা উচিত নয়।
  • ইনপুট এবং আউটপুট টেনসরের জন্য মেমরি বরাদ্দ অবশ্যই টেনসরের আকার পরিবর্তন করার ঠিক পরেই AllocateTensors() কল করে ট্রিগার করা উচিত।

C++ এর সাথে LiteRT-এর সবচেয়ে সহজ ব্যবহার এইরকম দেখায়:

// Load the model
std::unique_ptr<tflite::FlatBufferModel> model =
    tflite::FlatBufferModel::BuildFromFile(filename);

// Build the interpreter
tflite::ops::builtin::BuiltinOpResolver resolver;
std::unique_ptr<tflite::Interpreter> interpreter;
tflite::InterpreterBuilder(*model, resolver)(&interpreter);

// Resize input tensors, if needed.
interpreter->AllocateTensors();

float* input = interpreter->typed_input_tensor<float>(0);
// Fill `input`.

interpreter->Invoke();

float* output = interpreter->typed_output_tensor<float>(0);

আরও উদাহরণ কোডের জন্য, minimal.cc এবং label_image.cc দেখুন।

পাইথন

অনুমান চালানোর জন্য পাইথন API একটি মডেল লোড করতে এবং অনুমান চালানোর জন্য Interpreter ব্যবহার করে।

LiteRT প্যাকেজ ইনস্টল করুন:

$ python3 -m pip install ai-edge-litert

LiteRT ইন্টারপ্রেটার আমদানি করুন

from ai_edge_litert.interpreter import Interpreter
Interpreter = Interpreter(model_path=args.model.file)

নিম্নলিখিত উদাহরণ দেখায় কিভাবে পাইথন ইন্টারপ্রেটার ব্যবহার করে একটি FlatBuffers ( .tflite ) ফাইল লোড করতে হয় এবং র‍্যান্ডম ইনপুট ডেটা সহ অনুমান চালাতে হয়:

আপনি যদি সংজ্ঞায়িত SignatureDef এর সাথে SavedModel থেকে রূপান্তর করছেন তবে এই উদাহরণটি সুপারিশ করা হয়।

class TestModel(tf.Module):
  def __init__(self):
    super(TestModel, self).__init__()

  @tf.function(input_signature=[tf.TensorSpec(shape=[1, 10], dtype=tf.float32)])
  def add(self, x):
    '''
    Simple method that accepts single input 'x' and returns 'x' + 4.
    '''
    # Name the output 'result' for convenience.
    return {'result' : x + 4}

SAVED_MODEL_PATH = 'content/saved_models/test_variable'
TFLITE_FILE_PATH = 'content/test_variable.tflite'

# Save the model
module = TestModel()
# You can omit the signatures argument and a default signature name will be
# created with name 'serving_default'.
tf.saved_model.save(
    module, SAVED_MODEL_PATH,
    signatures={'my_signature':module.add.get_concrete_function()})

# Convert the model using TFLiteConverter
converter = tf.lite.TFLiteConverter.from_saved_model(SAVED_MODEL_PATH)
tflite_model = converter.convert()
with open(TFLITE_FILE_PATH, 'wb') as f:
  f.write(tflite_model)

# Load the LiteRT model in LiteRT Interpreter
from ai_edge_litert.interpreter import Interpreter
interpreter = Interpreter(TFLITE_FILE_PATH)

# There is only 1 signature defined in the model,
# so it will return it by default.
# If there are multiple signatures then we can pass the name.
my_signature = interpreter.get_signature_runner()

# my_signature is callable with input as arguments.
output = my_signature(x=tf.constant([1.0], shape=(1,10), dtype=tf.float32))
# 'output' is dictionary with all outputs from the inference.
# In this case we have single output 'result'.
print(output['result'])

আরেকটি উদাহরণ যদি মডেলটিতে SignatureDefs সংজ্ঞায়িত না থাকে।

import numpy as np
import tensorflow as tf

# Load the LiteRT model and allocate tensors.
from ai_edge_litert.interpreter import Interpreter
interpreter = Interpreter(TFLITE_FILE_PATH)
interpreter.allocate_tensors()

# Get input and output tensors.
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()

# Test the model on random input data.
input_shape = input_details[0]['shape']
input_data = np.array(np.random.random_sample(input_shape), dtype=np.float32)
interpreter.set_tensor(input_details[0]['index'], input_data)

interpreter.invoke()

# The function `get_tensor()` returns a copy of the tensor data.
# Use `tensor()` in order to get a pointer to the tensor.
output_data = interpreter.get_tensor(output_details[0]['index'])
print(output_data)

মডেলটিকে একটি পূর্ব-রূপান্তরিত .tflite ফাইল হিসাবে লোড করার বিকল্প হিসাবে, আপনি আপনার কোডকে LiteRT কম্পাইলারের সাথে একত্রিত করতে পারেন, যার ফলে আপনি আপনার কেরাস মডেলটিকে LiteRT ফর্ম্যাটে রূপান্তর করতে পারবেন এবং তারপরে অনুমান চালাতে পারবেন:

import numpy as np
import tensorflow as tf

img = tf.keras.Input(shape=(64, 64, 3), name="img")
const = tf.constant([1., 2., 3.]) + tf.constant([1., 4., 4.])
val = img + const
out = tf.identity(val, name="out")

# Convert to LiteRT format
converter = tf.lite.TFLiteConverter.from_keras_model(tf.keras.models.Model(inputs=[img], outputs=[out]))
tflite_model = converter.convert()

# Load the LiteRT model and allocate tensors.
from ai_edge_litert.interpreter import Interpreter
interpreter = Interpreter(model_content=tflite_model)
interpreter.allocate_tensors()

# Continue to get tensors and so forth, as shown above...

আরো পাইথন নমুনা কোডের জন্য, label_image.py দেখুন।

গতিশীল আকৃতি মডেলের সাথে অনুমান চালান

আপনি যদি গতিশীল ইনপুট আকৃতি সহ একটি মডেল চালাতে চান, অনুমান চালানোর আগে ইনপুট আকারের আকার পরিবর্তন করুন। অন্যথায়, Tensorflow মডেলের None শেপ LiteRT মডেলে 1 -এর একটি স্থানধারক দ্বারা প্রতিস্থাপিত হবে।

নিম্নলিখিত উদাহরণগুলি বিভিন্ন ভাষায় অনুমান চালানোর আগে কীভাবে ইনপুট আকারের আকার পরিবর্তন করতে হয় তা দেখায়। সমস্ত উদাহরণ অনুমান করে যে ইনপুট আকৃতিটি [1/None, 10] হিসাবে সংজ্ঞায়িত করা হয়েছে, এবং এটিকে [3, 10] এ পুনরায় আকার দিতে হবে।

C++ উদাহরণ:

// Resize input tensors before allocate tensors
interpreter->ResizeInputTensor(/*tensor_index=*/0, std::vector<int>{3,10});
interpreter->AllocateTensors();

পাইথন উদাহরণ:

# Load the LiteRT model in LiteRT Interpreter
from ai_edge_litert.interpreter import Interpreter
interpreter = Interpreter(model_path=TFLITE_FILE_PATH)

# Resize input shape for dynamic shape model and allocate tensor
interpreter.resize_tensor_input(interpreter.get_input_details()[0]['index'], [3, 10])
interpreter.allocate_tensors()

# Get input and output tensors.
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()
,

এই নির্দেশিকা আপনাকে ইনপুট ডেটার উপর ভিত্তি করে ভবিষ্যদ্বাণী করার জন্য ডিভাইসে একটি LiteRT (Lite Runtime-এর জন্য সংক্ষিপ্ত) মডেল চালানোর প্রক্রিয়ার সাথে পরিচয় করিয়ে দেয়। এটি LiteRT ইন্টারপ্রেটারের সাহায্যে অর্জন করা হয়, যা ন্যূনতম লোড, প্রারম্ভিকতা এবং কার্যকর করার লেটেন্সি নিশ্চিত করতে একটি স্ট্যাটিক গ্রাফ অর্ডারিং এবং একটি কাস্টম (কম-ডাইনামিক) মেমরি বরাদ্দকারী ব্যবহার করে।

LiteRT অনুমান সাধারণত নিম্নলিখিত পদক্ষেপগুলি অনুসরণ করে:

  1. একটি মডেল লোড করা হচ্ছে : .tflite মডেলটিকে মেমরিতে লোড করুন, যার মধ্যে মডেলের এক্সিকিউশন গ্রাফ রয়েছে৷

  2. তথ্য রূপান্তর : প্রত্যাশিত বিন্যাস এবং মাত্রা ইনপুট তথ্য রূপান্তর. মডেলের জন্য কাঁচা ইনপুট ডেটা সাধারণত মডেল দ্বারা প্রত্যাশিত ইনপুট ডেটা বিন্যাসের সাথে মেলে না৷ উদাহরণস্বরূপ, মডেলের সাথে সামঞ্জস্যপূর্ণ হতে আপনাকে একটি চিত্রের আকার পরিবর্তন করতে বা চিত্র বিন্যাস পরিবর্তন করতে হতে পারে।

  3. চলমান অনুমান : ভবিষ্যদ্বাণী করতে LiteRT মডেলটি চালান। এই ধাপে মডেলটি চালানোর জন্য LiteRT API ব্যবহার করা জড়িত। এতে দোভাষী তৈরি করা এবং টেনসর বরাদ্দ করার মতো কয়েকটি ধাপ জড়িত।

  4. ইন্টারপ্রেটিং আউটপুট : আউটপুট টেনসরগুলিকে অর্থপূর্ণ উপায়ে ব্যাখ্যা করুন যা আপনার অ্যাপ্লিকেশনে কার্যকর। উদাহরণস্বরূপ, একটি মডেল শুধুমাত্র সম্ভাব্যতার একটি তালিকা দিতে পারে। প্রাসঙ্গিক বিভাগে সম্ভাব্যতা ম্যাপ করা এবং আউটপুট ফর্ম্যাট করা আপনার উপর নির্ভর করে।

এই নির্দেশিকা বর্ণনা করে কিভাবে LiteRT দোভাষী অ্যাক্সেস করতে হয় এবং C++, Java, এবং Python ব্যবহার করে একটি অনুমান সম্পাদন করতে হয়।

সমর্থিত প্ল্যাটফর্ম

টেনসরফ্লো ইনফারেন্স এপিআইগুলি বেশিরভাগ সাধারণ মোবাইল এবং এমবেডেড প্ল্যাটফর্মের জন্য প্রদান করা হয় যেমন Android , iOS এবং Linux , একাধিক প্রোগ্রামিং ভাষায়

বেশিরভাগ ক্ষেত্রে, API ডিজাইন ব্যবহারের সুবিধার চেয়ে কর্মক্ষমতার জন্য একটি অগ্রাধিকার প্রতিফলিত করে। LiteRT ছোট ডিভাইসে দ্রুত অনুমানের জন্য ডিজাইন করা হয়েছে, তাই APIs সুবিধার খরচে অপ্রয়োজনীয় অনুলিপিগুলি এড়ায়।

সমস্ত লাইব্রেরি জুড়ে, LiteRT API আপনাকে মডেল লোড করতে, ইনপুট ফিড করতে এবং অনুমান আউটপুট পুনরুদ্ধার করতে দেয়।

অ্যান্ড্রয়েড প্ল্যাটফর্ম

অ্যান্ড্রয়েডে, জাভা বা C++ API ব্যবহার করে LiteRT অনুমান করা যেতে পারে। Java APIs সুবিধা প্রদান করে এবং সরাসরি আপনার Android কার্যকলাপ ক্লাসের মধ্যে ব্যবহার করা যেতে পারে। C++ API গুলি আরও নমনীয়তা এবং গতি প্রদান করে, তবে Java এবং C++ স্তরগুলির মধ্যে ডেটা সরানোর জন্য JNI র‍্যাপার লেখার প্রয়োজন হতে পারে।

আরও তথ্যের জন্য C++ এবং Java বিভাগগুলি দেখুন, অথবা Android quickstart অনুসরণ করুন।

iOS প্ল্যাটফর্ম

iOS-এ, LiteRT সুইফট এবং অবজেক্টিভ-সি iOS লাইব্রেরিতে পাওয়া যায়। আপনি উদ্দেশ্য-সি কোডে সরাসরি C API ব্যবহার করতে পারেন।

Swift , Objective-C , এবং C API বিভাগগুলি দেখুন, অথবা iOS কুইকস্টার্ট অনুসরণ করুন।

লিনাক্স প্ল্যাটফর্ম

লিনাক্স প্ল্যাটফর্মে, আপনি C++ এ উপলব্ধ LiteRT API ব্যবহার করে অনুমান চালাতে পারেন।

একটি মডেল লোড করুন এবং চালান

একটি LiteRT মডেল লোড করা এবং চালানোর জন্য নিম্নলিখিত পদক্ষেপগুলি জড়িত:

  1. মেমরিতে মডেল লোড করা হচ্ছে।
  2. একটি বিদ্যমান মডেলের উপর ভিত্তি করে একটি Interpreter তৈরি করা।
  3. ইনপুট টেনসর মান সেট করা হচ্ছে।
  4. invoking inferences.
  5. আউটপুট টেনসর মান।

অ্যান্ড্রয়েড (জাভা)

LiteRT এর সাথে অনুমান চালানোর জন্য Java API প্রাথমিকভাবে Android এর সাথে ব্যবহারের জন্য ডিজাইন করা হয়েছে, তাই এটি একটি Android লাইব্রেরি নির্ভরতা হিসাবে উপলব্ধ: com.google.ai.edge.litert

জাভাতে, আপনি একটি মডেল লোড করতে এবং ড্রাইভ মডেল অনুমান করতে Interpreter ক্লাস ব্যবহার করবেন। অনেক ক্ষেত্রে, এটি আপনার প্রয়োজন একমাত্র API হতে পারে।

আপনি FlatBuffers ( .tflite ) ফাইল ব্যবহার করে একটি Interpreter শুরু করতে পারেন:

public Interpreter(@NotNull File modelFile);

অথবা একটি MappedByteBuffer সঙ্গে:

public Interpreter(@NotNull MappedByteBuffer mappedByteBuffer);

উভয় ক্ষেত্রেই, আপনাকে অবশ্যই একটি বৈধ LiteRT মডেল প্রদান করতে হবে অথবা API থ্রো IllegalArgumentException . আপনি যদি একটি Interpreter শুরু করার জন্য MappedByteBuffer ব্যবহার করেন, তাহলে এটি অবশ্যই Interpreter সারাজীবনের জন্য অপরিবর্তিত থাকবে।

একটি মডেলে অনুমান চালানোর পছন্দের উপায় হল স্বাক্ষর ব্যবহার করা - Tensorflow 2.5 থেকে রূপান্তরিত মডেলগুলির জন্য উপলব্ধ

try (Interpreter interpreter = new Interpreter(file_of_tensorflowlite_model)) {
  Map<String, Object> inputs = new HashMap<>();
  inputs.put("input_1", input1);
  inputs.put("input_2", input2);
  Map<String, Object> outputs = new HashMap<>();
  outputs.put("output_1", output1);
  interpreter.runSignature(inputs, outputs, "mySignature");
}

runSignature পদ্ধতিতে তিনটি আর্গুমেন্ট লাগে:

  • ইনপুট : স্বাক্ষরে ইনপুট নাম থেকে ইনপুট অবজেক্টে ইনপুটগুলির জন্য মানচিত্র।

  • আউটপুট : স্বাক্ষরে আউটপুট নাম থেকে আউটপুট ডেটাতে আউটপুট ম্যাপিংয়ের জন্য মানচিত্র।

  • স্বাক্ষরের নাম (ঐচ্ছিক): স্বাক্ষরের নাম (মডেলের একক স্বাক্ষর থাকলে খালি রাখা যেতে পারে)।

মডেলের একটি সংজ্ঞায়িত স্বাক্ষর না থাকলে অনুমান চালানোর আরেকটি উপায়। শুধু Interpreter.run() কল করুন। যেমন:

try (Interpreter interpreter = new Interpreter(file_of_a_tensorflowlite_model)) {
  interpreter.run(input, output);
}

run() পদ্ধতি শুধুমাত্র একটি ইনপুট নেয় এবং শুধুমাত্র একটি আউটপুট প্রদান করে। সুতরাং আপনার মডেলের একাধিক ইনপুট বা একাধিক আউটপুট থাকলে, পরিবর্তে ব্যবহার করুন:

interpreter.runForMultipleInputsOutputs(inputs, map_of_indices_to_outputs);

এই ক্ষেত্রে, inputs প্রতিটি এন্ট্রি একটি ইনপুট টেনসরের সাথে মিলে যায় এবং map_of_indices_to_outputs ম্যাপ সূচকগুলি আউটপুট টেনসরের সংশ্লিষ্ট আউটপুট ডেটার সাথে।

উভয় ক্ষেত্রেই, টেনসর সূচকগুলি আপনি মডেল তৈরি করার সময় LiteRT রূপান্তরকারীকে যে মানগুলি দিয়েছিলেন তার সাথে সঙ্গতিপূর্ণ হওয়া উচিত। সচেতন থাকুন যে input টেনসরের ক্রম অবশ্যই LiteRT কনভার্টারে প্রদত্ত অর্ডারের সাথে মেলে।

Interpreter ক্লাস আপনার জন্য একটি অপারেশন নাম ব্যবহার করে যেকোন মডেল ইনপুট বা আউটপুটের সূচক পেতে সুবিধাজনক ফাংশন প্রদান করে:

public int getInputIndex(String opName);
public int getOutputIndex(String opName);

যদি opName মডেলে একটি বৈধ অপারেশন না হয়, তাহলে এটি একটি IllegalArgumentException নিক্ষেপ করে।

এছাড়াও সতর্ক থাকুন যে Interpreter সম্পদের মালিক। মেমরি লিক এড়াতে, সংস্থানগুলিকে ব্যবহার করার পরে ছেড়ে দিতে হবে:

interpreter.close();

জাভা সহ একটি উদাহরণ প্রকল্পের জন্য, Android অবজেক্ট সনাক্তকরণ উদাহরণ অ্যাপটি দেখুন।

সমর্থিত ডেটা প্রকার

LiteRT ব্যবহার করার জন্য, ইনপুট এবং আউটপুট টেনসরগুলির ডেটা প্রকারগুলি অবশ্যই নিম্নলিখিত আদিম প্রকারগুলির মধ্যে একটি হতে হবে:

  • float
  • int
  • long
  • byte

String প্রকারগুলিও সমর্থিত, তবে সেগুলি আদিম প্রকারের চেয়ে আলাদাভাবে এনকোড করা হয়৷ বিশেষ করে, একটি স্ট্রিং টেনসরের আকৃতি টেনসরের স্ট্রিংগুলির সংখ্যা এবং বিন্যাস নির্দেশ করে, প্রতিটি উপাদান নিজেই একটি পরিবর্তনশীল দৈর্ঘ্যের স্ট্রিং। এই অর্থে, টেনসরের (বাইট) আকার শুধুমাত্র আকৃতি এবং টাইপ থেকে গণনা করা যায় না, এবং ফলস্বরূপ স্ট্রিংগুলিকে একক, সমতল ByteBuffer আর্গুমেন্ট হিসাবে প্রদান করা যায় না।

যদি Integer এবং Float মতো বক্সযুক্ত প্রকারগুলি সহ অন্যান্য ডেটা প্রকারগুলি ব্যবহার করা হয়, তাহলে একটি IllegalArgumentException নিক্ষেপ করা হবে৷

ইনপুট

প্রতিটি ইনপুট সমর্থিত আদিম প্রকারের একটি অ্যারে বা মাল্টি-ডাইমেনশনাল অ্যারে বা উপযুক্ত আকারের একটি কাঁচা ByteBuffer হওয়া উচিত। যদি ইনপুট একটি অ্যারে বা মাল্টি-ডাইমেনশনাল অ্যারে হয়, তাহলে সংশ্লিষ্ট ইনপুট টেনসরটি অনুমান করার সময় অ্যারের মাত্রায় পরোক্ষভাবে আকার পরিবর্তন করা হবে। যদি ইনপুটটি একটি বাইটবাফার হয়, তাহলে অনুমান চালানোর আগে কলারের প্রথমে সংশ্লিষ্ট ইনপুট টেনসরের ( Interpreter.resizeInput() মাধ্যমে) ম্যানুয়ালি আকার পরিবর্তন করা উচিত।

ByteBuffer ব্যবহার করার সময়, সরাসরি বাইট বাফার ব্যবহার করতে পছন্দ করুন, কারণ এটি Interpreter অপ্রয়োজনীয় কপি এড়াতে দেয়। যদি ByteBuffer একটি সরাসরি বাইট বাফার হয়, তাহলে এর অর্ডার অবশ্যই ByteOrder.nativeOrder() হতে হবে। এটি একটি মডেল অনুমানের জন্য ব্যবহার করার পরে, মডেল অনুমান শেষ না হওয়া পর্যন্ত এটি অবশ্যই অপরিবর্তিত থাকবে।

আউটপুট

প্রতিটি আউটপুট সমর্থিত আদিম প্রকারের একটি অ্যারে বা মাল্টি-ডাইমেনশনাল অ্যারে বা উপযুক্ত আকারের বাইটবাফার হওয়া উচিত। উল্লেখ্য যে কিছু মডেলের গতিশীল আউটপুট রয়েছে, যেখানে আউটপুট টেনসরের আকার ইনপুটের উপর নির্ভর করে পরিবর্তিত হতে পারে। বিদ্যমান জাভা ইনফারেন্স API এর সাথে এটি পরিচালনা করার কোন সহজ উপায় নেই, তবে পরিকল্পিত এক্সটেনশনগুলি এটিকে সম্ভব করবে।

iOS (সুইফট)

সুইফট এপিআই Cocoapods থেকে TensorFlowLiteSwift Pod-এ উপলব্ধ।

প্রথমে আপনাকে TensorFlowLite মডিউল আমদানি করতে হবে।

import TensorFlowLite
// Getting model path
guard
  let modelPath = Bundle.main.path(forResource: "model", ofType: "tflite")
else {
  // Error handling...
}

do {
  // Initialize an interpreter with the model.
  let interpreter = try Interpreter(modelPath: modelPath)

  // Allocate memory for the model's input `Tensor`s.
  try interpreter.allocateTensors()

  let inputData: Data  // Should be initialized

  // input data preparation...

  // Copy the input data to the input `Tensor`.
  try self.interpreter.copy(inputData, toInputAt: 0)

  // Run inference by invoking the `Interpreter`.
  try self.interpreter.invoke()

  // Get the output `Tensor`
  let outputTensor = try self.interpreter.output(at: 0)

  // Copy output to `Data` to process the inference results.
  let outputSize = outputTensor.shape.dimensions.reduce(1, {x, y in x * y})
  let outputData =
        UnsafeMutableBufferPointer<Float32>.allocate(capacity: outputSize)
  outputTensor.data.copyBytes(to: outputData)

  if (error != nil) { /* Error handling... */ }
} catch error {
  // Error handling...
}

iOS (উদ্দেশ্য-সি)

অবজেক্টিভ-সি এপিআই Cocoapods থেকে LiteRTObjC পডে উপলব্ধ।

প্রথমে, আপনাকে TensorFlowLiteObjC মডিউল আমদানি করতে হবে।

@import TensorFlowLite;
NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model"
                                                      ofType:@"tflite"];
NSError *error;

// Initialize an interpreter with the model.
TFLInterpreter *interpreter = [[TFLInterpreter alloc] initWithModelPath:modelPath
                                                                  error:&error];
if (error != nil) { /* Error handling... */ }

// Allocate memory for the model's input `TFLTensor`s.
[interpreter allocateTensorsWithError:&error];
if (error != nil) { /* Error handling... */ }

NSMutableData *inputData;  // Should be initialized
// input data preparation...

// Get the input `TFLTensor`
TFLTensor *inputTensor = [interpreter inputTensorAtIndex:0 error:&error];
if (error != nil) { /* Error handling... */ }

// Copy the input data to the input `TFLTensor`.
[inputTensor copyData:inputData error:&error];
if (error != nil) { /* Error handling... */ }

// Run inference by invoking the `TFLInterpreter`.
[interpreter invokeWithError:&error];
if (error != nil) { /* Error handling... */ }

// Get the output `TFLTensor`
TFLTensor *outputTensor = [interpreter outputTensorAtIndex:0 error:&error];
if (error != nil) { /* Error handling... */ }

// Copy output to `NSData` to process the inference results.
NSData *outputData = [outputTensor dataWithError:&error];
if (error != nil) { /* Error handling... */ }

অবজেক্টিভ-সি কোডে C API

অবজেক্টিভ-সি এপিআই প্রতিনিধিদের সমর্থন করে না। উদ্দেশ্য-সি কোড সহ প্রতিনিধিদের ব্যবহার করার জন্য, আপনাকে সরাসরি অন্তর্নিহিত C API-কে কল করতে হবে।

#include "tensorflow/lite/c/c_api.h"
TfLiteModel* model = TfLiteModelCreateFromFile([modelPath UTF8String]);
TfLiteInterpreterOptions* options = TfLiteInterpreterOptionsCreate();

// Create the interpreter.
TfLiteInterpreter* interpreter = TfLiteInterpreterCreate(model, options);

// Allocate tensors and populate the input tensor data.
TfLiteInterpreterAllocateTensors(interpreter);
TfLiteTensor* input_tensor =
    TfLiteInterpreterGetInputTensor(interpreter, 0);
TfLiteTensorCopyFromBuffer(input_tensor, input.data(),
                           input.size() * sizeof(float));

// Execute inference.
TfLiteInterpreterInvoke(interpreter);

// Extract the output tensor data.
const TfLiteTensor* output_tensor =
    TfLiteInterpreterGetOutputTensor(interpreter, 0);
TfLiteTensorCopyToBuffer(output_tensor, output.data(),
                         output.size() * sizeof(float));

// Dispose of the model and interpreter objects.
TfLiteInterpreterDelete(interpreter);
TfLiteInterpreterOptionsDelete(options);
TfLiteModelDelete(model);

সি++

LiteRT এর সাথে অনুমান চালানোর জন্য C++ API Android, iOS এবং Linux প্ল্যাটফর্মের সাথে সামঞ্জস্যপূর্ণ। iOS-এ C++ API শুধুমাত্র বেজেল ব্যবহার করার সময় উপলব্ধ।

C++ এ, মডেলটি FlatBufferModel ক্লাসে সংরক্ষণ করা হয়। এটি একটি LiteRT মডেলকে এনক্যাপসুলেট করে এবং মডেলটি কোথায় সংরক্ষণ করা হয় তার উপর নির্ভর করে আপনি এটিকে কয়েকটি ভিন্ন উপায়ে তৈরি করতে পারেন:

class FlatBufferModel {
  // Build a model based on a file. Return a nullptr in case of failure.
  static std::unique_ptr<FlatBufferModel> BuildFromFile(
      const char* filename,
      ErrorReporter* error_reporter);

  // Build a model based on a pre-loaded flatbuffer. The caller retains
  // ownership of the buffer and should keep it alive until the returned object
  // is destroyed. Return a nullptr in case of failure.
  static std::unique_ptr<FlatBufferModel> BuildFromBuffer(
      const char* buffer,
      size_t buffer_size,
      ErrorReporter* error_reporter);
};

এখন যেহেতু আপনার কাছে মডেলটি একটি FlatBufferModel অবজেক্ট হিসাবে রয়েছে, আপনি এটিকে একটি Interpreter মাধ্যমে কার্যকর করতে পারেন। একটি একক FlatBufferModel একসাথে একাধিক Interpreter ব্যবহার করতে পারে৷

Interpreter API-এর গুরুত্বপূর্ণ অংশগুলি নীচের কোড স্নিপেটে দেখানো হয়েছে। এটা উল্লেখ করা উচিত যে:

  • স্ট্রিং তুলনা (এবং স্ট্রিং লাইব্রেরির উপর কোনো নির্দিষ্ট নির্ভরতা) এড়াতে টেনসরগুলিকে পূর্ণসংখ্যা দ্বারা প্রতিনিধিত্ব করা হয়।
  • সমবর্তী থ্রেড থেকে একটি দোভাষী অ্যাক্সেস করা উচিত নয়।
  • ইনপুট এবং আউটপুট টেনসরের জন্য মেমরি বরাদ্দ অবশ্যই টেনসরের আকার পরিবর্তন করার ঠিক পরেই AllocateTensors() কল করে ট্রিগার করা উচিত।

C++ এর সাথে LiteRT-এর সবচেয়ে সহজ ব্যবহার এইরকম দেখায়:

// Load the model
std::unique_ptr<tflite::FlatBufferModel> model =
    tflite::FlatBufferModel::BuildFromFile(filename);

// Build the interpreter
tflite::ops::builtin::BuiltinOpResolver resolver;
std::unique_ptr<tflite::Interpreter> interpreter;
tflite::InterpreterBuilder(*model, resolver)(&interpreter);

// Resize input tensors, if needed.
interpreter->AllocateTensors();

float* input = interpreter->typed_input_tensor<float>(0);
// Fill `input`.

interpreter->Invoke();

float* output = interpreter->typed_output_tensor<float>(0);

আরও উদাহরণ কোডের জন্য, minimal.cc এবং label_image.cc দেখুন।

পাইথন

অনুমান চালানোর জন্য পাইথন API একটি মডেল লোড করতে এবং অনুমান চালানোর জন্য Interpreter ব্যবহার করে।

LiteRT প্যাকেজ ইনস্টল করুন:

$ python3 -m pip install ai-edge-litert

LiteRT ইন্টারপ্রেটার আমদানি করুন

from ai_edge_litert.interpreter import Interpreter
Interpreter = Interpreter(model_path=args.model.file)

নিম্নলিখিত উদাহরণ দেখায় কিভাবে পাইথন ইন্টারপ্রেটার ব্যবহার করে একটি FlatBuffers ( .tflite ) ফাইল লোড করতে হয় এবং র‍্যান্ডম ইনপুট ডেটা সহ অনুমান চালাতে হয়:

আপনি যদি সংজ্ঞায়িত SignatureDef এর সাথে SavedModel থেকে রূপান্তর করছেন তবে এই উদাহরণটি সুপারিশ করা হয়।

class TestModel(tf.Module):
  def __init__(self):
    super(TestModel, self).__init__()

  @tf.function(input_signature=[tf.TensorSpec(shape=[1, 10], dtype=tf.float32)])
  def add(self, x):
    '''
    Simple method that accepts single input 'x' and returns 'x' + 4.
    '''
    # Name the output 'result' for convenience.
    return {'result' : x + 4}

SAVED_MODEL_PATH = 'content/saved_models/test_variable'
TFLITE_FILE_PATH = 'content/test_variable.tflite'

# Save the model
module = TestModel()
# You can omit the signatures argument and a default signature name will be
# created with name 'serving_default'.
tf.saved_model.save(
    module, SAVED_MODEL_PATH,
    signatures={'my_signature':module.add.get_concrete_function()})

# Convert the model using TFLiteConverter
converter = tf.lite.TFLiteConverter.from_saved_model(SAVED_MODEL_PATH)
tflite_model = converter.convert()
with open(TFLITE_FILE_PATH, 'wb') as f:
  f.write(tflite_model)

# Load the LiteRT model in LiteRT Interpreter
from ai_edge_litert.interpreter import Interpreter
interpreter = Interpreter(TFLITE_FILE_PATH)

# There is only 1 signature defined in the model,
# so it will return it by default.
# If there are multiple signatures then we can pass the name.
my_signature = interpreter.get_signature_runner()

# my_signature is callable with input as arguments.
output = my_signature(x=tf.constant([1.0], shape=(1,10), dtype=tf.float32))
# 'output' is dictionary with all outputs from the inference.
# In this case we have single output 'result'.
print(output['result'])

আরেকটি উদাহরণ যদি মডেলটিতে SignatureDefs সংজ্ঞায়িত না থাকে।

import numpy as np
import tensorflow as tf

# Load the LiteRT model and allocate tensors.
from ai_edge_litert.interpreter import Interpreter
interpreter = Interpreter(TFLITE_FILE_PATH)
interpreter.allocate_tensors()

# Get input and output tensors.
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()

# Test the model on random input data.
input_shape = input_details[0]['shape']
input_data = np.array(np.random.random_sample(input_shape), dtype=np.float32)
interpreter.set_tensor(input_details[0]['index'], input_data)

interpreter.invoke()

# The function `get_tensor()` returns a copy of the tensor data.
# Use `tensor()` in order to get a pointer to the tensor.
output_data = interpreter.get_tensor(output_details[0]['index'])
print(output_data)

মডেলটিকে একটি পূর্ব-রূপান্তরিত .tflite ফাইল হিসাবে লোড করার বিকল্প হিসাবে, আপনি আপনার কোডকে LiteRT কম্পাইলারের সাথে একত্রিত করতে পারেন, যার ফলে আপনি আপনার কেরাস মডেলটিকে LiteRT ফর্ম্যাটে রূপান্তর করতে পারবেন এবং তারপরে অনুমান চালাতে পারবেন:

import numpy as np
import tensorflow as tf

img = tf.keras.Input(shape=(64, 64, 3), name="img")
const = tf.constant([1., 2., 3.]) + tf.constant([1., 4., 4.])
val = img + const
out = tf.identity(val, name="out")

# Convert to LiteRT format
converter = tf.lite.TFLiteConverter.from_keras_model(tf.keras.models.Model(inputs=[img], outputs=[out]))
tflite_model = converter.convert()

# Load the LiteRT model and allocate tensors.
from ai_edge_litert.interpreter import Interpreter
interpreter = Interpreter(model_content=tflite_model)
interpreter.allocate_tensors()

# Continue to get tensors and so forth, as shown above...

আরো পাইথন নমুনা কোডের জন্য, label_image.py দেখুন।

গতিশীল আকৃতি মডেলের সাথে অনুমান চালান

আপনি যদি গতিশীল ইনপুট আকৃতি সহ একটি মডেল চালাতে চান, অনুমান চালানোর আগে ইনপুট আকারের আকার পরিবর্তন করুন। অন্যথায়, Tensorflow মডেলের None শেপ LiteRT মডেলে 1 -এর একটি স্থানধারক দ্বারা প্রতিস্থাপিত হবে।

নিম্নলিখিত উদাহরণগুলি বিভিন্ন ভাষায় অনুমান চালানোর আগে কীভাবে ইনপুট আকারের আকার পরিবর্তন করতে হয় তা দেখায়। সমস্ত উদাহরণ অনুমান করে যে ইনপুট আকৃতিটি [1/None, 10] হিসাবে সংজ্ঞায়িত করা হয়েছে, এবং এটিকে [3, 10] এ পুনরায় আকার দিতে হবে।

C++ উদাহরণ:

// Resize input tensors before allocate tensors
interpreter->ResizeInputTensor(/*tensor_index=*/0, std::vector<int>{3,10});
interpreter->AllocateTensors();

পাইথন উদাহরণ:

# Load the LiteRT model in LiteRT Interpreter
from ai_edge_litert.interpreter import Interpreter
interpreter = Interpreter(model_path=TFLITE_FILE_PATH)

# Resize input shape for dynamic shape model and allocate tensor
interpreter.resize_tensor_input(interpreter.get_input_details()[0]['index'], [3, 10])
interpreter.allocate_tensors()

# Get input and output tensors.
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()