মডেলকে এফিসিয়েন্ট করার জন্য আমাদেরকে weights, biases এগুলা ওপ্টিমাইজ করতে হবে। আর এগুলো অপ্টিমাইজ করার জন্য আমাদেরকে জানতে হবে মডেলটা কত ভালো পারফর্ম করল। এটা বের করতে পারবো y_pred এবং y_true এর তুলনা করে। এই তুলনা করার অনেক রকম পদ্ধতির মধ্যে একটি পদ্ধতি হচ্ছে cross-entropy মিজারমেন্ট। ক্লাসিফিকেশন সমস্যার জন্য এটি একটি বহুল ব্যবহৃত Cost Function. এটি একটি Continuous Function যার মান সবসময় পজিটিভ। কিন্তু যদি প্রেডিক্টেড আউটপুট এবং আমাদের চাহিদা মোতাবেক আউটপুট একদম মিলে যায় তাহলে এর মান আসে শূন্য। তার মানে, আমরা যদি এই ফ্যাক্টরটির দিকে নজর রাখি এবং সব সময় চাই যে, ওয়েট - বায়াস অ্যাডজাস্ট করে করে এই ফ্যাক্টরটির মান যতটা শূন্যের কাছাকাছি আনা যায় -তাহলেই আমরা ভালো Accuracy এর দিকে আগাবো। খুশির খবর হচ্ছে TensorFlow এর একটা বিল্ট ইন ফাংশন আছে এই ক্রস-এন্ট্রপি বের করার জন্য। মনে রাখতে হবে, এই ফাংশনটি logits ম্যাট্রিক্স নিয়ে কাজ করে। কারন এটি নিজেই softmax এর কাজটা ভিতরে করে ফেলে। তাই y_pred = tf.nn.softmax(logits) লাইনের আগের ভ্যালু আমাদের এখানে দরকার।
# Cell 18
cross_entropy = tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=y_true)
যেহেতু আমরা একবারে পুরো logits ম্যাট্রিক্সকে ইনপুট হিসেবে দিয়েছি, তাই এই ম্যাট্রিক্সে যতগুলো ইমেজের ক্লাসিফিকেশন থাকবে সবগুলোর ক্রস-এন্ট্রপি বের করে ফেলছি উপরের লাইনে। তার মানে প্রত্যেকটি ইমেজের জন্যই আলাদা আলাদা ক্রস-এন্ট্রপি ভ্যালু পাবো আমরা। কিন্তু, পুরো সিস্টেমের অপটিমাইজেশন গাইড করার জন্য আমাদের একটা সিঙ্গেল ভ্যালু হলেই বরং ভালো। আর তাই, আমরা সাধারণ গড় করে নিতে পারি ওই আলাদা আলাদা ইমেজের আলাদা আলাদা ক্রস-এন্ট্রপি ভ্যালু গুলোর।
# Cell 19
cost = tf.reduce_mean(cross_entropy)
অপটিমাইজেশন মেথডঃ
তো, এখন যেহেতু আমাদের হাতে একটি Cost Measure থাকলো যেটাকে মিনিমাইজ করতে হবে, তাই এখন আমরা একটি অপ্টিমাইজার তৈরি করতে পারি। এই টিউটোরিয়ালে আমরা একটি ব্যাসিক অপ্টিমাইজার (Gradient Descent) ব্যবহার করবো। এটাও বিল্ট ইন আছে TensorFlow তে। আলাদা করে এটা বুঝতে এখানে ক্লিক করতে পারেন।
# Cell 20
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.5).minimize(cost)
এখানে 0.5 হচ্ছে গ্র্যাডিয়েন্ট খোজার স্টেপ সাইজ (যদি উপরের লিঙ্কে ক্লিক করে ঘুরে এসে থাকেন তাহলে এটা বুঝে ফেলার কথা)।
এখানে খুব গুরুত্বপূর্ণ একটা কথা মনে রাখা জরুরি - উপরের স্টেটমেন্ট এক্সিকিউট করার সাথে সাথেই কিন্তু অপটিমাইজেশন শুরু হয়ে যায় নি। TensorFlow গ্রাফে আমরা একটা নতুন অবজেক্ট যুক্ত করেছি মাত্র। আসলে কোন কিছুই হয়নি এখন পর্যন্ত। পুরো গ্রাফকে রান করালে এসব কাজ করা শুরু করবে একসাথে। যেহেতু আমরা জুপিটার নোটবুকে এই সেল/কোডব্লক গুলো এক্সিকিউট করছি তাই এগুলো রানটাইম মেমোরিতে থাকছে মাত্র।
পারফর্মেন্স মিজার করাঃ
ঘটনা যাই হোক, আমাদের একটা ফ্যাক্টর রেডি করা উচিৎ যার দিকে তাকিয়ে আমরা এক কথায় বলে দিতে পারবো আমাদের মডেলের পারফর্মেন্স কেমন। অর্থাৎ যদি মডেল তৈরি করে ট্রেইন করার শেষে আমরা একটা একটা করে টেস্ট ইমেজ ইনপুট দিয়ে আউটপুট জেনে খাতায় টালি করে করে হিসাব রাখতে চাই যে - কয়টা ভুল হল আর কয়টা ঠিক হল; তাহলে খবর আছে। বরং আমরা কুইক হিসাব করে বের করতে চাই আসলে ওভারঅল পারফর্মেন্স কেমন। যাতে করে আমরা মডেলের রিডিজাইন এবং মডিফিকেশনে দ্রুত মন দিতে পারি। ফাইনালি যখন মডেলটি পাবলিক ইউজের জন্য ছেড়ে দেয়া হবে, তখন সেখানে ইউজার একটা করে ইনপুট দিয়ে দেখবে কাজ করছে কিনা।
আমরা প্রথমে একটা বুলিয়ান ভেক্টর পেতে পারি নিচের মত করে,
# Cell 21
correct_prediction = tf.equal(y_pred_cls, y_true_cls)
যার মধ্যে আছে প্রেডিক্টেড ক্লাস এবং ট্রু ক্লাসের মিল চেক করে জমা করা কিছু ট্রু, ফলস :) এরপর নিচের লাইনে আমরা সেই ভেক্টরটিকে আবার কাস্টিং করে ফ্লট এ কনভার্ট করছি যাতে করে ট্রু মানে 1 এবং ফলস মানে 0 হয়। আর শেষ নাগাদ এগুলোর গড় বের করলেই কিন্তু বোঝা যাচ্ছে যে টোটাল Accuracy কেমন। তাই না? সব যদি ট্রু হয় তাহলে ভেক্টরে থাকছে [1, 1, 1, 1, 1] (ধরি ৫টা ইমেজের ক্ষেত্রে) তাহলে গড় (যোগ দিয়ে ৫ দিয়ে ভাগ) তো 100% নাকি?
# Cell 22
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))