Computer Visionপড়তে ১০ মিনিট লাগবে

কনভোলিউশনস (Convolutions)

একটি স্লাইডিং ম্যাগনিফাইং গ্লাস যা বিভিন্ন প্যাটার্ন খুঁজে বের করে
scope:কোর কনসেপ্ট (মূল ধারণা)difficulty:মাঝারি

ম্যাগনিফাইং গ্লাস বা আতশকারি কাঁচ

কল্পনা করুন আপনি একটি ছবির ওপর ছোট একটি ম্যাগনিফাইং গ্লাস বা আতশকারি কাঁচ ধরে আছেন এবং সেটিকে ছবির এক জায়গা থেকে আরেক জায়গায় ধীরে ধীরে সরাচ্ছেন। প্রতিটি জায়গায় আপনি গ্লাসের নিচের ছোট অংশটুকু খুব সূক্ষ্মভাবে দেখছেন আর নিজেকে প্রশ্ন করছেন: "এখানে কি কোনো দাগ বা সীমানা (edge) আছে? কোনা (corner) আছে? নাকি কোনো টেক্সচার আছে?"

এটাই হলো কনভোলিউশন (convolution)। এটি মূলত একটি ছোট ফিল্টার (যাকে কার্নেল বা kernel-ও বলা হয়), যা কোনো ছবির ওপর দিয়ে স্লাইড বা স্লাইড করে যায় এবং প্রতিটি জায়গায় একটা সাধারণ গাণিতিক হিসাব করে। এর ফলে নতুন একটি ছবি তৈরি হয়, যেখানে বিশেষ কিছু প্যাটার্ন ফুটে ওঠে।

এটি কীভাবে কাজ করে

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

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

আসল জাদুটা লুকিয়ে আছে এই কার্নেল ভ্যালু (kernel values) বা সংখ্যাগুলোর ভেতরে। আলাদা আলাদা সংখ্যা দিয়ে আলাদা আলাদা জিনিস খুঁজে বের করা যায়:

  • যেমন [[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]] এর মতো কার্নেল খাড়া বা লম্বালম্বি দাগ (vertical edges) খুঁজে বের করে।
  • আবার [[-1,-1,-1], [0,0,0], [1,1,1]] এর মতো কার্নেল আড়াআড়ি দাগ (horizontal edges) খোঁজে।
  • আর [[1,1,1], [1,1,1], [1,1,1]] / 9-এর মতো কার্নেল ছবিটি ঘোলা বা ব্লার (blur) করে দেয়।

কেন ছবি বা ইমেজের জন্য কনভোলিউশন পারফেক্ট

ভিজ্যুয়াল বা ছবির ডেটা নিয়ে কাজ করার ক্ষেত্রে কনভোলিউশনের এমন তিনটি বিশেষ ক্ষমতা আছে যা একে অতুলনীয় করে তোলে:

১. লোকাল কানেক্টিভিটি (Local Connectivity)

আউটপুটের প্রতিটি পিক্সেল ইনপুটের শুধু একটি ছোট বা নির্দিষ্ট এলাকার (local region) ওপর নির্ভর করে। মানুষের দেখাও ঠিক এভাবেই কাজ করে — একটা দাগ বা কোণ চিনতে হলে আপনাকে শুধু তার আশেপাশের পিক্সেলগুলোর দিকে তাকালেই হয়, ছবির একেবারে উল্টো পাশের পিক্সেল দেখার কোনো দরকার নেই।

২. ওয়েট শেয়ারিং (Weight Sharing)

পুরো ছবির ওপর একই কার্নেল বা ফিল্টার ব্যবহার করা হয়। এর মানে হলো, যে এজ ডিটেক্টর বা দাগ চেনার ফিল্টারটি ছবির ওপরের বাঁ-দিকের কোনায় কাজ করে, সেটি নিচের ডান-দিকের কোনায়ও সমানভাবে কাজ করবে। ছবির প্রতিটি জায়গার জন্য আপনাকে আলাদা আলাদা ফিল্টার বানাতে হবে না। ফুল্লি কানেক্টেড লেয়ারের (fully connected layers) তুলনায় এটি মডেলের প্যারামিটারের সংখ্যা জাদুর মতো কমিয়ে দেয়

৩. ট্রান্সলেশন ইনভ্যারিয়েন্স (Translation Invariance)

যেহেতু একই ফিল্টার পুরো ছবির ওপর দিয়ে স্লাইড করে, তাই ওপরের বাঁ-দিকে থাকা একটি বিড়াল যে ধরনের সিগন্যাল তৈরি করে, নিচের ডান-দিকে থাকা একটি বিড়ালও ঠিক একই ধরনের সিগন্যাল তৈরি করবে। এর ফলে নেটওয়ার্ক কোনো জিনিস ছবির যে জায়গাতেই থাকুক না কেন, তাকে ঠিকই চিনে ফেলতে পারে।

শুরু থেকে কনভোলিউশন কোড করা

