টেনসরফ্লো লাইট – অ্যান্ড্রয়েড ডিভাইসে মেশিন লার্নিং মডেল ডিপ্লয় করা

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

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

মেশিন লার্নিং মডেল কিভাবে মোবাইলে রান করা যায়, তার উদাহরণটি গিট থেকে ক্লোন বা ডাউনলোড করে নিব। তার জন্য টার্মিনাল বা কমান্ডলাইনে গিয়ে লিখবঃ

git clone https://github.com/tensorflow/examples.git 

অনেক গুলো প্রজেক্ট রয়েছে এখানে। আমরা শুধু মাত্র অ্যান্ড্রয়েড প্রজেক্টটা ব্যবহার করব।

এর জন্য অ্যান্ড্রয়েড স্টুডিও ওপেন করে নিব। অ্যান্ড্রয়েড অ্যাপ ডেভেলপমেন্ট সম্পর্কে আইডিয়া না থাকলে তা এই পেইজ থেকে শেখা যাবে।

অ্যান্ড্রয়েড স্টুডিও ওপেন করার পর File > New > Import Project এ ক্লিক করতে হবে। এরপর ক্লোন করা উদাহরণ গুলো থেকে examples > lite > examples > object_detection > android_play_services প্রজেক্টটা সিলেক্ট করতে হবে।

এরপর অ্যান্ড্রয়েড স্টুডিওতে প্রজেক্টটি ওপেন হবে। এই প্রজেক্টের জন্য প্রয়োজনীয় ফাইল গুলো গ্র্যাডেল অটোমেটিক ডাউনলোড করে নিবে। এমনকি টেনসরফ্লো লাইট মডেলও। টেনসরফ্লো মডেল গুলো দেখা যাবে assets ফোল্ডারে।

গ্র্যাডেল রান কমপ্লিট হলে আমরা প্রজেক্টটি রান করতে পারব। এই প্রজেক্ট রিয়েল ডিভাইসে রান করতে হবে। রান করলে শুরুতে ক্যামেরা ব্যবহারের অনুমতি চাইবে। অনুমতি দেওয়ার পর মডেল প্রিপারেশন নিতে হয়তো কিছু সময় লাগবে। এরপর ক্যামেরা ভিউ ওপেন হবে। ক্যামেরা কোন একটা অবজেক্টের দিকে তাক করলে ঐ অবজেক্ট ডিটেক্ট করবে। ইন্টারেস্টিং না? কত সহজেই আমরা একটা মেশিন লার্নিং অ্যাপ তৈরি করে ফেললাম! কোড গুলো দেখলে বুঝব খুব একটা কমপ্লিকেশনও না। প্রতিটা কোডের কোন অংশ কিসের কাজ করছে, তা কমেন্ট আকারে বিস্তারিত লেখা আছে।

উপরের উদাহরণটা গুগলের অফিশিয়াল উদাহরণ। TensorFlow Lite Quickstart for Android পেইজে আরো বিস্তারিত জানা যাবে।

শুরু থেকে অ্যান্ড্রয়েড ডিভাইসে মেশিন লার্নিং মডেল ডিপ্লয় করা

এবার আমরা একেবারে শুরু থেকে কিভাবে টেনসরফ্লো লাইট ব্যবহার করে একটা অ্যাপ তৈরি করা যায়, তা শিখব। এর আগে কিভাবে টেনসরফ্লো নিয়ে কাজ করা যায়, সে সম্পর্কে আইডিয়া থাকলে বুঝতে সুবিধা হবে। এই লেখাটি দেখতে পারেনঃ টেনসরফ্লো ব্যবহার করে নিউরাল নেটওয়ার্ক ট্রেনিং এবং প্রিডিকশন

সবার আগে আমাদের একটা টেনসরফ্লো মডেল লাগবে। যেমন খুব সিম্পল একটা উদাহরণ দিয়েই শুরু করিঃ

import tensorflow as tf
import numpy as np
import keras
from keras import layers
# training data 
celsius    = np.array([-40, -10,  0,  8, 15, 22,  38],  dtype=float)
fahrenheit = np.array([-40,  14, 32, 46.4, 59, 71.6, 100.4],  dtype=float)
 
 
# model creation
model = keras.Sequential([
layers.Dense(units=1, input_shape=[1])
])
 
