পাঠ ২০ · ৫৭-এর মধ্যে · মডিউল ৪
Home / Courses / Numerical Methods / লিস্ট-স্কয়ার্স ফিটিং

লিস্ট-স্কয়ার্স কার্ভ ফিটিং ও লিনিয়ার রিগ্রেশন

Least-squares curve fitting & linear regression
১০ মিনিট পড়া মধ্যম · Intermediate Python কোডসহ সম্পূর্ণ বাংলায়

এই পাঠে যা শিখবেন

  • ইন্টারপোলেশন ও কার্ভ ফিটিং-এর মধ্যে মৌলিক পার্থক্য — "ঠিক দিয়ে যাওয়া" বনাম "সবচেয়ে ভালো ফিট"
  • লিস্ট-স্কয়ার্স এরর মেট্রিক কেন বেছে নেওয়া হয়, এবং কীভাবে এটি নরমাল ইকুয়েশনে পরিণত হয়
  • Python-এ হাতে-লেখা নরমাল ইকুয়েশন সমাধান করে লিনিয়ার রিগ্রেশন বাস্তবায়ন করা
  • রেসিডুয়াল সাম অফ স্কয়ার্স গণনা করে ফিটের মান পরিমাপ করা

১ · ইন্টারপোলেশন বনাম কার্ভ ফিটিং

M4-এর আগের চারটি পাঠে (L16-L19) আমরা এমন ফাংশন খুঁজেছি যা প্রতিটি ডেটা পয়েন্টের মধ্য দিয়ে ঠিক যায়। কিন্তু বাস্তব-বিশ্বের ডেটা প্রায়ই নয়েজি — পরিমাপ যন্ত্রের ত্রুটি, র‍্যান্ডম ওঠানামা, বা অসম্পূর্ণ মডেলের কারণে। এমন ডেটায় প্রতিটি বিন্দুর মধ্য দিয়ে জোর করে যাওয়া একটি পলিনোমিয়াল বরং নয়েজকেই "ফিট" করে ফেলবে (একে ওভারফিটিং বলা হয়, ../machine-learning/-এ বিস্তারিত)।

লিস্ট-স্কয়ার্স কার্ভ ফিটিংLeast-Squares Curve Fittingএকটি সরল ফাংশন (যেমন একটি সরলরেখা বা নিচু-ডিগ্রি পলিনোমিয়াল) বেছে নেওয়া যা ডেটা পয়েন্টের মধ্য দিয়ে ঠিক না গিয়েও, প্রতিটি পয়েন্টের রেসিডুয়াল (প্রকৃত মান বনাম ফিট করা মানের পার্থক্য)-এর বর্গের যোগফল সর্বনিম্ন করে। সম্পূর্ণ ভিন্ন লক্ষ্য নেয়: একটি সাধারণ, কম-প্যারামিটারের ফাংশন খুঁজে বের করা যা ডেটার সামগ্রিক প্রবণতা (trend) ধরে, প্রতিটি বিন্দুর নয়েজ নয়।

২ · নরমাল ইকুয়েশন

সবচেয়ে সহজ কেস — একটি সরলরেখা y = mx + b ফিট করা — দুটো অজানা প্যারামিটার: ঢাল m এবং ইন্টারসেপ্ট b। লক্ষ্য হলো এমন m, b বের করা যা রেসিডুয়ালের বর্গের যোগফল সর্বনিম্ন করে:

$$E(m,b) = \sum_{i=1}^{n} \left(y_i - (mx_i+b)\right)^2$$

E-কে m ও b-এর সাপেক্ষে ডেরিভেটিভ নিয়ে শূন্যের সমান বসালে (ক্যালকুলাসের ন্যূনতম-খোঁজার মৌলিক কৌশল, ../math-for-ai/index.html-এ বিস্তারিত), যা পাওয়া যায় তাকে নরমাল ইকুয়েশন বলে — একটি ছোট ২×২ লিনিয়ার সিস্টেম:

