শুরুর ঘটনা

‘কনভলিউশনাল নিউরাল নেটওয়ার্ক’ এবং গ্লোবাল অ্যাভারেজ পুলিং

(পুরো চ্যাপ্টার একটা নোটবুক)

আমরা বই পড়ছি, নোটবুক কেন পড়বো?

নোটবুক সবসময় আপডেটেড। এই বই থেকেও। কারণ বইটা লিখছি নোটবুকে।

যেহেতু গিটবুকে নোটবুক ঠিকমতো রেন্ডার হয়না, সেকারণে গুগল কোলাব এবং গিটহাবে দেখা উচিৎ। গিটহাব লিংক:

নিজে নিজে প্র্যাকটিস করুন: https://github.com/raqueeb/TensorFlow2/blob/master/GAP_cnn_tf3.ipynb অথবা https://nbviewer.jupyter.org/github/raqueeb/TensorFlow2/blob/master/GAP_cnn_tf3.ipynb

কোলাব লিংক: https://colab.research.google.com/github/raqueeb/TensorFlow2/blob/master/GAP_cnn_tf3.ipynb

‘কনভলিউশনাল নিউরাল নেটওয়ার্ক’ এবং গ্লোবাল অ্যাভারেজ পুলিং

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

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

try:
# শুধুমাত্র টেন্সর-ফ্লো ২.x ব্যবহার করবো
%tensorflow_version 2.x
except Exception:
pass
import tensorflow as tf
TensorFlow 2.x selected.

প্রি-ট্রেইনড মডেল VGG16 এর লেয়ার

# from tensorflow.keras import layers
from tensorflow.keras.applications.vgg16 import VGG16; VGG16().summary()
Model: "vgg16"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_3 (InputLayer) [(None, 224, 224, 3)] 0
_________________________________________________________________
block1_conv1 (Conv2D) (None, 224, 224, 64) 1792
_________________________________________________________________
block1_conv2 (Conv2D) (None, 224, 224, 64) 36928
_________________________________________________________________
block1_pool (MaxPooling2D) (None, 112, 112, 64) 0
_________________________________________________________________
block2_conv1 (Conv2D) (None, 112, 112, 128) 73856
_________________________________________________________________
block2_conv2 (Conv2D) (None, 112, 112, 128) 147584
_________________________________________________________________
block2_pool (MaxPooling2D) (None, 56, 56, 128) 0
_________________________________________________________________
block3_conv1 (Conv2D) (None, 56, 56, 256) 295168
_________________________________________________________________
block3_conv2 (Conv2D) (None, 56, 56, 256) 590080
_________________________________________________________________
block3_conv3 (Conv2D) (None, 56, 56, 256) 590080
_________________________________________________________________
block3_pool (MaxPooling2D) (None, 28, 28, 256) 0
_________________________________________________________________
block4_conv1 (Conv2D) (None, 28, 28, 512) 1180160
_________________________________________________________________
block4_conv2 (Conv2D) (None, 28, 28, 512) 2359808
_________________________________________________________________
block4_conv3 (Conv2D) (None, 28, 28, 512) 2359808
_________________________________________________________________
block4_pool (MaxPooling2D) (None, 14, 14, 512) 0
_________________________________________________________________
block5_conv1 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_conv2 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_conv3 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_pool (MaxPooling2D) (None, 7, 7, 512) 0
_________________________________________________________________
flatten (Flatten) (None, 25088) 0
_________________________________________________________________
fc1 (Dense) (None, 4096) 102764544
_________________________________________________________________
fc2 (Dense) (None, 4096) 16781312
_________________________________________________________________
predictions (Dense) (None, 1000) 4097000
=================================================================
Total params: 138,357,544
Trainable params: 138,357,544
Non-trainable params: 0
_________________________________________________________________

প্রি-ট্রেইনড মডেল ResNet-50 এর লেয়ার

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

পরেরটা ResNet-50, কি পার্থক্য দেখলাম?