# model compilation 
model.compile(loss='mean_squared_error',
              optimizer=tf.keras.optimizers.Adam(0.1))
# model training 
model.fit(celsius, fahrenheit, epochs=500, verbose=False)
print("Finished training the model")
 
# predict
print(model.predict([100.0]))

এই মডেল এখন টেনসরফ্লো লাইটে কনভার্ট করতে হবে। কনভার্ট করা সহজঃ

# convert TF model into TFLite model
converter = tf.lite.TFLiteConverter.from_keras_model(model=model)

tfmodel = converter.convert()

# Save TFLite model into a .tflite file 

open("output_model.tflite","wb").write(tfmodel)

উপরের প্রজেকটা আমরা চাইলে গুগল কোল্যাবে রান করে output_model.tflite ডাউনলোড করে নিতে পারি। এই output_model.tflite মডেলটি আমরা অ্যান্ড্রয়েড অ্যাপে ব্যবহার করব।

আপনার কম্পিউটারে টেনসরফ্লো এনভারনমেন্ট ইন্সটল করা থাকলে কম্পিউটারেও tflite ফাইল জেনারেট করে নিতে পারেনঃ

import tensorflow as tf
import numpy as np
import keras
from keras import layers
# training data
celsius    = np.array([-40, -10,  0,  8, 15, 22,  38],  dtype=float)
fahrenheit = np.array([-40,  14, 32, 46.4, 59, 71.6, 100.4],  dtype=float)


# model creation
model = keras.Sequential([
layers.Dense(units=1, input_shape=[1])
])

# model compilation
model.compile(loss='mean_squared_error',
              optimizer=tf.keras.optimizers.Adam(0.1))
# model training
model.fit(celsius, fahrenheit, epochs=500, verbose=False)
print("Finished training the model")

# predict
print(model.predict([100.0]))

# convert TF model into TFLite model
converter = tf.lite.TFLiteConverter.from_keras_model(model=model)

tfmodel = converter.convert()

# Save TFLite model into a .tflite file

open("output_model.tflite","wb").write(tfmodel)

অ্যান্ড্রয়েড অ্যাপ তৈরি

অ্যান্ড্রয়েড স্টুডিওতে গিয়ে একটা Empty Views Activity অ্যাপ তৈরি করব। ল্যাঙ্গুয়েজ হিসেবে Java সিলেক্ট করব।

প্রজেক্টটি অ্যান্ড্রয়েড স্টুডিওতে ওপেন হলে assets ফোল্ডার তৈরি করে নিব। এই ফোল্ডারে output_model.tflite ফাইলটি কপি করব।

ডিপেন্ডেন্সিতে টেনসরফ্লো যুক্ত করতে হবে। অ্যাপ লেভেলের build.gradle এ dependencies এর মধ্যে টেনসরফ্লো যুক্ত করবঃ

implementation 'org.tensorflow:tensorflow-lite:+'

মেশিন লার্নিং এর যে মডেল নিয়ে কাজ করছি, সেখানে সেলসিয়াস হিসেবে একটা ভ্যালু ইনপুট দিলে তা ফারেনহাইটে কত হবে, তা বলে দেয়। আর তাই ইউজার থেকে ইউনপুট নেওয়ার জন্য একটা এডিট টেক্সট, আউপুটের জন্য টেক্সট ভিউ এবং একটা বাটন লাগবে। যার activity_main.xml লেয়াউট ফাইলটি এভাবে লিখতে পারিঃ

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:gravity="center"
    android:orientation="vertical" >


    <TextView
        android:id="@+id/tv_output"
        android:layout_gravity="center"
        android:textSize="20dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
    <EditText
        android:id="@+id/et_input"
        android:layout_gravity="center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="Enter celsius value"
        android:inputType="textPersonName" />



    <Button
        android:id="@+id/btn_predict"
        android:layout_gravity="center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"

        android:text="Predict"
     />
</LinearLayout>

টেনসরফ্লো লাইট মডেল প্রজেক্টে লোড করাঃ
টেনসরফ্লো লাইট মডেল ফাইল প্রজেক্টে লোড করার জন্য নিচের কোড MainActivity.java ফাইলে যুক্ত করবঃ