$$\begin{pmatrix}\sum x_i^2 & \sum x_i \\ \sum x_i & n\end{pmatrix}\begin{pmatrix}m \\ b\end{pmatrix} = \begin{pmatrix}\sum x_i y_i \\ \sum y_i\end{pmatrix}$$

এই ২×২ সিস্টেম M3-এর যেকোনো টেকনিক (এখানে সরাসরি Cramer's rule, যেহেতু আকার মাত্র ২×২) দিয়ে সমাধান করা যায়।

কেন বর্গ (স্কয়ার)
বর্গ ব্যবহার করলে ধনাত্মক ও ঋণাত্মক রেসিডুয়াল একে অপরকে বাতিল করে না, এবং বড় এররকে ছোট এররের চেয়ে বেশি "শাস্তি" দেয় — এবং গুরুত্বপূর্ণভাবে, এটি ডিফারেনশিয়েবল, তাই ক্যালকুলাস দিয়ে সরাসরি সর্বনিম্ন বের করা যায়।
সাধারণীকরণযোগ্য
একই নরমাল-ইকুয়েশন কৌশল দিয়ে উঁচু-ডিগ্রি পলিনোমিয়াল ফিটিং, বহু-ভেরিয়েবল রিগ্রেশন, বা অন্য যেকোনো লিনিয়ার-ইন-প্যারামিটার মডেল ফিট করা যায় — শুধু সিস্টেমের আকার বাড়ে।
ML-এর ভিত্তি
এই একই "রেসিডুয়ালের বর্গের যোগফল সর্বনিম্ন করা" ধারণা মেশিন লার্নিং-এর লিনিয়ার রিগ্রেশন মডেলের কেন্দ্রে, এবং গ্র্যাডিয়েন্ট ডিসেন্ট (M9/L43) এই একই সমস্যা সমাধানের একটি ইটারেটিভ বিকল্প পথ।

৩ · একটি সত্যিকারের ডেমো — নয়েজি ডেটায় সরলরেখা ফিট করা

নিচের কোড সেলে random.gauss দিয়ে (নির্দিষ্ট সিড 42, যাতে ফলাফল পুনরুৎপাদনযোগ্য হয়) একটি সিন্থেটিক ডেটাসেট তৈরি করা হয়েছে সত্যিকারের ঢাল 2.5 ও ইন্টারসেপ্ট 1.0 থেকে, তার উপর সিগমা-1.0 গসিয়ান নয়েজ যোগ করে। তারপর হাতে-লেখা নরমাল ইকুয়েশন দিয়ে ঢাল ও ইন্টারসেপ্ট পুনরুদ্ধার করার চেষ্টা করা হয়েছে।

Python
import random

random.seed(42)

true_slope = 2.5
true_intercept = 1.0

xs = [float(i) for i in range(10)]
ys = [true_slope*x + true_intercept + random.gauss(0, 1.0) for x in xs]

print("সিন্থেটিক ডেটাসেট (প্রকৃত ঢাল=2.5, প্রকৃত ইন্টারসেপ্ট=1.0, গসিয়ান নয়েজ সিগমা=1.0, সিড=42):")
for x, y in zip(xs, ys):
    print(f"  x={x:.1f}  y={y:.6f}")

n = len(xs)
sum_x = sum(xs)
sum_y = sum(ys)
sum_xx = sum(x*x for x in xs)
sum_xy = sum(x*y for x, y in zip(xs, ys))

# নরমাল ইকুয়েশন সমাধান (Cramer's rule, ২x২ সিস্টেম):
# [sum_xx  sum_x ] [m]   [sum_xy]
# [sum_x   n     ] [b] = [sum_y ]
det = sum_xx*n - sum_x*sum_x
m = (sum_xy*n - sum_x*sum_y) / det
b = (sum_xx*sum_y - sum_x*sum_xy) / det

print()
print(f"sum_x={sum_x:.4f} sum_y={sum_y:.4f} sum_xx={sum_xx:.4f} sum_xy={sum_xy:.4f}")
print(f"ডিটারমিন্যান্ট = {det:.4f}")
print(f"ফিট করা ঢাল (m)      = {m:.6f}   (প্রকৃত = {true_slope})")
print(f"ফিট করা ইন্টারসেপ্ট (b) = {b:.6f}   (প্রকৃত = {true_intercept})")

rss = sum((y - (m*x + b))**2 for x, y in zip(xs, ys))
print(f"রেসিডুয়াল সাম অফ স্কয়ার্স (RSS) = {rss:.6f}")

    
মাত্র ১০টি নয়েজি ডেটা পয়েন্ট থেকে নরমাল ইকুয়েশন ফিট করা ঢাল ২.৪৯২৫৬১ বের করে — প্রকৃত ঢাল ২.৫-এর অত্যন্ত কাছাকাছি (মাত্র ০.০০৭৪ এরর)! ফিট করা ইন্টারসেপ্ট ০.৮৯৪৭৪১ — প্রকৃত ১.০-এর তুলনায় একটু বেশি দূরে (০.১০৫ এরর, কারণ ইন্টারসেপ্ট অনুমান করা সাধারণত ঢালের চেয়ে বেশি নয়েজ-সংবেদনশীল, বিশেষত ছোট নমুনায়)। রেসিডুয়াল সাম অফ স্কয়ার্স ২.৮৬ — এটি ফিটের "মোট অবশিষ্ট ভুল" পরিমাপ করে, শূন্য মানে নিখুঁত ফিট (যা এখানে প্রত্যাশিত নয়, কারণ ডেটায় সত্যিকারের র‍্যান্ডম নয়েজ আছে)।
মূল কথা · Key takeaway

লিস্ট-স্কয়ার্স কার্ভ ফিটিং ইন্টারপোলেশনের বিপরীত দর্শন প্রকাশ করে — নয়েজি ডেটার সবচেয়ে ভালো সামগ্রিক প্রবণতা খোঁজা, প্রতিটি বিন্দুর মধ্য দিয়ে ঠিক যাওয়া নয়। নরমাল ইকুয়েশন এই সমস্যাকে একটি ছোট, সরাসরি সমাধানযোগ্য লিনিয়ার সিস্টেমে রূপান্তরিত করে (M3-এর টেকনিক পুনর্ব্যবহার করে) — M4-এর পুরো মডিউলের মূল শিক্ষা: বাস্তব ডেটা মডেল করতে হয় ডেটার প্রকৃতি (নিখুঁত না নয়েজি) বুঝে সঠিক টেকনিক বেছে।

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।

প্র ০১ ফিট করা ঢাল (২.৪৯২৬) প্রকৃত ঢালের (২.৫) খুব কাছে ছিল, কিন্তু ইন্টারসেপ্ট (০.৮৯৪৭ বনাম প্রকৃত ১.০) তুলনামূলক বেশি দূরে। কেন?

ঢাল অনুমান করতে পুরো ডেটা রেঞ্জ জুড়ে (x=0 থেকে ৯) তথ্য ব্যবহৃত হয়, যা গড়ে নয়েজকে কিছুটা বাতিল করে দেয়। কিন্তু ইন্টারসেপ্ট হলো x=0-এ ফিট করা রেখার মান — একটি একক বিন্দুর কাছাকাছি এক্সট্রাপোলেশনের মতো, যেখানে সেই এলাকার নির্দিষ্ট নয়েজ (এখানে x=0-এ প্রকৃত রেসিডুয়াল ছিল -০.০৩৮৮) বেশি প্রভাব ফেলে। পরিসংখ্যানে এটি পরিচিত — ইন্টারসেপ্ট অনুমান সাধারণত ঢাল অনুমানের চেয়ে বেশি ভ্যারিয়েন্স-সংবেদনশীল।

প্র ০২ যদি একটি ডেটা পয়েন্টের মধ্য দিয়ে জোর করে একটি ডিগ্রি-৯ পলিনোমিয়াল ফিট করা হতো (১০টি পয়েন্ট, ১০টি সহগ), রেসিডুয়াল সাম অফ স্কয়ার্স কত হতো, আর সেটা কি "ভালো" ফলাফল হতো?

RSS প্রায় ঠিক ০ হতো, কারণ ডিগ্রি-৯ পলিনোমিয়াল ঠিক ১০টি পয়েন্টের মধ্য দিয়ে যেতে বাধ্য (L16-এর ইন্টারপোলেশন উপপাদ্য অনুযায়ী)। কিন্তু এটি "ভালো" ফলাফল নয় — এটি ওভারফিটিং, যেখানে পলিনোমিয়াল প্রকৃত প্রবণতা (y=2.5x+1) না শিখে র‍্যান্ডম নয়েজকে "মুখস্থ" করে ফেলে, এবং নতুন x-এ (যেমন x=10) ভয়াবহ ভুল ভবিষ্যদ্বাণী দেবে (L18-এর রুঙ্গের ফেনোমেননের সাথে ধারণাগতভাবে সম্পর্কিত একটি সমস্যা)।

প্র ০৩ নরমাল ইকুয়েশনের ডিটারমিন্যান্ট (825) যদি 0-এর খুব কাছাকাছি হতো, কী সমস্যা হতো?

ডিটারমিন্যান্ট শূন্যের কাছাকাছি মানে সিস্টেমটি প্রায়-সিঙ্গুলার (near-singular) — M3/L14-এর কন্ডিশন নাম্বারের ধারণা অনুযায়ী, ছোট নয়েজেও m ও b-এর অনুমান বিশাল দোলায়মান হয়ে যেতে পারে। বাস্তবে এটি ঘটে যখন সব xᵢ প্রায় একই মান হয় (কোনো "বিস্তার" (spread) না থাকলে ঢাল নির্ভরযোগ্যভাবে অনুমান করা যায় না) — এই ডেমোতে x=0 থেকে ৯ পর্যন্ত ভালো বিস্তার আছে বলে ডিটারমিন্যান্ট যথেষ্ট বড়।

অনুশীলন

  1. চিন্তা করুন: যদি কোড সেলে random.gauss(0, 1.0)-এর বদলে random.gauss(0, 5.0) (৫ গুণ বেশি নয়েজ) ব্যবহার করা হয়, ফিট করা ঢাল ও RSS কীভাবে বদলাবে বলে আপনার ধারণা?

    বেশি নয়েজ মানে ফিট করা ঢাল ও ইন্টারসেপ্ট প্রকৃত মান (২.৫, ১.০) থেকে আরও বেশি বিচ্যুত হতে পারে (যদিও একটি নির্দিষ্ট সিডে ফলাফল ভাগ্যক্রমে কাছাকাছিও থাকতে পারে), এবং RSS উল্লেখযোগ্যভাবে বাড়বে (নয়েজ ৫ গুণ মানে ভ্যারিয়েন্স ২৫ গুণ, তাই RSS মোটামুটি সেই অনুপাতে বাড়ার কথা)।

  2. পরীক্ষা করুন: উপরের কোড সেলে random.gauss(0, 1.0)-কে random.gauss(0, 5.0)-এ পরিবর্তন করে Run চেপে আপনার অনুমান যাচাই করুন।

    সিগমা ৫.০-এ RSS নাটকীয়ভাবে বেড়ে যায় (মোটামুটি ২৫ গুণের কাছাকাছি মাত্রায়, যদিও সিডের নির্দিষ্ট র‍্যান্ডম মানের উপর নির্ভর করে ঠিক ২৫ গুণ নাও হতে পারে), এবং ফিট করা m ও b প্রকৃত মান থেকে আরও দূরে সরে যায় — নিশ্চিত করে বেশি নয়েজ মানে কম নির্ভরযোগ্য প্যারামিটার অনুমান, এমনকি নরমাল ইকুয়েশন সঠিকভাবে সমাধান করা হলেও।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

আগের পাঠ
কিউবিক স্প্লাইন ইন্টারপোলেশন