অধ্যায় 4 · ডেটার জন্য Python
NumPy: অ্যারেতে দ্রুত হিসাব
- পৃষ্ঠা 13 / 20
- 5 মিনিট পড়া
মেশিন লার্নিং মানে সংখ্যার বড় বড় টেবিলের ওপর গণিত: একটা ছবি পিক্সেলের মানের একটা গ্রিড, একটা বাক্য হয়ে যায় সংখ্যার একটা তালিকা যার নাম এমবেডিং, একটা মডেল হলো ওয়েট নামের লক্ষ লক্ষ সংখ্যা। Python লুপ দিয়ে এই গণিত করলে অনেক বেশি ধীর হতো। NumPy — "Numerical Python" — দেয় অ্যারে: সংখ্যার একটা দ্রুতগতির ব্লক, যার ওপর একসাথে কাজ করা যায়। pandas, scikit-learn, PyTorch আর প্রায় সব ডেটা লাইব্রেরি এর ধারণার ওপর তৈরি।
ইনস্টল করুন python -m pip install numpy দিয়ে। প্রথা অনুযায়ী এটা সবসময় np নামে ইমপোর্ট করা হয়।
অ্যারে
import numpy as np
scores = np.array([72, 85, 90, 64, 78])
print(scores)
print(scores.shape, scores.dtype)
print(scores + 5) # প্রতিটা উপাদানে যোগ হয়
print(scores * 1.1)
print(scores.mean(), scores.max(), scores.std().round(2))[72 85 90 64 78]
(5,) int64
[77 90 95 69 83]
[79.2 93.5 99. 70.4 85.8]
77.8 90 9.22প্রতিটা অ্যারের একটা shape (প্রতিটা দিকে তার আকার) আর একটা dtype (সব উপাদানের টাইপ — পুরো অ্যারের জন্য একটাই টাইপ, যা এর দ্রুততার একটা কারণ) থাকে। অপারেশনগুলো সব উপাদানে একসাথে প্রয়োগ হয়; একে বলে ভেক্টরাইজেশন। কোনো লুপ লিখতে হয় না, আর কাজটা চলে অপ্টিমাইজ করা C কোডে — সাধারণত লিস্টের ওপর Python লুপের চেয়ে দশ থেকে শতগুণ দ্রুত।
অ্যারে আর লিস্ট এক নয়
import numpy as np
prices = [100, 200, 300]
print(prices * 2) # লিস্ট নিজেকেই পুনরাবৃত্তি করে
print(np.array(prices) * 2) # অ্যারে প্রতিটা উপাদান গুণ করে[100, 200, 300, 100, 200, 300]
[200 400 600]দুই মাত্রা: সারি আর কলাম
2-D অ্যারে হলো একটা টেবিল। [row, column] দিয়ে ইনডেক্স করুন; কোলন : মানে "সব":
import numpy as np
# ৩ জন শিক্ষার্থী × ৪টা পরীক্ষা
marks = np.array([
[70, 82, 91, 65],
[88, 79, 94, 90],
[55, 61, 72, 58],
])
print(marks.shape) # (সারি, কলাম)
print(marks[1]) # সারি 1: দ্বিতীয় শিক্ষার্থী
print(marks[:, 2]) # কলাম 2: সবার তৃতীয় পরীক্ষা
print(marks[0, 3]) # সারি 0, কলাম 3
print(marks.mean(axis=1)) # প্রতি শিক্ষার্থীর গড় (কলাম জুড়ে)
print(marks.mean(axis=0)) # প্রতি পরীক্ষার গড় (সারি বরাবর)(3, 4)
[88 79 94 90]
[91 94 72]
65
[77. 87.75 61.5 ]
[71. 74. 85.66666667 71. ]axis আর্গুমেন্ট প্রথমে সবাইকেই গুলিয়ে দেয়। ভাবুন "যে দিকটা গুটিয়ে যায়": axis=0 সারিগুলো একসাথে চেপে ধরে (প্রতি কলামে একটা ফলাফল), axis=1 কলামগুলো চেপে ধরে (প্রতি সারিতে একটা ফলাফল)।
বুলিয়ান মাস্ক: লুপ ছাড়াই ছাঁকা
অ্যারের ওপর তুলনা করলে পাওয়া যায় True/False-এর একটা অ্যারে — একটা মাস্ক। মাস্ক দিয়ে ইনডেক্স করলে শুধু মিলে যাওয়া উপাদানগুলো থাকে। একটা মডেলের আত্মবিশ্বাসী অনুমানগুলো এভাবেই রাখা হয়:
import numpy as np
confidences = np.array([0.91, 0.42, 0.77, 0.30, 0.88])
labels = np.array(["cat", "dog", "cat", "bird", "dog"])
sure = confidences > 0.75 # True/False-এর একটা অ্যারে
print(sure)
print(labels[sure]) # শুধু True যেখানে, সেগুলো রাখো
print(sure.sum(), "confident predictions")
print(np.where(confidences > 0.75, labels, "unsure"))[ True False True False True]
['cat' 'cat' 'dog']
3 confident predictions
['cat' 'unsure' 'cat' 'unsure' 'dog']ব্রডকাস্টিং আর অ্যারে তৈরি
আকার আলাদা হলে NumPy ছোট অ্যারেটাকে বড়টার ওপর ব্রডকাস্ট করে, যদি ডান দিক থেকে আকারগুলো মেলে। এখানে দুটো বোনাসের একটা সারি প্রত্যেক শিক্ষার্থীর ওপর বসানো হয়েছে। অ্যারে টাইপ না করে প্রায়ই বানিয়েও নেবেন:
import numpy as np
marks = np.array([[70, 82], [88, 79], [55, 61]])
bonus = np.array([5, 0]) # শুধু প্রথম পরীক্ষায় +5
print(marks + bonus) # সারিটা প্রত্যেক শিক্ষার্থীর ওপর "টেনে" বসানো হয়
rng = np.random.default_rng(42) # seed দেওয়া এলোমেলো জেনারেটর
noise = rng.normal(0, 1, size=(2, 3)).round(2)
print(noise)
print(np.zeros((2, 3)), np.arange(0, 10, 3), np.linspace(0, 1, 5))[[75 82]
[93 79]
[60 61]]
[[ 0.3 -1.04 0.75]
[ 0.94 -1.95 -1.3 ]]
[[0. 0. 0.]
[0. 0. 0.]] [0 3 6 9] [0. 0.25 0.5 0.75 1. ]np.random.default_rng(42) হলো এলোমেলো সংখ্যা পাওয়ার আধুনিক উপায়; seed সেগুলোকে পুনরাবৃত্তিযোগ্য রাখে, ঠিক পাতা ৯-এর মতো।
AI-এর জন্য কেন জরুরি: অর্থের মিল
AI সিস্টেম লেখাকে এমবেডিং ভেক্টর-এ বদলায়, এমনভাবে সাজিয়ে যে কাছাকাছি অর্থের লেখাগুলো কাছাকাছি দিকে নির্দেশ করে। কোসাইন সিমিলারিটি মাপে দুটো ভেক্টর কতটা একই দিকে নির্দেশ করছে: 1.0 মানে একই দিক, 0-এর কাছে মানে সম্পর্কহীন। সিমান্টিক সার্চ আর RAG (retrieval-augmented generation)-এর কেন্দ্রে এটাই। NumPy-তে এটা এক লাইন — @ হলো ডট প্রোডাক্ট:
import numpy as np
# ধরে নেওয়া এমবেডিং: আসলগুলোতে শত শত বা হাজার হাজার সংখ্যা থাকে।
sentences = ["How do I reset my password?", "I forgot my login password", "What is the price of the pro plan?"]
vectors = np.array([
[0.90, 0.10, 0.05],
[0.85, 0.20, 0.10],
[0.05, 0.10, 0.95],
])
def cosine_similarity(a, b):
return a @ b / (np.linalg.norm(a) * np.linalg.norm(b))
query = vectors[0]
for sentence, vector in zip(sentences, vectors):
print(f"{cosine_similarity(query, vector):.3f} {sentence}")1.000 How do I reset my password?
0.991 I forgot my login password
0.118 What is the price of the pro plan?পাসওয়ার্ডের দুটো প্রশ্নে মিল-শব্দ কম, তবু স্কোর 1-এর কাছাকাছি; দামের প্রশ্নের স্কোর কম। এই তিনটা বানানো ভেক্টরের জায়গায় API থেকে আসল এমবেডিং বসালেই এটা আপনার ডকুমেন্টের জন্য একটা কাজের সার্চ ইঞ্জিন।
নিজে চেষ্টা করুন
- ৭ দিনের তাপমাত্রার একটা অ্যারে বানান আর গড়ের চেয়ে বেশি এমন দিনগুলোর (ইনডেক্স) প্রিন্ট করুন।
np.arange(1, 10).reshape(3, 3)দিয়ে 1–9 সংখ্যার একটা 3×3 অ্যারে বানান আর প্রতি কলামের যোগফল প্রিন্ট করুন।- সিমিলারিটির উদাহরণে চতুর্থ একটা বাক্য আর ভেক্টর যোগ করুন, আর
argmax()দিয়ে তার সবচেয়ে কাছের বাক্যটা খুঁজুন।