Chapter 9 of 28
Convolution, pooling, flatten, and dense layers up close
একটি CNN মূলত "কনভোলিউশন এবং পুলিং লেয়ারের একটি স্তুপ" — এ কথা জানাটা অনেকটা এই তথ্য জানার মতো যে একটি গাড়িতে "ইঞ্জিন এবং চাকা থাকে"। কথাটি সত্য, কিন্তু নিজে একটি গাড়ি তৈরি করার জন্য, অথবা সেটি নষ্ট হয়ে গেলে মেরামত করার জন্য এইটুকু জানা যথেষ্ট নয়। একটি CNN-এর প্রতিটি লেয়ারের প্রকারভেদে বেশ কিছু সুনির্দিষ্ট ডিজাইন বা নকশা বেছে নিতে হয় — যেমন কার্নেলের আকার বা সাইজ, স্ট্রাইড, প্যাডিং, কোন ধরনের পুলিং ব্যবহার করা হবে, এবং ঠিক কোন জায়গায় গিয়ে ফ্ল্যাটেন করা হবে — আর এই সিদ্ধান্তগুলোর প্রতিটিরই ডেটার আকৃতি (shape) এবং নেটওয়ার্কের শেখার মানের ওপর সরাসরি ও অনুমানযোগ্য প্রভাব রয়েছে।
এই চ্যাপ্টারটি মূলত সেই সব লেয়ারের ধরণের একটি ক্লোজ-আপ ট্যুর বা পুঙ্খানুপুঙ্খ বিবরণ, যা জুড়ে দিয়ে আপনি বাস্তবে একটি আস্ত CNN তৈরি করবেন: প্রতিটি লেয়ার তার ইনপুটের সাথে ঠিক কী করে, এর প্যারামিটারের খরচ কেমন এবং কখন কোন লেয়ারটি ব্যবহার করা উচিত।
একটি CNN-কে কল্পনা করুন একটি কারখানার অ্যাসেম্বলি লাইনের মতো, যার কাজ হলো একটি ছবিকে শেষমেশ একটি সিদ্ধান্তে রূপান্তর করা। এই লাইনের শুরুতে, কয়েকটি স্টেশন একটি করে ছোট স্টেঞ্চিল বা ছাঁচ (একটি কার্নেল) ছবির ওপর ধরে এবং যেখানে যেখানে ছাঁচের ভেতরের ডিজাইন বা প্যাটার্নটি খুব তীব্রভাবে ফুটে ওঠে তা নোট করে নেয় — এটিই হলো কনভোলিউশন (convolution)। নির্দিষ্ট দূরত্ব পরপর, আরেকটি স্টেশন এক বিশাল পরিমাপের স্তুপকে ছোট ও সহজে সামলানো যায় এমন স্তুপে সংকুচিত করে ফেলে, যেখানে শুধুমাত্র সবচেয়ে গুরুত্বপূর্ণ তথ্যটি রেখে দেওয়া হয় — এটিই পুলিং (pooling)। শেষমেশ, সমস্ত তথ্যের স্তুপকে একটি লম্বা তালিকায় ঢেলে সোজা করে ফেলা হয় — যাকে বলা হয় ফ্ল্যাটেন (flatten) — এবং সিদ্ধান্ত গ্রহণকারীদের একটি ছোট কমিটির কাছে হস্তান্তর করা হয় যারা প্রতিটি পরিমাপকে একে অপরের সাথে বিচার করে একটি রায় দেয় — এটিই হলো fully connected বা ডেন্স লেয়ার। প্রতিটি স্টেশনের একটি সুনির্দিষ্ট কাজ, একটি সুনির্দিষ্ট কম্পিউটেশনাল খরচ এবং বেশ কয়েকটি নড়াচড়া করার মতো বোতাম বা ডায়াল রয়েছে।
যেকোনো নির্দিষ্ট লেয়ারের খুঁটিনাটিতে যাওয়ার আগে, এই মানচিত্রটি মাথায় রাখুন:
একটি কনভোলিউশন লেয়ারে সংখ্যক লার্নেবল ফিল্টার থাকে, যার প্রতিটির আকার । এটি আকারের ইনপুটের ওপর প্রতিটি ফিল্টারকে স্লাইড করে আকারের একটি আউটপুট তৈরি করে।
যেখানে: হলো ইনপুটের উচ্চতা, হলো ফিল্টারের উচ্চতা, হলো প্রতি পাশে যোগ করা প্যাডিং, এবং হলো স্ট্রাইড। প্রস্থ বা width ভ্যারিয়েবলগুলো বসালে এই একই সমীকরণ প্রদান করে।
সহজ কথা: প্যাডিংয়ের প্রতি অতিরিক্ত ইউনিট মূলত সীমানা থেকে একটি করে সারি বা কলাম ফিরিয়ে আনে যা কার্নেল অন্যথায় "খেয়ে ফেলত"; আর স্ট্রাইডের প্রতি অতিরিক্ত ইউনিট পজিশনগুলোকে লাফিয়ে পার হতে সাহায্য করে যার ফলে আউটপুট দ্রুত ছোট হয়ে আসে। এই সমীকরণটিই আপনার দেখা প্রতিটি আর্কিটেকচার ডায়াগ্রামের পেছনের আসল পাটিগণিত — এটি দিয়েই মূলত লেয়ারের সাইজগুলোর কানেকশন চেক করা হয়।
কার্নেল হলো একটি ফিল্টারের ভেতরে থাকা লার্নেবল ওয়েটের ছোট ম্যাট্রিক্স — সাধারণত সাইজের, তবে কখনো কখনো , , বা হতে পারে। আধুনিক আর্কিটেকচারগুলো একটি বড় কার্নেল ব্যবহার করার চেয়ে একাধিক ছোট ছোট কার্নেলকে একটার ওপর আরেকটা সাজানো বা স্ট্যাক করা বেশি পছন্দ করে। কারণ দুটি লেয়ার একটিমাত্র লেয়ারের সমান স্থানিক এলাকা (receptive field) কভার করে, অথচ এতে parámetros বা প্যারামিটার সংখ্যা অনেক কম লাগে এবং মাঝখানে বাড়তি একটি নন-লিনিয়ার অ্যাক্টিভেশন ফাংশন ব্যবহার করার সুযোগ পাওয়া যায়।
ফিচার ম্যাপ হলো পুরো ইনপুটের ওপর একটি ফিল্টার স্লাইড বা প্রয়োগ করার পর প্রাপ্ত ২D গ্রিড — যা মূলত নির্দেশ করে "ছবির এই পজিশনে প্যাটার্নটি ঠিক কতটুকু মিলেছে"। সবগুলো ফিল্টারের আউটপুট একসাথে স্তুপ করলে আমরা আউটপুট টেন্সরের চ্যানেল ডাইমেনশন পাই: বেশি ফিল্টারের অর্থ হলো বেশি ফিচার ম্যাপ, যা ইনপুট সম্পর্কে আরও সমৃদ্ধ ও উচ্চ-মাত্রার বিবরণ তৈরি করে।
স্ট্রাইড নিয়ন্ত্রণ করে ফিল্টার বসানোর প্রতি ধাপে কার্নেলটি ঠিক কত পিক্সেল করে লাফ দেবে। ১ স্ট্রাইড হলো ঘন স্লাইডিং — যা ফিচার এক্সট্র্যাক্ট করার জন্য ডিফল্ট পছন্দ, কারণ এটি ছবির কোনো অংশ বাদ দেয় না। ২ স্ট্রাইড আউটপুটের স্থানিক আকারকে প্রায় অর্ধেক করে ফেলে, এবং কখনো delicacies বা পুলিং লেয়ারের একটি হালকা বিকল্প হিসেবে ব্যবহৃত হয়।
"Valid" প্যাডিং ছবিতে কোনো অতিরিক্ত সীমানা যোগ করে না, যার ফলে প্রতিটি কনভোলিউশন ধাপে আউটপুটের সাইজ ছোট হতে থাকে। আর "Same" প্যাডিং ইনপুটের সীমানায় ঠিক ততগুলো শূন্য বা zeros যোগ করে যাতে আউটপুটের আকার ইনপুটের সমান থাকে — যেমন ১ স্ট্রাইডে কার্নেলের জন্য প্রতি পাশে এক পিক্সেল করে জিরো-প্যাডিং প্রয়োজন হয়।