private MappedByteBuffer loadModelFile() throws IOException {
    AssetFileDescriptor fileDescriptor=this.getAssets().openFd("output_model.tflite");
    FileInputStream inputStream=new FileInputStream(fileDescriptor.getFileDescriptor());
    FileChannel fileChannel=inputStream.getChannel();
    long startOffset=fileDescriptor.getStartOffset();
    long declareLength=fileDescriptor.getDeclaredLength();
    return fileChannel.map(FileChannel.MapMode.READ_ONLY,startOffset,declareLength);
}

প্রিডিকশন

প্রিডিকশনের টেনসরফ্লো ভার্সন হচ্ছে tflite.run()। আর ইনপুট হিসেবে দিতে হবে ফ্লোট ভ্যালু। আমরা যখন ইউজার থেকে ইনপুট নেই, তখন তা মূলত স্ট্রিং হিসেবে ইনপুট নেয়। এই স্ট্রিংকে ফ্লোটে কভার্ট করে নিতে হবে। এরপর এই ভ্যালু দিয়ে tflite রান করলে আউটপুটটা রিটার্ণ করার জন্য একটা মেথড লিখতে পারি এভাবেঃ

private float doPredict(String inputString) {
    float[] inputVal=new float[1];
    inputVal[0]=Float.parseFloat(inputString);
    float[][] output=new float[1][1];
    tflite.run(inputVal,output);
    return output[0][0];
}

ইনপুট ভ্যালু থেকে প্রিডিকশনের জন্য TFLite Interpretter ইম্পোর্ট করে নিতে হবেঃ

import org.tensorflow.lite.Interpreter;

সম্পূর্ণ MainActivity.java:

import android.content.res.AssetFileDescriptor;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import org.tensorflow.lite.Interpreter;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

public class MainActivity extends AppCompatActivity {

    Interpreter tflite;
    EditText input;
    TextView output;
    Button predict;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        predict =findViewById(R.id.btn_predict);
        output =findViewById(R.id.tv_output);
        input =findViewById(R.id.et_input);

        try {
            tflite = new Interpreter(loadModelFile());
        }catch (Exception ex){
            ex.printStackTrace();
        }
        predict.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                float prediction= doPredict(input.getText().toString());
                System.out.println(prediction);
                output.setText(Float.toString(prediction));
            }
        });

    }
    private MappedByteBuffer loadModelFile() throws IOException {
        AssetFileDescriptor fileDescriptor=this.getAssets().openFd("output_model.tflite");
        FileInputStream inputStream=new FileInputStream(fileDescriptor.getFileDescriptor());
        FileChannel fileChannel=inputStream.getChannel();
        long startOffset=fileDescriptor.getStartOffset();
        long declareLength=fileDescriptor.getDeclaredLength();
        return fileChannel.map(FileChannel.MapMode.READ_ONLY,startOffset,declareLength);
    }
    private float doPredict(String inputString) {
        float[] inputVal=new float[1];
        inputVal[0]=Float.parseFloat(inputString);
        float[][] output=new float[1][1];
        tflite.run(inputVal,output);
        return output[0][0];
    }


}

প্রজেক্টটি রান করার পর ইনপুট হিসেবে একটা সেলসিয়াস ভ্যালু দিলে আউটপুট হিসেবে ফারেনহাইট ভ্যালু কত, তা বলে দিবে।

এই প্রজেক্টটা খুব সিম্পল হলেও মূলত একটা মেশিন লার্নিং প্রজেক্ট কিভাবে মোবাইল ডিভাইসে ডিপ্লয় করা যায়, তার প্রতিটা ধাপ রয়েছে। আমরা চাইলে সরাসরি যে কোন প্রি বিল্ড সেভ মডেলও ব্যবহার কতে পারি। তার জন্য টেনসরফ্লো মডেলকে TFLite মডেলে কভার্ট করে নিতে হবে। যা করা যাবে এভাবেঃ

import tensorflow as tf

# Convert the model
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) # path to the SavedModel directory
tflite_model = converter.convert()

# Save the model.
with open('model.tflite', 'wb') as f:
  f.write(tflite_model)

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

গিটহাব থেকে প্রজেক্টটা ডাউনলোড করে নেওয়া যাবে।

Leave a Reply