অধ্যায় 2 · ভেক্টর ও ম্যাট্রিক্স
ডট প্রোডাক্ট ও কোসাইন সিমিলারিটি
- পৃষ্ঠা 3 / 17
- 3 মিনিট পড়া
ডট প্রোডাক্ট AI-তে সবচেয়ে বেশি ব্যবহৃত একক অপারেশন। নিউরাল নেটওয়ার্কের প্রতিটা লেয়ার ডট প্রোডাক্ট দিয়ে গড়া, আর প্রতিটা সিমান্টিক সার্চ একটা দিয়েই ডকুমেন্ট সাজায়। ব্যাপারটা সহজ: মিলে যাওয়া উপাদানগুলো গুণ করুন, তারপর যোগ করুন।
import numpy as np
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
print(a * b) # উপাদান ধরে ধরে
print(np.sum(a * b)) # সেগুলো যোগ করলে: ডট প্রোডাক্ট
print(a @ b) # একই জিনিস, @ দিয়ে লেখা
print(np.dot(a, b)) # আবারও[ 4 10 18]
32
32
32১×৪ + ২×৫ + ৩×৬ = ৩২। NumPy-তে লিখুন a @ b।
ডট প্রোডাক্ট কী বলে
দুটো ভেক্টর একই দিকে মুখ করে থাকলে ডট প্রোডাক্ট বড় আর ধনাত্মক, সমকোণে থাকলে শূন্য (তাদের মধ্যে কোনো মিল নেই), আর উল্টো দিকে থাকলে ঋণাত্মক। ভেক্টরের দৈর্ঘ্যের সাথে এর মানও বাড়ে। শুধু দিক তুলনা করতে দুই দৈর্ঘ্য দিয়ে ভাগ করুন। ফলাফল হলো কোসাইন সিমিলারিটি, সবসময় −১ থেকে ১-এর মধ্যে:
cosine similarity(a, b) = (a · b) / (‖a‖ × ‖b‖)import numpy as np
pairs = {
"same direction": (np.array([1, 1]), np.array([3, 3])),
"at right angles": (np.array([1, 0]), np.array([0, 5])),
"opposite": (np.array([1, 2]), np.array([-2, -4])),
}
for name, (a, b) in pairs.items():
cos = a @ b / (np.linalg.norm(a) * np.linalg.norm(b))
angle = np.degrees(np.arccos(np.clip(cos, -1, 1)))
print(f"{name:16} cosine {cos:+.2f} angle {angle:.0f}°")same direction cosine +1.00 angle 0°
at right angles cosine +0.00 angle 90°
opposite cosine -1.00 angle 180°খেয়াল করুন [1, 1] আর [3, 3]-এর কোসাইন ১, যদিও একটা তিন গুণ লম্বা। লেখার ক্ষেত্রে ঠিক এটাই দরকার: একই বিষয়ের একটা লম্বা আর একটা ছোট ডকুমেন্ট একই রকম গণ্য হওয়া উচিত।
দশ লাইনে সিমান্টিক সার্চ
প্রতিটা RAG সিস্টেম আর প্রতিটা "অর্থ দিয়ে খোঁজা" ফিচারের মূল এটাই। প্রতিটা ডকুমেন্ট আর প্রশ্নকে এমবেডিংয়ে বদলানো হয়; তারপর প্রশ্নের সাথে কোসাইন সিমিলারিটি অনুযায়ী ডকুমেন্ট সাজানো হয়:
import numpy as np
def cosine_similarity(a, b):
return (a @ b) / (np.linalg.norm(a) * np.linalg.norm(b))
# বানানো ৪-সংখ্যার এমবেডিং; আসলগুলোতে ৭৬৮ থেকে ৩,০৭২টা সংখ্যা
docs = {
"How do I get a refund?": np.array([0.90, 0.10, 0.05, 0.20]),
"Return an item for my money back": np.array([0.80, 0.20, 0.10, 0.25]),
"When does my parcel arrive?": np.array([0.10, 0.90, 0.15, 0.10]),
"Reset my password": np.array([0.05, 0.10, 0.95, 0.05]),
}
question = np.array([0.85, 0.15, 0.05, 0.22]) # "টাকা কি ফেরত পাব?"
ranked = sorted(docs, key=lambda d: cosine_similarity(question, docs[d]), reverse=True)
for d in ranked:
print(f"{cosine_similarity(question, docs[d]):.3f} {d}")0.998 How do I get a refund?
0.995 Return an item for my money back
0.303 When does my parcel arrive?
0.136 Reset my password"Return an item for my money back" ওপরের দিকে আসে, যদিও "Can I get my money back?"-এর সাথে প্রায় কোনো শব্দই মেলে না — কারণ তাদের এমবেডিং একই দিকে মুখ করে আছে। অর্থ দিয়ে খোঁজা আর কিওয়ার্ড দিয়ে খোঁজার পার্থক্য এটাই।
- অনেক এমবেডিং API আগে থেকেই দৈর্ঘ্য ১-এ নরমালাইজ করা ভেক্টর দেয়। তখন কোসাইন সিমিলারিটি শুধু ডট প্রোডাক্ট, যা দ্রুততর:
question @ doc। - লাখ লাখ ডকুমেন্টের জন্য ভেক্টর ডেটাবেস চতুর ইনডেক্স ব্যবহার করে, যাতে প্রতিটার সাথে তুলনা না করেই সেরা মিলগুলো পাওয়া যায় (
O(n)কেন গুরুত্বপূর্ণ, তা AI-এর জন্য Python-এর পাতা ১৯-এ)।
নিজে চেষ্টা করুন
[2, 0, 1]আর[1, 3, 2]-এর ডট প্রোডাক্ট হাতে হিসাব করুন, তারপর@দিয়ে।- প্রতিটা ডকুমেন্ট ভেক্টর আর প্রশ্নকে নরমালাইজ করুন, তারপর শুধু
@দিয়ে সাজান। ক্রম কি একই? - এমন দুটো ভেক্টর খুঁজুন, যাদের কোসাইন সিমিলারিটি ঠিক ০।