টেনসরফ্লো ব্যবহার করে ট্রান্সফার লার্নিং

ট্রান্সফার লার্নিং

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

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

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

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

প্রি-ট্রেইন্ড মডেল

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

ট্রান্সফার লার্নিং এর জন্য অনেক গুলো প্রি ট্রেইন্ড মডেল রয়েছে। যেমন ইমেজের জন্য VGG19, Inceptionv3 (GoogLeNet), ResNet50, EfficientNet ইত্যাদি। ন্যাচারাল ল্যাঙ্গুয়েজ প্রসেসিং এর জন্য Google’s BERT, Microsoft’s CodeBERT, OpenAI’s GPT-3 ইত্যাদি। এগুলো ছাড়াও আরো অনেক গুলো প্রি ট্রেইন্ড মডেল রয়েছে নিজের প্রজেক্টের জন্য কোন মডেলটি উপযুক্ত, তা একটু খুঁজে নিতে হবে।

টেনসর ফ্লো হাব

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

প্রিট্রেইন্ড মডেল নিজের প্রজেক্টে ব্যবহার

প্রিট্রেইন্ড মডেল দুই ভাবে ব্যবহার করা যায়।

  1. কোন মডিফিকেশন ছাড়া যেভাবে রয়েছে, ঠিক সে ভাবে ব্যবহার করা।
  2. নিজেদের প্রয়োজন অনুযায়ী মডিফিকেশন করে ব্যবহার করা।

 

১) প্রিট্রেইন্ড মডেল মডিফিকেশন ছাড়া ব্যবহার করা

 

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

model = tf.keras.Sequential([
hub.KerasLayer("https://tfhub.dev/google/tf2-preview/mobilenet_v2/classification/4", output_shape=[1001])
])

বলা যায় এতটুকুতেই  কাজ শেষ। এবার আমরা যে কোন ইমেজ প্রিডিক্ট করতে পারব। তার জন্য প্রথমে একটা ইমেজ ডাউনলোড করে নিব। Mobilenet এ ইনপুট হিসেবে 224*224 পিক্সেল ইমেজ দিতে হয়। তাই ডাউনলোডকৃত ইমেজকে রিসাইজ করে নিতে হবে। এবং এরপর ইমেজটিকে নরমালাইজ করে নিতে হবে।

IMAGE_RES = 224

predict_img = tf.keras.utils.get_file('image.jpg','https://upload.wikimedia.org/wikipedia/commons/thumb/4/43/AD2009Aug07_Natrix_natrix_01.jpg/640px-AD2009Aug07_Natrix_natrix_01.jpg')
predict_img = Image.open(predict_img).resize((IMAGE_RES, IMAGE_RES))
predict_img

predict_img = np.array(predict_img)/255.0 # data normalization
predict_img.shape

এবার ইমেজটি প্রিডিক্ট করার জন্য প্রস্তুত। টেন্সরফ্লো মডেল ইনপুট হিসেবে ব্যাচ ইমেজ নেয়, তাই সিঙ্গেল ইমেজকে ব্যাচ ইমেজে কনভার্ট করে নিতে হবে। তা করতে পারি এভাবেঃ

result = model.predict(predict_img[np.newaxis, ...])
result.shape

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

predicted_class = np.argmax(result[0], axis=-1)
predicted_class

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

# get level name from prediction

labels_path = tf.keras.utils.get_file('ImageNetLabels.txt','https://storage.googleapis.com/download.tensorflow.org/data/ImageNetLabels.txt')
imagenet_labels = np.array(open(labels_path).read().splitlines())

plt.imshow(predict_img)
plt.axis('off')
predicted_class_name = imagenet_labels[predicted_class]
_ = plt.title("Prediction: " + predicted_class_name.title())

তাহলে পেয়ে গেলাম প্রিডিক্টেড ইমেজটির নাম।

এতটুকু পর্যন্ত যা করেছি, তা পাওয়া যাবে পাওয়া যাবে গুগল কোল্যাবে – Transfer Learning as is। পুরো কোডঃ

import matplotlib.pylab as plt

import tensorflow as tf
import tensorflow_hub as hub
from tensorflow.keras import layers


import numpy as np
import PIL.Image as Image


model = tf.keras.Sequential([
    hub.KerasLayer("https://tfhub.dev/google/tf2-preview/mobilenet_v2/classification/4", output_shape=[1001])
])



IMAGE_RES = 224

predict_img = tf.keras.utils.get_file('image.jpg','https://upload.wikimedia.org/wikipedia/commons/thumb/4/43/AD2009Aug07_Natrix_natrix_01.jpg/640px-AD2009Aug07_Natrix_natrix_01.jpg')
predict_img = Image.open(predict_img).resize((IMAGE_RES, IMAGE_RES))
predict_img 