import numpy as np
def convolve2d(image, kernel):
"""একটি ২ডি (2D) ছবিতে কনভোলিউশন কার্নেল অ্যাপ্লাই করা।"""
ih, iw = image.shape
kh, kw = kernel.shape
oh, ow = ih - kh + 1, iw - kw + 1
output = np.zeros((oh, ow))
for y in range(oh):
for x in range(ow):
# ছোট অংশটুকু বা প্যাচ (patch) কেটে কার্নেলের সাথে গুণ করা
patch = image[y:y+kh, x:x+kw]
output[y, x] = np.sum(patch * kernel)
return output
# খাড়া বা লম্বালম্বি দাগওয়ালা একটি সাধারণ 6x6 সাইজের "ছবি বা ইমেজ"
image = np.array([
[0, 0, 0, 10, 10, 10],
[0, 0, 0, 10, 10, 10],
[0, 0, 0, 10, 10, 10],
[0, 0, 0, 10, 10, 10],
[0, 0, 0, 10, 10, 10],
[0, 0, 0, 10, 10, 10],
])
# ভার্টিকাল এজ ডিটেক্টর (খাড়া দাগ চেনার ফিল্টার)
edge_kernel = np.array([
[-1, 0, 1],
[-1, 0, 1],
[-1, 0, 1]
])
# ব্লার (Blur) বা ঘোলা করার কার্নেল
blur_kernel = np.ones((3, 3)) / 9
print("আসল ছবি:")
print(image)
print("\nভার্টিকাল বা লম্বালম্বি এজ ডিটেকশন:")
edge_result = convolve2d(image, edge_kernel)
print(edge_result.astype(int))
print("\nব্লার বা ঘোলা করা ছবি:")
blur_result = convolve2d(image, blur_kernel)
print(np.round(blur_result, 1))
Output
আসল ছবি:
[[ 0  0  0 10 10 10]
 [ 0  0  0 10 10 10]
 [ 0  0  0 10 10 10]
 [ 0  0  0 10 10 10]
 [ 0  0  0 10 10 10]
 [ 0  0  0 10 10 10]]

ভার্টিকাল বা লম্বালম্বি এজ ডিটেকশন:
[[ 0 30 30  0]
 [ 0 30 30  0]
 [ 0 30 30  0]
 [ 0 30 30  0]]

ব্লার বা ঘোলা করা ছবি:
[[ 0.   0.   3.3  6.7 10.  10. ]
 [ 0.   0.   3.3  6.7 10.  10. ]
 [ 0.   0.   3.3  6.7 10.  10. ]
 [ 0.   0.   3.3  6.7 10.  10. ]]
Note: একটি ৩x৩ কার্নেলে মাত্র ৯টি শিক্ষণীয় প্যারামিটার বা লার্নেবল প্যারামিটার (learnable parameters) থাকে, অথচ এর সাহায্যে যেকোনো সাইজের বিশাল ছবিকেও স্ক্যান করা যায়। একটি ২২৪x২২৪ সাইজের পিক্সেলের ছবির প্রতিটি ইনপুট পিক্সেলকে প্রতিটি আউটপুট পিক্সেলের সাথে ফুল্লি কানেক্টেড লেয়ার দিয়ে যুক্ত করতে গেলে প্রায় ২৫০ কোটি (2.5 billion) প্যারামিটারের প্রয়োজন হবে। কনভোলিউশন ঠিক একই কাজ করে খুব সামান্য কিছু প্যারামিটার ব্যবহার করেই — আর এ কারণেই এটি এতো বেশি কার্যকর ও প্যারামিটার-দক্ষ।

সাধারণ ফিল্টারের গণ্ডি পেরিয়ে

ক্লাসিক কম্পিউটার ভিশন বা আগের যুগে, গবেষকরা প্রতিটি নির্দিষ্ট কাজের জন্য নিজের হাতে কার্নেল ডিজাইন করতেন (যেমন দাগ চেনার জন্য Sobel, বা ছবি ঘোলা করার জন্য Gaussian কার্নেল)। কিন্তু ডিপ লার্নিংয়ের জাদুতে, নেটওয়ার্ক ট্রেনিং করার সময় নিজেই এই কার্নেলের মানগুলো শিখে নেয়

নেটওয়ার্কগুলো একদম র‍্যান্ডম বা এলোমেলো কার্নেল নিয়ে কাজ শুরু করে এবং ব্যাকপ্রোপাগেশন (backpropagation)-এর মাধ্যমে ধীরে ধীরে সেগুলো ঠিক বা অ্যাডজাস্ট করতে থাকে, যতক্ষণ না সেগুলো ওই নির্দিষ্ট কাজের জন্য সবচেয়ে দরকারি প্যাটার্নগুলো ধরতে পারে। শুধু মানুষের চেহারা দিয়ে ট্রেইন করানো একটি নেটওয়ার্ক হয়তো চোখ, নাক আর মুখ চেনার জন্য আলাদা আলাদা কার্নেল শিখে ফেলবে। আবার প্রাকৃতিক দৃশ্য দিয়ে ট্রেন করালে সেটা আকাশের রঙের পরিবর্তন বা গাছের পাতার টেক্সচার ধরার জন্য নিজের মতো করে কার্নেল বানিয়ে নেবে।

এখানেই সবচেয়ে বড় ও অসাধারণ ব্যাপারটা লুকিয়ে আছে: আপনাকে ফিল্টারগুলো ডিজাইন করতে হবে না — ডেটাই নিজে নিজে নেটওয়ার্ককে শিখিয়ে দেবে যে তার আসলে কী খোঁজা উচিত।

ছোট কুইজ

কনভোলিউশন কার্নেলের কাজ কী?
Challenge

পড়া চালিয়ে যান