পুলিং সবচেয়ে গুরুত্বপূর্ণ তথ্যগুলো ধরে রেখে ফিচার ম্যাপের স্থানিক বা স্পেশাল আকার সংকুচিত করে। এর কোনো লার্নেবল প্যারামিটার থাকে না — এটি একটি সম্পূর্ণ নির্দিষ্ট ও গাণিতিক অপারেশন।
| দিক বা Aspect | Max Pooling | Average Pooling |
|---|---|---|
| অপারেশন | উইন্ডোর ভেতরের সর্বোচ্চ মানটি নেয় | উইন্ডোর ভেতরের মানগুলোর গড় নেয় |
| প্রভাব | সবচেয়ে স্পষ্ট ও তীক্ষ্ণ ফিচারগুলো (কিনারা) ধরে রাখে | ফিচার ম্যাপকে মসৃণ করে এবং সামগ্রিক ট্রেন্ড ধরে রাখে |
| কমন ব্যবহার | ফিচার এক্সট্র্যাক্টরের ভেতরে সবচেয়ে জনপ্রিয় পছন্দ | আর্কিটেকচারের একেবারে শেষে, ক্লাসিফিকেশনের আগে Global Average Pooling হিসেবে ব্যবহৃত হয় |
| নয়েজের সংবেদনশীলতা | একটিমাত্র বড় ও ভুল মান বা নয়েজের কারণে ভুল সিদ্ধান্ত দিতে পারে | আউটলায়ার ও নয়েজের ক্ষেত্রে তুলনামূলক বেশি স্থিতিশীল |
প্রতিটি উইন্ডো নিয়ে কাজ করলে: ওপর-বাম উইন্ডো থেকে সর্বোচ্চ মান আসে ; ওপর-ডান উইন্ডো থেকে আসে ; নিচে-বাম উইন্ডো থেকে আসে ; এবং নিচে-ডান উইন্ডো থেকে আসে । এভাবে একটি ম্যাপ প্রতি অংশের সবচেয়ে শক্তিশালী অ্যাক্টিভেশনটি ধরে রেখে আকারে সংকুচিত হয়েছে।
Flatten একটি baggage বা বহুমাত্রিক ফিচার টেন্সরকে (যেমন আকারের) একটি একক এক-মাত্রিক বা 1D ভেক্টরে (এখানে, দৈর্ঘ্যের) রূপান্তর বা রি-শেপ করে, যাতে সেটিকে fully connected লেয়ারে পাঠানো যায়।
সহজ কথা: Flatten নিজে কোনো হিসাব করে না — এর কোনো লার্নেবল প্যারামিটার নেই এবং এটি ম্যাট্রিক্সের হিসাবের বাইরে কোনো পাটিগণিত রান করে না। এর একমাত্র কাজ হলো স্থানিক ও চ্যানেল-ভিত্তিক রিপ্রেজেন্টেশনকে ডেন্স লেয়ারের উপযোগী সোজা ভেক্টরে রূপান্তর করা।
কনভোলিউশন এবং পুলিং যখন ছবি থেকে সমৃদ্ধ ও গুরুত্বপূর্ণ ফিচারগুলো এক্সট্র্যাক্ট করে নেয়, তখন এক বা একাধিক fully connected লেয়ার সেগুলোকে একত্রিত করে সামগ্রিক ছবি নিয়ে চিন্তা করে এবং চূড়ান্ত ক্লাস স্কোর তৈরি করে। এটি কনভোলিউশন থেকে সম্পূর্ণ আলাদা এক ধরনের হিসাব: একটি কনভোলিউশন ফিল্টার শুধুমাত্র একটি ছোট উইন্ডোর দিকে তাকায়, কিন্তু ডেন্স লেয়ারের প্রতিটি নিউরন ছবির এক্সট্র্যাক্ট করা প্রতিটি ফিচারের ওপর একযোগে চোখ বোলায়। এই ধাপেই মূলত ছবির ভেতরের চেনা প্যাটার্নগুলোর ওপর ভিত্তি করে চূড়ান্ত ক্লাসিফিকেশনের সিদ্ধান্ত নেওয়া হয়।
সবচেয়ে শেষের লেয়ারের অ্যাক্টিভেশন ফাংশনটি সম্পূর্ণভাবে নির্ভর করে কাজের ধরনের ওপর:
import numpy as np
def conv2d_forward(X, K, stride=1, padding=0):
"""একক চ্যানেলের 2D কনভোলিউশন ফরওয়ার্ড পাস।"""
if padding > 0:
X = np.pad(X, ((padding, padding), (padding, padding)))
H, W = X.shape
Fh, Fw = K.shape
H_out = (H - Fh) // stride + 1
W_out = (W - Fw) // stride + 1
Z = np.zeros((H_out, W_out))
for i in range(H_out):
for j in range(W_out):
r, c = i * stride, j * stride
window = X[r:r + Fh, c:c + Fw]
Z[i, j] = np.sum(window * K)
return Z
def max_pool_forward(A, pool_size=2, stride=2):
H, W = A.shape
H_out = (H - pool_size) // stride + 1
W_out = (W - pool_size) // stride + 1
P = np.zeros((H_out, W_out))
for i in range(H_out):
for j in range(W_out):
r, c = i * stride, j * stride
P[i, j] = np.max(A[r:r + pool_size, c:c + pool_size])
return P
def flatten(A):
return A.reshape(-1)
# ছোট একটি এন্ড-টু-এন্ড টেস্ট
X = np.array([[1, 3, 2, 4], [5, 6, 1, 2], [7, 2, 0, 1], [3, 4, 5, 2]], dtype=float)
K = np.array([[1, 0], [0, -1]], dtype=float) # একটি সাধারণ এজ ফিল্টার
feature_map = conv2d_forward(X, K, stride=1, padding=0)
pooled = max_pool_forward(feature_map, pool_size=2, stride=1)
vector = flatten(pooled)
print("Feature map shape:", feature_map.shape)
print("Pooled shape:", pooled.shape)
print("Flattened vector:", vector)কোডটির কয়েকটি বিশেষ দিক লক্ষ্য করুন:
conv2d_forward গাণিতিকভাবে ক্রস-কোরিলেশন রান করে, কোনো কার্নেল ফ্লিপ ছাড়া — যা বাস্তব ফ্রেমওয়ার্কগুলোর আচরণের সাথে হুবহু মিলে যায়।max_pool_forward-এর জন্য কোনো ওয়েট ইনিশিয়ালাইজ করতে হয় না — কনভোলিউশন ফিল্টার K-এর মতো পুলিং লেয়ারে কোনো কিছু শেখার বা আপডেট করার নেই।flatten হলো স্রেফ এক লাইনের reshape, যা প্রমাণ করে এটি নিজে কোনো অতিরিক্ত হিসাব ছাড়াই শুধু ছবির স্পেশাল ডাইমেনশনকে ডেন্স লেয়ারের উপযোগী ভেক্টরে রূপান্তর করার ব্রিজ বা সেতু হিসেবে কাজ করে।নিজেকে প্রশ্ন করুন: "কোন কোন CNN লেয়ারের লার্নেবল প্যারামিটার আছে এবং কোনগুলোর নেই?" Convolution, Fully Connected এবং Batch Normalization লেয়ারগুলোর প্যারামিটার আছে। Pooling, Flatten এবং বেশিরভাগ সাধারণ অ্যাক্টিভেশন ফাংশনের (ReLU-র নেই, তবে PReLU-র আছে) কোনো প্যারামিটার নেই।
নেটওয়ার্কের প্রতিটি লেয়ারই বোধহয় কোনো না কোনোভাবে "শেখে" — এমনটা ভাবা খুব স্বাভাবিক। তবে পুলিং এবং ফ্ল্যাটেন তা করে না; এগুলো ফিক্সড বা নির্দিষ্ট অপারেশন। ব্যাকপ্রোপাগেশন এদের ভেতর দিয়ে গ্রেডিয়েন্ট প্রবাহিত করে মাত্র, অপ্টিমাইজারের আপডেট করার মতো কোনো ওয়েট এদের ভেতরে থাকে না।
নিজে হাতে লেয়ারগুলো একটার ওপর আরেকটা সাজানোর সময় কোন লেয়ারে "valid" এবং কোন লেয়ারে "same" প্যাডিং ব্যবহৃত হচ্ছে তা ভুলে যাওয়া অত্যন্ত কমন একটি ডাইমেনশন বা shape-mismatch ভুলের কারণ। পরবর্তী লেয়ার কানেক্ট করার আগে সবসময় আউটপুট সাইজের ফর্মুলাটি রান করে নিশ্চিত হয়ে নিন।
যেকোনো বাস্তব বা প্রোডাকশন CNN মডেলের দিকে তাকালে — তা ছোট কোনো কাস্টম ক্লাসিফায়ার হোক বা ResNet বা EfficientNet-এর মতো বড় আর্কিটেকচার হোক — আপনি এই উপাদানগুলোকেই বিভিন্ন বিন্যাস, গভীরতা ও প্রস্থে সাজানো অবস্থায় দেখতে পাবেন। প্রতিটি লেয়ারের অবদান এবং প্যারামিটারের কম্পিউটেশনাল খরচ খুব নিখুঁতভাবে জানাটাই মূলত আপনাকে যেকোনো আর্কিটেকচার ডায়াগ্রাম দেখে তাদের পেছনের ডিজাইন ও সুবিধা-অসুবিধাগুলো সাথে সাথে চিনে ফেলতে সাহায্য করবে — এবং নিজের স্ক্র্যাচ থেকে মডেল ডিজাইন করার সময় এই জ্ঞানই সবচেয়ে বেশি প্রয়োজন হবে।