predict_img = np.array(predict_img)/255.0 # data normalization 
predict_img.shape

# convert single image array to batch dimension, cause models always want a batch of images to process

result = model.predict(predict_img[np.newaxis, ...]) 
result.shape

predicted_class = np.argmax(result[0], axis=-1)
predicted_class

# get level name from prediction

labels_path = tf.keras.utils.get_file('ImageNetLabels.txt','https://storage.googleapis.com/download.tensorflow.org/data/ImageNetLabels.txt')
imagenet_labels = np.array(open(labels_path).read().splitlines())

plt.imshow(predict_img)
plt.axis('off')
predicted_class_name = imagenet_labels[predicted_class]
_ = plt.title("Prediction: " + predicted_class_name.title())


 

২ঃ প্রিট্রেইন্ড মডেল কাস্টমাইজ করে ব্যবহার করা

 

প্রিট্রেইন্ড মডেল কাস্টোমাইজ করে আবার দুই ভাবে করা যায়।

  1. ফিচার এক্সট্রাকশন প্রক্রিয়া
  2. ফাইন টিউইং প্রক্রিয়া

 

প্রথমে দেখি ফিচার এক্সট্রাকশন করে কিভাবে প্রিট্রেইন্ড মডেল ব্যবহার করা যায়।

ফিচার এক্সট্রাকশনঃ

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

মডেল ফ্রিজিং

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

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

# creating feature extractor

URL = "https://tfhub.dev/google/tf2-preview/mobilenet_v2/feature_vector/4"
feature_extractor = hub.KerasLayer(URL,
input_shape=(IMAGE_RES, IMAGE_RES, 3))

এরপর বলে দিতে হবে এই ফিচার গুলো যেন ট্রেইন না হয়। আর তা করতে হবে এভাবেঃ

feature_extractor.trainable = False

এরপর আমরা নতুন যে মডেল তৈরি করব, সেখানে ক্লাসিফিকেশন লেয়ার যুক্ত করতে হবেঃ

model = tf.keras.Sequential([
feature_extractor,
layers.Dense(num_classes)
])

এবার আমরা এই নতুন মডেলটি ট্রেইন করার জন্য প্রস্তুত!

model.fit(train_batches,
epochs=EPOCHS,
validation_data=validation_batches)

অনেক সহজ না?   পুরো প্রজেক্ট  পাওয়া যাবে গুগল কোল্যাবে। কোড গুলো এখানেও দিয়ে দিলামঃ

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

import tensorflow_hub as hub
import tensorflow_datasets as tfds

from tensorflow.keras import layers

import logging
logger = tf.get_logger()
logger.setLevel(logging.ERROR)

# data load and split 

(training_set, validation_set), dataset_info = tfds.load(
    'tf_flowers',
    split=['train[:70%]', 'train[70%:]'],
    with_info=True,
    as_supervised=True,
)

num_classes = dataset_info.features['label'].num_classes
class_names = np.array(dataset_info.features['label'].names)

num_training_examples = 0
num_validation_examples = 0

for example in training_set:
  num_training_examples += 1

for example in validation_set:
  num_validation_examples += 1

# resize & normalize images & creating batch

IMAGE_RES = 224

def format_image(image, label):
  image = tf.image.resize(image, (IMAGE_RES, IMAGE_RES))/255.0
  return image, label

BATCH_SIZE = 32

train_batches = training_set.shuffle(num_training_examples//4).map(format_image).batch(BATCH_SIZE).prefetch(1)

validation_batches = validation_set.map(format_image).batch(BATCH_SIZE).prefetch(1)

# createing feature extractor

URL = "https://tfhub.dev/google/tf2-preview/mobilenet_v2/feature_vector/4"
feature_extractor = hub.KerasLayer(URL,
                                   input_shape=(IMAGE_RES, IMAGE_RES, 3))
# Model freezing 
feature_extractor.trainable = False


# attaching classification head

model = tf.keras.Sequential([
  feature_extractor,
  layers.Dense(num_classes)
])


model.compile(
  optimizer='adam',
  loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
  metrics=['accuracy'])

EPOCHS = 1

history = model.fit(train_batches,
                    epochs=EPOCHS,
                    validation_data=validation_batches)


print("Labels:           ", label_batch)
print("Predicted labels: ", predicted_ids)

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

এই সম্পর্কিত আরো কিছু লেখাঃ

এছাড়া আর্টিফিশিয়াল ইন্টিলিজেন্স এবং মেশিন লার্নিং নিয়ে সব গুলো লেখা পাওয়া যাবে এখানে।

Leave a Reply