from tensorflow.keras.applications.resnet50 import ResNet50; ResNet50().summary()
Model: "resnet50"
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_4 (InputLayer) [(None, 224, 224, 3) 0
__________________________________________________________________________________________________
conv1_pad (ZeroPadding2D) (None, 230, 230, 3) 0 input_4[0][0]
__________________________________________________________________________________________________
conv1_conv (Conv2D) (None, 112, 112, 64) 9472 conv1_pad[0][0]
__________________________________________________________________________________________________
conv1_bn (BatchNormalization) (None, 112, 112, 64) 256 conv1_conv[0][0]
__________________________________________________________________________________________________
conv1_relu (Activation) (None, 112, 112, 64) 0 conv1_bn[0][0]
__________________________________________________________________________________________________
pool1_pad (ZeroPadding2D) (None, 114, 114, 64) 0 conv1_relu[0][0]
__________________________________________________________________________________________________
pool1_pool (MaxPooling2D) (None, 56, 56, 64) 0 pool1_pad[0][0]
__________________________________________________________________________________________________
conv2_block1_1_conv (Conv2D) (None, 56, 56, 64) 4160 pool1_pool[0][0]
__________________________________________________________________________________________________
conv2_block1_1_bn (BatchNormali (None, 56, 56, 64) 256 conv2_block1_1_conv[0][0]
__________________________________________________________________________________________________
conv2_block1_1_relu (Activation (None, 56, 56, 64) 0 conv2_block1_1_bn[0][0]
__________________________________________________________________________________________________
conv2_block1_2_conv (Conv2D) (None, 56, 56, 64) 36928 conv2_block1_1_relu[0][0]
__________________________________________________________________________________________________
conv2_block1_2_bn (BatchNormali (None, 56, 56, 64) 256 conv2_block1_2_conv[0][0]
__________________________________________________________________________________________________
conv2_block1_2_relu (Activation (None, 56, 56, 64) 0 conv2_block1_2_bn[0][0]
__________________________________________________________________________________________________
conv2_block1_0_conv (Conv2D) (None, 56, 56, 256) 16640 pool1_pool[0][0]
__________________________________________________________________________________________________
conv2_block1_3_conv (Conv2D) (None, 56, 56, 256) 16640 conv2_block1_2_relu[0][0]
__________________________________________________________________________________________________
conv2_block1_0_bn (BatchNormali (None, 56, 56, 256) 1024 conv2_block1_0_conv[0][0]
__________________________________________________________________________________________________
conv2_block1_3_bn (BatchNormali (None, 56, 56, 256) 1024 conv2_block1_3_conv[0][0]
__________________________________________________________________________________________________
conv2_block1_add (Add) (None, 56, 56, 256) 0 conv2_block1_0_bn[0][0]
conv2_block1_3_bn[0][0]
__________________________________________________________________________________________________
conv2_block1_out (Activation) (None, 56, 56, 256) 0 conv2_block1_add[0][0]
__________________________________________________________________________________________________
conv2_block2_1_conv (Conv2D) (None, 56, 56, 64) 16448 conv2_block1_out[0][0]
__________________________________________________________________________________________________
conv2_block2_1_bn (BatchNormali (None, 56, 56, 64) 256 conv2_block2_1_conv[0][0]
__________________________________________________________________________________________________
conv2_block2_1_relu (Activation (None, 56, 56, 64) 0 conv2_block2_1_bn[0][0]
__________________________________________________________________________________________________
conv2_block2_2_conv (Conv2D) (None, 56, 56, 64) 36928 conv2_block2_1_relu[0][0]
__________________________________________________________________________________________________
conv2_block2_2_bn (BatchNormali (None, 56, 56, 64) 256 conv2_block2_2_conv[0][0]
__________________________________________________________________________________________________
conv2_block2_2_relu (Activation (None, 56, 56, 64) 0 conv2_block2_2_bn[0][0]
__________________________________________________________________________________________________
conv2_block2_3_conv (Conv2D) (None, 56, 56, 256) 16640 conv2_block2_2_relu[0][0]
__________________________________________________________________________________________________
conv2_block2_3_bn (BatchNormali (None, 56, 56, 256) 1024 conv2_block2_3_conv[0][0]
__________________________________________________________________________________________________
conv2_block2_add (Add) (None, 56, 56, 256) 0 conv2_block1_out[0][0]
conv2_block2_3_bn[0][0]
__________________________________________________________________________________________________
conv2_block2_out (Activation) (None, 56, 56, 256) 0 conv2_block2_add[0][0]
__________________________________________________________________________________________________
conv2_block3_1_conv (Conv2D) (None, 56, 56, 64) 16448 conv2_block2_out[0][0]
__________________________________________________________________________________________________
conv2_block3_1_bn (BatchNormali (None, 56, 56, 64) 256 conv2_block3_1_conv[0][0]
__________________________________________________________________________________________________
conv2_block3_1_relu (Activation (None, 56, 56, 64) 0 conv2_block3_1_bn[0][0]
__________________________________________________________________________________________________
conv2_block3_2_conv (Conv2D) (None, 56, 56, 64) 36928 conv2_block3_1_relu[0][0]
__________________________________________________________________________________________________
conv2_block3_2_bn (BatchNormali (None, 56, 56, 64) 256 conv2_block3_2_conv[0][0]
__________________________________________________________________________________________________
conv2_block3_2_relu (Activation (None, 56, 56, 64) 0 conv2_block3_2_bn[0][0]
__________________________________________________________________________________________________
conv2_block3_3_conv (Conv2D) (None, 56, 56, 256) 16640 conv2_block3_2_relu[0][0]
__________________________________________________________________________________________________
conv2_block3_3_bn (BatchNormali (None, 56, 56, 256) 1024 conv2_block3_3_conv[0][0]
__________________________________________________________________________________________________
conv2_block3_add (Add) (None, 56, 56, 256) 0 conv2_block2_out[0][0]
conv2_block3_3_bn[0][0]
__________________________________________________________________________________________________
conv2_block3_out (Activation) (None, 56, 56, 256) 0 conv2_block3_add[0][0]
__________________________________________________________________________________________________
conv3_block1_1_conv (Conv2D) (None, 28, 28, 128) 32896 conv2_block3_out[0][0]
__________________________________________________________________________________________________
conv3_block1_1_bn (BatchNormali (None, 28, 28, 128) 512 conv3_block1_1_conv[0][0]
__________________________________________________________________________________________________
conv3_block1_1_relu (Activation (None, 28, 28, 128) 0 conv3_block1_1_bn[0][0]
__________________________________________________________________________________________________
conv3_block1_2_conv (Conv2D) (None, 28, 28, 128) 147584 conv3_block1_1_relu[0][0]
__________________________________________________________________________________________________
conv3_block1_2_bn (BatchNormali (None, 28, 28, 128) 512 conv3_block1_2_conv[0][0]
__________________________________________________________________________________________________
conv3_block1_2_relu (Activation (None, 28, 28, 128) 0 conv3_block1_2_bn[0][0]
__________________________________________________________________________________________________
conv3_block1_0_conv (Conv2D) (None, 28, 28, 512) 131584 conv2_block3_out[0][0]
__________________________________________________________________________________________________
conv3_block1_3_conv (Conv2D) (None, 28, 28, 512) 66048 conv3_block1_2_relu[0][0]
__________________________________________________________________________________________________
conv3_block1_0_bn (BatchNormali (None, 28, 28, 512) 2048 conv3_block1_0_conv[0][0]
__________________________________________________________________________________________________
conv3_block1_3_bn (BatchNormali (None, 28, 28, 512) 2048 conv3_block1_3_conv[0][0]
__________________________________________________________________________________________________
conv3_block1_add (Add) (None, 28, 28, 512) 0 conv3_block1_0_bn[0][0]
conv3_block1_3_bn[0][0]
__________________________________________________________________________________________________
conv3_block1_out (Activation) (None, 28, 28, 512) 0 conv3_block1_add[0][0]
__________________________________________________________________________________________________
conv3_block2_1_conv (Conv2D) (None, 28, 28, 128) 65664 conv3_block1_out[0][0]
__________________________________________________________________________________________________
conv3_block2_1_bn (BatchNormali (None, 28, 28, 128) 512 conv3_block2_1_conv[0][0]
__________________________________________________________________________________________________
conv3_block2_1_relu (Activation (None, 28, 28, 128) 0 conv3_block2_1_bn[0][0]
__________________________________________________________________________________________________
conv3_block2_2_conv (Conv2D) (None, 28, 28, 128) 147584 conv3_block2_1_relu[0][0]
__________________________________________________________________________________________________
conv3_block2_2_bn (BatchNormali (None, 28, 28, 128) 512 conv3_block2_2_conv[0][0]
__________________________________________________________________________________________________
conv3_block2_2_relu (Activation (None, 28, 28, 128) 0 conv3_block2_2_bn[0][0]
__________________________________________________________________________________________________
conv3_block2_3_conv (Conv2D) (None, 28, 28, 512) 66048 conv3_block2_2_relu[0][0]
__________________________________________________________________________________________________
conv3_block2_3_bn (BatchNormali (None, 28, 28, 512) 2048 conv3_block2_3_conv[0][0]
__________________________________________________________________________________________________
conv3_block2_add (Add) (None, 28, 28, 512) 0 conv3_block1_out[0][0]
conv3_block2_3_bn[0][0]
__________________________________________________________________________________________________
conv3_block2_out (Activation) (None, 28, 28, 512) 0 conv3_block2_add[0][0]
__________________________________________________________________________________________________
conv3_block3_1_conv (Conv2D) (None, 28, 28, 128) 65664 conv3_block2_out[0][0]
__________________________________________________________________________________________________
conv3_block3_1_bn (BatchNormali (None, 28, 28, 128) 512 conv3_block3_1_conv[0][0]
__________________________________________________________________________________________________
conv3_block3_1_relu (Activation (None, 28, 28, 128) 0 conv3_block3_1_bn[0][0]
__________________________________________________________________________________________________
conv3_block3_2_conv (Conv2D) (None, 28, 28, 128) 147584 conv3_block3_1_relu[0][0]
__________________________________________________________________________________________________
conv3_block3_2_bn (BatchNormali (None, 28, 28, 128) 512 conv3_block3_2_conv[0][0]
__________________________________________________________________________________________________
conv3_block3_2_relu (Activation (None, 28, 28, 128) 0 conv3_block3_2_bn[0][0]
__________________________________________________________________________________________________
conv3_block3_3_conv (Conv2D) (None, 28, 28, 512) 66048 conv3_block3_2_relu[0][0]
__________________________________________________________________________________________________
conv3_block3_3_bn (BatchNormali (None, 28, 28, 512) 2048 conv3_block3_3_conv[0][0]
__________________________________________________________________________________________________
conv3_block3_add (Add) (None, 28, 28, 512) 0 conv3_block2_out[0][0]
conv3_block3_3_bn[0][0]
__________________________________________________________________________________________________
conv3_block3_out (Activation) (None, 28, 28, 512) 0 conv3_block3_add[0][0]
__________________________________________________________________________________________________
conv3_block4_1_conv (Conv2D) (None, 28, 28, 128) 65664 conv3_block3_out[0][0]
__________________________________________________________________________________________________
conv3_block4_1_bn (BatchNormali (None, 28, 28, 128) 512 conv3_block4_1_conv[0][0]
__________________________________________________________________________________________________
conv3_block4_1_relu (Activation (None, 28, 28, 128) 0 conv3_block4_1_bn[0][0]
__________________________________________________________________________________________________
conv3_block4_2_conv (Conv2D) (None, 28, 28, 128) 147584 conv3_block4_1_relu[0][0]
__________________________________________________________________________________________________
conv3_block4_2_bn (BatchNormali (None, 28, 28, 128) 512 conv3_block4_2_conv[0][0]
__________________________________________________________________________________________________
conv3_block4_2_relu (Activation (None, 28, 28, 128) 0 conv3_block4_2_bn[0][0]
__________________________________________________________________________________________________
conv3_block4_3_conv (Conv2D) (None, 28, 28, 512) 66048 conv3_block4_2_relu[0][0]
__________________________________________________________________________________________________
conv3_block4_3_bn (BatchNormali (None, 28, 28, 512) 2048 conv3_block4_3_conv[0][0]
__________________________________________________________________________________________________
conv3_block4_add (Add) (None, 28, 28, 512) 0 conv3_block3_out[0][0]
conv3_block4_3_bn[0][0]
__________________________________________________________________________________________________
conv3_block4_out (Activation) (None, 28, 28, 512) 0 conv3_block4_add[0][0]
__________________________________________________________________________________________________
conv4_block1_1_conv (Conv2D) (None, 14, 14, 256) 131328 conv3_block4_out[0][0]
__________________________________________________________________________________________________
conv4_block1_1_bn (BatchNormali (None, 14, 14, 256) 1024 conv4_block1_1_conv[0][0]
__________________________________________________________________________________________________
conv4_block1_1_relu (Activation (None, 14, 14, 256) 0 conv4_block1_1_bn[0][0]
__________________________________________________________________________________________________
conv4_block1_2_conv (Conv2D) (None, 14, 14, 256) 590080 conv4_block1_1_relu[0][0]
__________________________________________________________________________________________________
conv4_block1_2_bn (BatchNormali (None, 14, 14, 256) 1024 conv4_block1_2_conv[0][0]
__________________________________________________________________________________________________
conv4_block1_2_relu (Activation (None, 14, 14, 256) 0 conv4_block1_2_bn[0][0]
__________________________________________________________________________________________________
conv4_block1_0_conv (Conv2D) (None, 14, 14, 1024) 525312 conv3_block4_out[0][0]
__________________________________________________________________________________________________
conv4_block1_3_conv (Conv2D) (None, 14, 14, 1024) 263168 conv4_block1_2_relu[0][0]
__________________________________________________________________________________________________
conv4_block1_0_bn (BatchNormali (None, 14, 14, 1024) 4096 conv4_block1_0_conv[0][0]
__________________________________________________________________________________________________
conv4_block1_3_bn (BatchNormali (None, 14, 14, 1024) 4096 conv4_block1_3_conv[0][0]
__________________________________________________________________________________________________
conv4_block1_add (Add) (None, 14, 14, 1024) 0 conv4_block1_0_bn[0][0]
conv4_block1_3_bn[0][0]
__________________________________________________________________________________________________
conv4_block1_out (Activation) (None, 14, 14, 1024) 0 conv4_block1_add[0][0]
__________________________________________________________________________________________________
conv4_block2_1_conv (Conv2D) (None, 14, 14, 256) 262400 conv4_block1_out[0][0]
__________________________________________________________________________________________________
conv4_block2_1_bn (BatchNormali (None, 14, 14, 256) 1024 conv4_block2_1_conv[0][0]
__________________________________________________________________________________________________
conv4_block2_1_relu (Activation (None, 14, 14, 256) 0 conv4_block2_1_bn[0][0]
__________________________________________________________________________________________________
conv4_block2_2_conv (Conv2D) (None, 14, 14, 256) 590080 conv4_block2_1_relu[0][0]
__________________________________________________________________________________________________
conv4_block2_2_bn (BatchNormali (None, 14, 14, 256) 1024 conv4_block2_2_conv[0][0]
__________________________________________________________________________________________________
conv4_block2_2_relu (Activation (None, 14, 14, 256) 0 conv4_block2_2_bn[0][0]
__________________________________________________________________________________________________
conv4_block2_3_conv (Conv2D) (None, 14, 14, 1024) 263168 conv4_block2_2_relu[0][0]
__________________________________________________________________________________________________
conv4_block2_3_bn (BatchNormali (None, 14, 14, 1024) 4096 conv4_block2_3_conv[0][0]
__________________________________________________________________________________________________
conv4_block2_add (Add) (None, 14, 14, 1024) 0 conv4_block1_out[0][0]
conv4_block2_3_bn[0][0]
__________________________________________________________________________________________________
conv4_block2_out (Activation) (None, 14, 14, 1024) 0 conv4_block2_add[0][0]
__________________________________________________________________________________________________
conv4_block3_1_conv (Conv2D) (None, 14, 14, 256) 262400 conv4_block2_out[0][0]
__________________________________________________________________________________________________
conv4_block3_1_bn (BatchNormali (None, 14, 14, 256) 1024 conv4_block3_1_conv[0][0]
__________________________________________________________________________________________________
conv4_block3_1_relu (Activation (None, 14, 14, 256) 0 conv4_block3_1_bn[0][0]
__________________________________________________________________________________________________
conv4_block3_2_conv (Conv2D) (None, 14, 14, 256) 590080 conv4_block3_1_relu[0][0]
__________________________________________________________________________________________________
conv4_block3_2_bn (BatchNormali (None, 14, 14, 256) 1024 conv4_block3_2_conv[0][0]
__________________________________________________________________________________________________
conv4_block3_2_relu (Activation (None, 14, 14, 256) 0 conv4_block3_2_bn[0][0]
__________________________________________________________________________________________________
conv4_block3_3_conv (Conv2D) (None, 14, 14, 1024) 263168 conv4_block3_2_relu[0][0]
__________________________________________________________________________________________________
conv4_block3_3_bn (BatchNormali (None, 14, 14, 1024) 4096 conv4_block3_3_conv[0][0]
__________________________________________________________________________________________________
conv4_block3_add (Add) (None, 14, 14, 1024) 0 conv4_block2_out[0][0]
conv4_block3_3_bn[0][0]
__________________________________________________________________________________________________
conv4_block3_out (Activation) (None, 14, 14, 1024) 0 conv4_block3_add[0][0]
__________________________________________________________________________________________________
conv4_block4_1_conv (Conv2D) (None, 14, 14, 256) 262400 conv4_block3_out[0][0]
__________________________________________________________________________________________________
conv4_block4_1_bn (BatchNormali (None, 14, 14, 256) 1024 conv4_block4_1_conv[0][0]
__________________________________________________________________________________________________
conv4_block4_1_relu (Activation (None, 14, 14, 256) 0 conv4_block4_1_bn[0][0]
__________________________________________________________________________________________________
conv4_block4_2_conv (Conv2D) (None, 14, 14, 256) 590080 conv4_block4_1_relu[0][0]
__________________________________________________________________________________________________
conv4_block4_2_bn (BatchNormali (None, 14, 14, 256) 1024 conv4_block4_2_conv[0][0]
__________________________________________________________________________________________________
conv4_block4_2_relu (Activation (None, 14, 14, 256) 0 conv4_block4_2_bn[0][0]
__________________________________________________________________________________________________
conv4_block4_3_conv (Conv2D) (None, 14, 14, 1024) 263168 conv4_block4_2_relu[0][0]
__________________________________________________________________________________________________
conv4_block4_3_bn (BatchNormali (None, 14, 14, 1024) 4096 conv4_block4_3_conv[0][0]
__________________________________________________________________________________________________
conv4_block4_add (Add) (None, 14, 14, 1024) 0 conv4_block3_out[0][0]
conv4_block4_3_bn[0][0]
__________________________________________________________________________________________________
conv4_block4_out (Activation) (None, 14, 14, 1024) 0 conv4_block4_add[0][0]
__________________________________________________________________________________________________
conv4_block5_1_conv (Conv2D) (None, 14, 14, 256) 262400 conv4_block4_out[0][0]
__________________________________________________________________________________________________
conv4_block5_1_bn (BatchNormali (None, 14, 14, 256) 1024 conv4_block5_1_conv[0][0]
__________________________________________________________________________________________________
conv4_block5_1_relu (Activation (None, 14, 14, 256) 0 conv4_block5_1_bn[0][0]
__________________________________________________________________________________________________
conv4_block5_2_conv (Conv2D) (None, 14, 14, 256) 590080 conv4_block5_1_relu[0][0]
__________________________________________________________________________________________________
conv4_block5_2_bn (BatchNormali (None, 14, 14, 256) 1024 conv4_block5_2_conv[0][0]
__________________________________________________________________________________________________
conv4_block5_2_relu (Activation (None, 14, 14, 256) 0 conv4_block5_2_bn[0][0]
__________________________________________________________________________________________________
conv4_block5_3_conv (Conv2D) (None, 14, 14, 1024) 263168 conv4_block5_2_relu[0][0]
__________________________________________________________________________________________________
conv4_block5_3_bn (BatchNormali (None, 14, 14, 1024) 4096 conv4_block5_3_conv[0][0]
__________________________________________________________________________________________________
conv4_block5_add (Add) (None, 14, 14, 1024) 0 conv4_block4_out[0][0]
conv4_block5_3_bn[0][0]
__________________________________________________________________________________________________
conv4_block5_out (Activation) (None, 14, 14, 1024) 0 conv4_block5_add[0][0]
__________________________________________________________________________________________________
conv4_block6_1_conv (Conv2D) (None, 14, 14, 256) 262400 conv4_block5_out[0][0]
__________________________________________________________________________________________________
conv4_block6_1_bn (BatchNormali (None, 14, 14, 256) 1024 conv4_block6_1_conv[0][0]
__________________________________________________________________________________________________
conv4_block6_1_relu (Activation (None, 14, 14, 256) 0 conv4_block6_1_bn[0][0]
__________________________________________________________________________________________________
conv4_block6_2_conv (Conv2D) (None, 14, 14, 256) 590080 conv4_block6_1_relu[0][0]
__________________________________________________________________________________________________
conv4_block6_2_bn (BatchNormali (None, 14, 14, 256) 1024 conv4_block6_2_conv[0][0]
__________________________________________________________________________________________________
conv4_block6_2_relu (Activation (None, 14, 14, 256) 0 conv4_block6_2_bn[0][0]
__________________________________________________________________________________________________
conv4_block6_3_conv (Conv2D) (None, 14, 14, 1024) 263168 conv4_block6_2_relu[0][0]
__________________________________________________________________________________________________
conv4_block6_3_bn (BatchNormali (None, 14, 14, 1024) 4096 conv4_block6_3_conv[0][0]
__________________________________________________________________________________________________
conv4_block6_add (Add) (None, 14, 14, 1024) 0 conv4_block5_out[0][0]
conv4_block6_3_bn[0][0]
__________________________________________________________________________________________________
conv4_block6_out (Activation) (None, 14, 14, 1024) 0 conv4_block6_add[0][0]
__________________________________________________________________________________________________
conv5_block1_1_conv (Conv2D) (None, 7, 7, 512) 524800 conv4_block6_out[0][0]
__________________________________________________________________________________________________
conv5_block1_1_bn (BatchNormali (None, 7, 7, 512) 2048 conv5_block1_1_conv[0][0]
__________________________________________________________________________________________________
conv5_block1_1_relu (Activation (None, 7, 7, 512) 0 conv5_block1_1_bn[0][0]
__________________________________________________________________________________________________
conv5_block1_2_conv (Conv2D) (None, 7, 7, 512) 2359808 conv5_block1_1_relu[0][0]
__________________________________________________________________________________________________
conv5_block1_2_bn (BatchNormali (None, 7, 7, 512) 2048 conv5_block1_2_conv[0][0]
__________________________________________________________________________________________________
conv5_block1_2_relu (Activation (None, 7, 7, 512) 0 conv5_block1_2_bn[0][0]
__________________________________________________________________________________________________
conv5_block1_0_conv (Conv2D) (None, 7, 7, 2048) 2099200 conv4_block6_out[0][0]
__________________________________________________________________________________________________
conv5_block1_3_conv (Conv2D) (None, 7, 7, 2048) 1050624 conv5_block1_2_relu[0][0]
__________________________________________________________________________________________________
conv5_block1_0_bn (BatchNormali (None, 7, 7, 2048) 8192 conv5_block1_0_conv[0][0]
__________________________________________________________________________________________________
conv5_block1_3_bn (BatchNormali (None, 7, 7, 2048) 8192 conv5_block1_3_conv[0][0]
__________________________________________________________________________________________________
conv5_block1_add (Add) (None, 7, 7, 2048) 0 conv5_block1_0_bn[0][0]
conv5_block1_3_bn[0][0]
__________________________________________________________________________________________________
conv5_block1_out (Activation) (None, 7, 7, 2048) 0 conv5_block1_add[0][0]
__________________________________________________________________________________________________
conv5_block2_1_conv (Conv2D) (None, 7, 7, 512) 1049088 conv5_block1_out[0][0]
__________________________________________________________________________________________________
conv5_block2_1_bn (BatchNormali (None, 7, 7, 512) 2048 conv5_block2_1_conv[0][0]
__________________________________________________________________________________________________
conv5_block2_1_relu (Activation (None, 7, 7, 512) 0 conv5_block2_1_bn[0][0]
__________________________________________________________________________________________________
conv5_block2_2_conv (Conv2D) (None, 7, 7, 512) 2359808 conv5_block2_1_relu[0][0]
__________________________________________________________________________________________________
conv5_block2_2_bn (BatchNormali (None, 7, 7, 512) 2048 conv5_block2_2_conv[0][0]
__________________________________________________________________________________________________
conv5_block2_2_relu (Activation (None, 7, 7, 512) 0 conv5_block2_2_bn[0][0]
__________________________________________________________________________________________________
conv5_block2_3_conv (Conv2D) (None, 7, 7, 2048) 1050624 conv5_block2_2_relu[0][0]
__________________________________________________________________________________________________
conv5_block2_3_bn (BatchNormali (None, 7, 7, 2048) 8192 conv5_block2_3_conv[0][0]
__________________________________________________________________________________________________
conv5_block2_add (Add) (None, 7, 7, 2048) 0 conv5_block1_out[0][0]
conv5_block2_3_bn[0][0]
__________________________________________________________________________________________________
conv5_block2_out (Activation) (None, 7, 7, 2048) 0 conv5_block2_add[0][0]
__________________________________________________________________________________________________
conv5_block3_1_conv (Conv2D) (None, 7, 7, 512) 1049088 conv5_block2_out[0][0]
__________________________________________________________________________________________________
conv5_block3_1_bn (BatchNormali (None, 7, 7, 512) 2048 conv5_block3_1_conv[0][0]
__________________________________________________________________________________________________
conv5_block3_1_relu (Activation (None, 7, 7, 512) 0 conv5_block3_1_bn[0][0]
__________________________________________________________________________________________________
conv5_block3_2_conv (Conv2D) (None, 7, 7, 512) 2359808 conv5_block3_1_relu[0][0]
__________________________________________________________________________________________________
conv5_block3_2_bn (BatchNormali (None, 7, 7, 512) 2048 conv5_block3_2_conv[0][0]
__________________________________________________________________________________________________
conv5_block3_2_relu (Activation (None, 7, 7, 512) 0 conv5_block3_2_bn[0][0]
__________________________________________________________________________________________________
conv5_block3_3_conv (Conv2D) (None, 7, 7, 2048) 1050624 conv5_block3_2_relu[0][0]
__________________________________________________________________________________________________
conv5_block3_3_bn (BatchNormali (None, 7, 7, 2048) 8192 conv5_block3_3_conv[0][0]
__________________________________________________________________________________________________
conv5_block3_add (Add) (None, 7, 7, 2048) 0 conv5_block2_out[0][0]
conv5_block3_3_bn[0][0]
__________________________________________________________________________________________________
conv5_block3_out (Activation) (None, 7, 7, 2048) 0 conv5_block3_add[0][0]
__________________________________________________________________________________________________
avg_pool (GlobalAveragePooling2 (None, 2048) 0 conv5_block3_out[0][0]
__________________________________________________________________________________________________
probs (Dense) (None, 1000) 2049000 avg_pool[0][0]
==================================================================================================
Total params: 25,636,712
Trainable params: 25,583,592
Non-trainable params: 53,120
__________________________________________________________________________________________________

কি দেখলেন? শেষ আউটপুট লেয়ারের আগে একটা নতুন এন্ট্রি 'avg_pool (GlobalAveragePooling2D)', চলুন আলাপ করি। শুরুতেই আরেকটা ডেটাসেট, সিএনএন দিয়ে।

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

# লোড করে নেই হেল্পার লাইব্রেরি, টেন্সর-ফ্লো ডেটাসেট এপিআই
import tensorflow as tf
from tensorflow.keras import layers
import tensorflow_datasets as tfds
import matplotlib.pylab as plt
import datetime as dt

গ্লোবাল অ্যাভারেজ পুলিং

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

চিত্রঃ ‘গ্লোবাল অ্যাভারেজ পুলিং’ লেয়ার চলে আসছে আউটপুটের আগের লেয়ারে

আপনারা দেখুন - সবশেষ লেয়ারে যেখানে আমরা জিনিসপত্র ক্লাসিফাই করছি তার আগেই এই গ্লোবাল এভারেজ পুলিং লেয়ারটা দেখতে পাচ্ছি। সেটা থেকে আউটপুট চলে যাচ্ছে আগের মত সফটম্যাক্স লেয়ারে। আমাদের এই আর্কিটেকচারে ৬৪টা গড় ক্যালকুলেশন আসছে সেই ৬৪ এবং ৭ x ৭ চ্যানেল থেকে - যেটা আমরা দেখছি দ্বিতীয় কনভলিউশনাল লেয়ারের আউটপুট থেকে আসছে। আমাদের এই ‘গ্যাপ’ মানে ‘গ্লোবাল অ্যাভারেজ পুলিং’ লেয়ার আগের ৭ x ৭, ৬৪ ডাইমেনশন থেকে ১ x ১, ৬৪ ডাইমেনশনে যা আসলে আসছে ৭ x ৭ চ্যানেলের গড় আউটপুট থেকে। অনেকে বলতে পারেন শেষের ‘ফুললি কানেক্টেড লেয়ারগুলো থেকে গ্লোবাল অ্যাভারেজ পুলিং লেয়ার কেন ভালো?

১. সবচেয়ে বড় কথা হচ্ছে আমরা মডেলের শেষ লেয়ারগুলোতে ট্রেনিং করার মত প্যারামিটারগুলোকে বাদ দিয়ে দিচ্ছি। একটা ‘ফুললি কানেক্টেড’ অথবা ‘ডেন্স’ লেয়ারে প্রচুর প্যারামিটার থাকে সেখানে আমাদের আগের ছবিতে একটা ৭ x ৭, ৬৪ ডাইমেনশনের ‘সিএনএন’ আউটপুটকে প্ল্যান করে সেটাকে ঢুকিয়ে দেয়া হচ্ছে ৫০০ নোডের একটা ডেন্স লেয়ারে যেটা প্রায় ১৫ কোটি ‘ওয়েট’ বের করে দিচ্ছে আমাদের ট্রেনিংয়ের জন্য। এটা একটা বিশাল কাজের লোড। এই জিনিসগুলোকে বাদ দেয়াতে আমাদের ট্রেনিং স্পিড বেড়ে যাবে অনেক গুন।

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

৩. ‘গ্লোবাল অ্যাভারেজ পুলিং’ নিয়ে প্রচুর আলাপ হয়েছে রিসার্চে। দেখা গেছে আমরা যদি এই ‘ফুললি কানেক্টেড ক্লাসিফিকেশন লেয়ার ফেলে দেই তাহলে ফিচার ম্যাপগুলো খুব কাছাকাছি কাজ করতে পারে তাদের ক্লাসিফিকেশন ক্যাটেগরি বানানোর জন্য। কিছুটা ডাইরেক্ট কানেকশন। এখানে আমরা বলতে পারি আমাদের প্রতিটা ফিচার ম্যাপ একেকটা ক্যাটেগরির ‘কনফিডেন্স ম্যাপ’ হিসেবে দাঁড়িয়ে গেছে।

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

আমাদের একটা সাধারণ ‘কনভলিউশনাল নিউরাল নেটওয়ার্ক’ এবং ‘গ্লোবাল এভারেজ পুলিং’ এর মধ্যে লস এবং অ্যাক্যুরেসি বের করে দেখব কোনটা ভালো কাজ করে।

# দরকার টেন্সর-ফ্লো কলব্যাক ফিচার
%load_ext tensorboard
The tensorboard extension is already loaded. To reload it, use:
%reload_ext tensorboard
from tensorflow.keras.callbacks import TensorBoard
log_dir='log/'
# আগের সব ট্রেনিং এর লগ ফেলে দিচ্ছি
!rm -rf log/

বিড়াল এবং কুকুরের ডাটাসেটের উপর ‘গ্লোবাল এভারেজ পুলিং’

শুরুতেই আমরা সাহায্য নেব ‘টেন্সর-ফ্লো’ ডাটাসেট এপিআই থেকে। কল করছি ডাটাসেট অবজেক্টের ভেতর থেকে। তবে, এটাকে দরকার মতো তিনটা টুপলে ভাগ করছি। ৮০, ১০, ১০ যার থেকে ৮০% ট্রেনিং ১০% ভ্যালিডেশন আর বাকি ১০% টেস্টসেট হিসেবে রাখবো। শুরুতে আমরা ডাটা সেটের ইনফরমেশন দেখি। আমাদের স্প্লিট অবজেক্ট ডাটাসেট লোডারকে বলছে কিভাবে ডাটাসেটকে সে তিন ভাগে ভাগ করবে। আমরা তাদেরকে ‘সুপারভাইজড লার্নিং’ মডেলের জন্য ব্যবহার করবো কিনা সেখানে ‘হ্যাঁ’ করে দিচ্ছি। এখানে আমরা ডাটা নিয়ে আসছি লেবেলসহ। কি ডাটা নিয়ে এলাম সেটা দেখি একটু?

split = (80, 10, 10)
cat_dog_spl = tfds.Split.TRAIN.subsplit(weighted=split)
(cat_train, cat_valid, cat_test), info = tfds.load('cats_vs_dogs', split=list(cat_dog_spl), with_info=True, as_supervised=True)
# ডেটাসেটের ইনফো পড়ে দেখি
print(info)
tfds.core.DatasetInfo(
name='cats_vs_dogs',
version=2.0.1,
description='A large set of images of cats and dogs.There are 1738 corrupted images that are dropped.',
urls=['https://www.microsoft.com/en-us/download/details.aspx?id=54765'],
features=FeaturesDict({
'image': Image(shape=(None, None, 3), dtype=tf.uint8),
'image/filename': Text(shape=(), dtype=tf.string),
'label': ClassLabel(shape=(), dtype=tf.int64, num_classes=2),
}),
total_num_examples=23262,
splits={
'train': 23262,
},
supervised_keys=('image', 'label'),
citation="""@Inproceedings (Conference){asirra-a-captcha-that-exploits-interest-aligned-manual-image-categorization,
author = {Elson, Jeremy and Douceur, John (JD) and Howell, Jon and Saul, Jared},
title = {Asirra: A CAPTCHA that Exploits Interest-Aligned Manual Image Categorization},
booktitle = {Proceedings of 14th ACM Conference on Computer and Communications Security (CCS)},
year = {2007},
month = {October},
publisher = {Association for Computing Machinery, Inc.},
url = {https://www.microsoft.com/en-us/research/publication/asirra-a-captcha-that-exploits-interest-aligned-manual-image-categorization/},
edition = {Proceedings of 14th ACM Conference on Computer and Communications Security (CCS)},
}""",
redistribution_info=,
)
# for image, label in cat_train.take(2):
for image, label in cat_test.take(2):
plt.figure()
plt.imshow(image)
png
png

একটা জিনিস বোঝা গেল যে, আমাদের এখানে যে দুটো ছবি দেখছি, সেগুলোর সাইজ একরকম নয়। আমাদের নতুন মডেলে ডাটা ফিড করানোর আগে ইমেজ পিক্সেল ভ্যালুগুলোকে আমরা এক রকম করে নিয়ে আসবো। তার পাশাপাশি আগের মত ছবির পিক্সেল ভ্যালুগুলোকে নর্মালাইজ করে নেব যাতে এটা ০ থেকে ১ এর মধ্যে থাকে। আমাদের এই কাজে ইমেজগুলোকে ১০০, ১০০ পিক্সেল সাইজ করে নেব tf.image.resize থেকে। ছবির সাইজ ছোট করে ফেলার কারণে অ্যাকুরেসি কমলেও ট্রেনিং এর স্পিড বাড়বে। এখানে tf.cast(image, tf.float32)ব্যবহার করছি তার দরকারি ডাটা টাইপে কনভার্ট করে সেটাকে নর্মালাইজ করব ২৫৫ দিয়ে ভাগ দিয়ে। আমাদের দরকার মতো ডাটা সেটকে ‘শাফল’ করে নেই যাতে ঠিকমতো ব্যাচ হিসেবে ট্রেইন করানো যায়। আমাদের এখানে ব্যাচ সাইজ হবে ৬৪ করে।

IMAGE_SIZE = 100
def pre_process_image(image, label):
image = tf.cast(image, tf.float32)
image = image / 255.0
image = tf.image.resize(image, (IMAGE_SIZE, IMAGE_SIZE))
return image, label
TRAIN_BATCH_SIZE = 64
cat_train = cat_train.map(pre_process_image).shuffle(1000).repeat().batch(TRAIN_BATCH_SIZE)
cat_valid = cat_valid.map(pre_process_image).repeat().batch(1000)

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

আমরা এখানে ব্যবহার করছি সিকুয়েন্সিয়াল মডেল, আগের মতো।

head = tf.keras.Sequential()
head.add(layers.Conv2D(32, (3, 3), input_shape=(IMAGE_SIZE, IMAGE_SIZE, 3)))
head.add(layers.BatchNormalization())
head.add(layers.Activation('relu'))
head.add(layers.MaxPooling2D(pool_size=(2, 2)))
head.add(layers.Conv2D(32, (3, 3)))
head.add(layers.BatchNormalization())
head.add(layers.Activation('relu'))
head.add(layers.MaxPooling2D(pool_size=(2, 2)))
head.add(layers.Conv2D(64, (3, 3)))
head.add(layers.BatchNormalization())
head.add(layers.Activation('relu'))
head.add(layers.MaxPooling2D(pool_size=(2, 2)))

‘স্ট্যান্ডার্ড ফুললি কানেক্টেড ক্লাসিফায়ার’ যোগ করছি শেষে

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

standard_classifier = tf.keras.Sequential()
standard_classifier.add(layers.Flatten())
standard_classifier.add(layers.BatchNormalization())
standard_classifier.add(layers.Dense(100))
standard_classifier.add(layers.Activation('relu'))
standard_classifier.add(layers.BatchNormalization())
standard_classifier.add(layers.Dense(100))
standard_classifier.add(layers.Activation('relu'))
standard_classifier.add(layers.Dense(1))
standard_classifier.add(layers.Activation('sigmoid'))
standard_classifier_with_do = tf.keras.Sequential()
standard_classifier_with_do.add(layers.Flatten())
standard_classifier_with_do.add(layers.BatchNormalization())
standard_classifier_with_do.add(layers.Dense(100))
standard_classifier_with_do.add(layers.Activation('relu'))
standard_classifier_with_do.add(layers.Dropout(0.5))
standard_classifier_with_do.add(layers.BatchNormalization())
standard_classifier_with_do.add(layers.Dense(100))
standard_classifier_with_do.add(layers.Activation('relu'))
standard_classifier_with_do.add(layers.Dense(1))
standard_classifier_with_do.add(layers.Activation('sigmoid'))
average_pool = tf.keras.Sequential()
average_pool.add(layers.AveragePooling2D())
average_pool.add(layers.Flatten())
average_pool.add(layers.Dense(1, activation='sigmoid'))

টেন্সর-ফ্লো ‘কল ব্যাক’

আমাদের মডেল ভালো করছে কিনা সেটা দেখার জন্য টেন্সর-ফ্লো ‘কল ব্যাক’ ফিচার অ্যাড করেছি। এখন আমাদের এই স্ট্যান্ডার্ড মডেলকে ট্রেইন করার পালা। আমাদের লসে ব্যবহার করছি ‘বাইনারি এনট্রপি’ কারণ আমাদের এখানে দুটো বাইনারি ক্লাস।

callbacks = [tf.keras.callbacks.TensorBoard(log_dir='log/{}'.format(dt.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")))]

হেড এবং ব্যাকএড যোগ করছি

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

pool_model = tf.keras.Sequential([
head,
average_pool
])
pool_model.compile(optimizer=tf.keras.optimizers.Adam(),
loss='binary_crossentropy',
metrics=['accuracy'])
callbacks = [tf.keras.callbacks.TensorBoard(log_dir='log/{}'.format(dt.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")))]
pool_model.fit(cat_train, steps_per_epoch = 23262//TRAIN_BATCH_SIZE, epochs=7,
validation_data=cat_valid, validation_steps=10, callbacks=callbacks)
Train for 363 steps, validate for 10 steps
Epoch 1/7
1/363 [..............................] - ETA: 22:23 - loss: 0.8463 - accuracy: 0.4531WARNING:tensorflow:Method (on_train_batch_end) is slow compared to the batch update (0.475070). Check your callbacks.
WARNING:tensorflow:Method (on_train_batch_end) is slow compared to the batch update (0.475070). Check your callbacks.
363/363 [==============================] - 110s 303ms/step - loss: 0.5331 - accuracy: 0.7295 - val_loss: 0.6724 - val_accuracy: 0.5919
Epoch 2/7
363/363 [==============================] - 111s 305ms/step - loss: 0.4168 - accuracy: 0.8107 - val_loss: 0.4806 - val_accuracy: 0.7724
Epoch 3/7
363/363 [==============================] - 111s 305ms/step - loss: 0.3683 - accuracy: 0.8376 - val_loss: 0.5664 - val_accuracy: 0.7423
Epoch 4/7
363/363 [==============================] - 110s 303ms/step - loss: 0.3454 - accuracy: 0.8521 - val_loss: 0.3705 - val_accuracy: 0.8421
Epoch 5/7
363/363 [==============================] - 113s 312ms/step - loss: 0.3116 - accuracy: 0.8653 - val_loss: 0.7058 - val_accuracy: 0.7020
Epoch 6/7
363/363 [==============================] - 115s 317ms/step - loss: 0.2859 - accuracy: 0.8796 - val_loss: 0.4707 - val_accuracy: 0.8017
Epoch 7/7
363/363 [==============================] - 112s 308ms/step - loss: 0.2697 - accuracy: 0.8855 - val_loss: 0.3756 - val_accuracy: 0.8392
<tensorflow.python.keras.callbacks.History at 0x7f57b9bbc2e8>

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

standard_model = tf.keras.Sequential([
head,
standard_classifier
])
standard_model.compile(optimizer=tf.keras.optimizers.Adam(),
loss='binary_crossentropy',
metrics=['accuracy'])
callbacks = [tf.keras.callbacks.TensorBoard(log_dir='log/{}'.format(dt.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")))]

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

standard_model.fit(cat_train, steps_per_epoch = 23262//TRAIN_BATCH_SIZE, epochs=10, validation_data=cat_valid, validation_steps=10, callbacks=callbacks)
Train for 363 steps, validate for 10 steps
Epoch 1/10
1/363 [..............................] - ETA: 24:23 - loss: 0.7721 - accuracy: 0.5469WARNING:tensorflow:Method (on_train_batch_end) is slow compared to the batch update (0.929957). Check your callbacks.
WARNING:tensorflow:Method (on_train_batch_end) is slow compared to the batch update (0.929957). Check your callbacks.
363/363 [==============================] - 114s 314ms/step - loss: 0.3241 - accuracy: 0.8577 - val_loss: 0.4319 - val_accuracy: 0.8124
Epoch 2/10
363/363 [==============================] - 116s 320ms/step - loss: 0.1897 - accuracy: 0.9227 - val_loss: 1.1670 - val_accuracy: 0.6750
Epoch 3/10
363/363 [==============================] - 113s 310ms/step - loss: 0.1159 - accuracy: 0.9549 - val_loss: 0.5938 - val_accuracy: 0.8165
Epoch 4/10
363/363 [==============================] - 114s 315ms/step - loss: 0.0790 - accuracy: 0.9693 - val_loss: 0.5316 - val_accuracy: 0.8480
Epoch 5/10
363/363 [==============================] - 114s 315ms/step - loss: 0.0630 - accuracy: 0.9765 - val_loss: 0.6797 - val_accuracy: 0.8180
Epoch 6/10
363/363 [==============================] - 113s 312ms/step - loss: 0.0430 - accuracy: 0.9844 - val_loss: 0.5791 - val_accuracy: 0.8404
Epoch 7/10
363/363 [==============================] - 112s 309ms/step - loss: 0.0436 - accuracy: 0.9839 - val_loss: 0.6394 - val_accuracy: 0.8444
Epoch 8/10
363/363 [==============================] - 112s 307ms/step - loss: 0.0322 - accuracy: 0.9889 - val_loss: 0.6894 - val_accuracy: 0.8105
Epoch 9/10
363/363 [==============================] - 116s 320ms/step - loss: 0.0366 - accuracy: 0.9868 - val_loss: 0.5386 - val_accuracy: 0.8485
Epoch 10/10
363/363 [==============================] - 113s 311ms/step - loss: 0.0277 - accuracy: 0.9904 - val_loss: 0.8477 - val_accuracy: 0.8287
<tensorflow.python.keras.callbacks.History at 0x7f57b8e96d68>

‘ড্রপ আউট’

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

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

standard_model_with_do = tf.keras.Sequential([
head,
standard_classifier_with_do
])
standard_model_with_do.compile(optimizer=tf.keras.optimizers.Adam(),
loss='binary_crossentropy',
metrics=['accuracy'])
callbacks = [tf.keras.callbacks.TensorBoard(log_dir='log/{}'.format(dt.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")))]

আমাদের ফাইনাল মডেলে ০.৫ এর একটা ‘ড্রপ আউট’ লেয়ার যোগ করছি ওভার ফিটিং থেকে বাঁচার জন্য।

standard_model_with_do.fit(cat_train, steps_per_epoch = 23262//TRAIN_BATCH_SIZE, epochs=7, validation_data=cat_valid, validation_steps=10,
callbacks=callbacks)
Train for 363 steps, validate for 10 steps
Epoch 1/7
1/363 [..............................] - ETA: 27:03 - loss: 0.7907 - accuracy: 0.5781WARNING:tensorflow:Method (on_train_batch_end) is slow compared to the batch update (1.172179). Check your callbacks.
WARNING:tensorflow:Method (on_train_batch_end) is slow compared to the batch update (1.172179). Check your callbacks.
363/363 [==============================] - 119s 327ms/step - loss: 0.3032 - accuracy: 0.8693 - val_loss: 0.5006 - val_accuracy: 0.8005
Epoch 2/7
363/363 [==============================] - 117s 322ms/step - loss: 0.1877 - accuracy: 0.9238 - val_loss: 0.3590 - val_accuracy: 0.8603
Epoch 3/7
363/363 [==============================] - 108s 298ms/step - loss: 0.1361 - accuracy: 0.9459 - val_loss: 0.5233 - val_accuracy: 0.8333
Epoch 4/7
363/363 [==============================] - 111s 304ms/step - loss: 0.1127 - accuracy: 0.9576 - val_loss: 0.4749 - val_accuracy: 0.8522
Epoch 5/7
363/363 [==============================] - 114s 315ms/step - loss: 0.0915 - accuracy: 0.9647 - val_loss: 0.4062 - val_accuracy: 0.8687
Epoch 6/7
363/363 [==============================] - 111s 307ms/step - loss: 0.0768 - accuracy: 0.9709 - val_loss: 0.4679 - val_accuracy: 0.8535
Epoch 7/7
363/363 [==============================] - 112s 308ms/step - loss: 0.0689 - accuracy: 0.9731 - val_loss: 0.5361 - val_accuracy: 0.8565
<tensorflow.python.keras.callbacks.History at 0x7f57b7bad940>
%tensorboard --logdir log/

চিত্রঃ স্ট্যান্ডার্ড কনভল্যুশনাল নিউরাল নেটওয়ার্ক / 'গ্যাপ' মডেলের অ্যাক্যুরেসি এবং লস

চিত্রঃ ট্রেনিং এবং ভ্যালিডেশন ফাইলের হিসেব

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

pool_model.save('gap_model.h5')
# নতুন একটা ইমেজ প্রেডিকশন করি
from tensorflow.keras.preprocessing.image import load_img
from tensorflow.keras.preprocessing import image
from tensorflow.keras.preprocessing.image import img_to_array
from tensorflow.keras.models import load_model
img_path = 'sample_image.jpg'
img = image.load_img(img_path, target_size=(200, 200))
img
png
# ইমেজটাকে লোড করি
def load_image(filename):
# ইন্টারনেট থেকে sample_image.jpg নামালাম
img = load_img(filename, target_size=(100, 100))
# অ্যারেতে কনভার্ট করলাম
img = img_to_array(img)
# মডেলের জন্য রি-শেপিং
img = img.reshape(1, 100, 100, 3)
return img
# লোড করার পর প্রেডিক্ট করি
def run_example():
# ইমেজ লোড করি
img = load_image('sample_image.jpg')
# মডেল লোড করি
model = load_model('gap_model.h5')
# ক্লাস প্রেডিক্ট করি
result = model.predict(img)
print(result[0])
# run_example() চালাই
run_example()
[0.9999999]

কি ভুল হলো?