সরাসরি পর্বে যান
পর্ব ০৬ · ৭৭-এর মধ্যে · মডিউল ২

Vector space — span, basis, linear independence আর rank

Vector Spaces — Subspaces, Span, Linear Independence, Basis, Column and Null Space, Rank–Nullity and Numerical Rank

Taught in Bangla, this lesson builds vector spaces, subspaces, span, linear independence, basis and coordinates, then computes rank and null space by row reduction and in NumPy. It connects rank to machine learning through redundant features and the dummy variable trap, and shows why numerical rank in floating point depends on a tolerance.

এই পর্বে যা শিখবেন

  • Vector space আর subspace-এর সংজ্ঞা, আর তিন লাইনের subspace পরীক্ষা
  • Linear combination, span, linear independence, basis আর dimension: ছবিতে, সংজ্ঞায় আর NumPy-তে
  • একটি নতুন basis-এ একটি বিন্দুর coordinates বের করা
  • Row reduction দিয়ে হাতে rank, column space আর null space; rank–nullity উপপাদ্য আর SciPy দিয়ে যাচাই
  • ML-এ rank-ঘাটতি: বাড়তি কলাম, dummy trap, অস্থির coefficient আর তার সমাধান; আর float-এ numerical rank ও tolerance

AI-এর ভিত্তি কোর্সের পর্ব ৩৩-এ vector-এর যোগ, scalar গুণ, norm আর dot product এসেছে, আর পর্ব ১৭-এ matrix গুণ, solve, lstsq আর condition number. পর্ব ৫৮-এ dummy trap-এ “rank 4” কথাটি একবার দেখা দিয়েছিল। এই পর্বে সেই হিসাবগুলো আবার করব না; প্রশ্ন হলো তাদের নিচের জ্যামিতি: কয়েকটি vector মিলে কতটা জায়গা ঢাকে, কোন কলাম আসলে নতুন তথ্য দেয়, আর না দিলে model-এর কী হয়। চালানো যায় এমন চারটি ব্লক পাতাতেই চলে (ব্রাউজারের Python, NumPy আর SciPy); প্রথমবার প্যাকেজ নামতে কয়েক সেকেন্ড লাগে।

১ · Vector space আর subspace — যোগ আর গুণে যে জগৎ বন্ধ থাকে

বাজারঘরের একটি অর্ডারকে তিনটি সংখ্যায় লেখা যায়: চাল কত কেজি, ডাল কত কেজি, তেল কত লিটার। দুটি অর্ডার যোগ করলে আরেকটি অর্ডার, আর একটি অর্ডারকে ৩ দিয়ে গুণ করলে (তিন মাসের বাজার) সেটিও অর্ডার। এই “যোগ করলে বা গুণ করলে একই জাতের জিনিস থাকে” বৈশিষ্ট্যটিই vector space-এর প্রাণ। (ঋণাত্মক পরিমাণ মানে ফেরত, তাই গণিতে সেটিও চলে।)

একটি vector space হলো কিছু বস্তুর (যাদের vector বলি) একটি সংগ্রহ V, যেখানে দুটি কাজ সংজ্ঞায়িত: দুটি vector যোগ আর একটি vector-কে একটি বাস্তব সংখ্যা (scalar) দিয়ে গুণ। শর্ত হলো ফলাফল V-এর ভেতরেই থাকবে, আর পরিচিত নিয়মগুলো খাটবে: যোগ ক্রম-নিরপেক্ষ ও সহযোজী, একটি শূন্য vector 0 আছে, প্রতিটি v-এর একটি −v আছে, আর গুণ যোগের ওপর বণ্টিত হয় (a(u + v) = au + av), সঙ্গে 1·v = v. পূর্ণ তালিকায় আটটি নিয়ম; মুখস্থ করার দরকার নেই, কারণ ML-এ আমরা প্রায় সবসময় Rn নিয়ে কাজ করি, অর্থাৎ n-টি বাস্তব সংখ্যার তালিকা, যেখানে সব নিয়ম আপনা থেকেই সত্য।

তবু বিমূর্ত সংজ্ঞাটির দাম আছে। ২ ঘাত পর্যন্ত সব polynomial (a + bx + cx²), একটি নির্দিষ্ট আকারের সব matrix, বা সব function-ও vector space; এজন্যই পরে kernel method-এ (পর্ব ২৯) “function-কে vector হিসেবে দেখা” স্বাভাবিক লাগবে। ইতিহাসে Hermann Grassmann ১৮৪৪ সালের Ausdehnungslehre-তে linear independence আর dimension-এর ধারণার অনেকটা দেন, তবে সেই সময় তাঁর কাজ খুব কম পাঠক পায়; আর Giuseppe Peano ১৮৮৮ সালে vector space-এর প্রায় আধুনিক স্বতঃসিদ্ধ সংজ্ঞা লেখেন বলে সাধারণত উল্লেখ করা হয়।

Subspace — বড় জগতের ভেতরে ছোট, কিন্তু সম্পূর্ণ জগৎ

V-এর একটি উপসংগ্রহ W নিজেই vector space হলে তাকে subspace বলে। পরীক্ষাটি তিন লাইনের:

  1. শূন্য vector 0 W-তে আছে।
  2. W-এর যেকোনো দুটি vector-এর যোগফল W-তে থাকে (যোগে বন্ধ)।
  3. W-এর যেকোনো vector-কে যেকোনো scalar দিয়ে গুণ করলে W-তে থাকে (গুণে বন্ধ)।

কোনটি subspace, কোনটি নয়

Three subsets of R²: a line through the origin, a shifted line, and the union of the two axes

Subspace test on three subsets of the plane uvu+v ✓ subspace ✗ 0 নেই ✗ যোগে বাইরে y = x/2y = x/2 + 1x-অক্ষ ∪ y-অক্ষ
ছবি ৬.১ — মূলবিন্দু দিয়ে যাওয়া রেখা subspace: রেখার দুটি বিন্দুর যোগফল বা গুণিতক রেখাতেই থাকে। একই রেখা একটু সরালে শূন্য vector বাদ পড়ে, তাই আর subspace নয়। দুই অক্ষের মিলন (∪) গুণে বন্ধ, কিন্তু u = (1, 0) আর v = (0, 1)-এর যোগফল (1, 1) কোনো অক্ষে নেই।

R2-এর subspace আসলে মাত্র তিন রকম: শুধু {0}, মূলবিন্দু দিয়ে যাওয়া কোনো রেখা, আর পুরো সমতল। R3-এ এর সঙ্গে যোগ হয় মূলবিন্দু দিয়ে যাওয়া সমতল। ML-এ সবচেয়ে গুরুত্বপূর্ণ subspace দুটি এই পর্বের শেষ অর্ধে আসবে: একটি matrix-এর column space আর null space. আর একটি সতর্কতা: “রেখা” শুনলে মূলবিন্দু দিয়ে যাওয়ার শর্তটি ভুলবেন না। Linear regression-এর y = wx + b রেখাটি b ≠ 0 হলে subspace নয়; এজন্যই design matrix-এ সব-1-এর একটি কলাম যোগ করে intercept-কে “মূলবিন্দুর রেখা”-র ভাষায় আনা হয়।

২ · Linear combination আর span — দুটি তীর দিয়ে কতদূর যাওয়া যায়

কয়েকটি vector v1, …, vk আর কয়েকটি scalar c1, …, ck নিয়ে c1v1 + … + ckvk হলো একটি linear combination. সম্ভাব্য সব c বসিয়ে যত vector পাওয়া যায়, তাদের সংগ্রহ হলো span:

span{v1, …, vk} = { c1v1 + … + ckvk : প্রতিটি ci ∈ R }

Span সবসময় একটি subspace: c সব শূন্য নিলে 0 আসে, আর দুটি combination-এর যোগফল বা গুণিতক আবার একটি combination. রিকশার উপমায়: একটি রাস্তা ধরে শুধু সামনে-পেছনে গেলে একটি রেখার বাইরে যাওয়া যায় না; দুটি ভিন্ন দিকের রাস্তা পেলে, যত খুশি মিশিয়ে, শহরের যেকোনো মোড়ে পৌঁছানো যায়। নিচের stepper u = (2, 1) আর v = (1, 3) দিয়ে span গড়ে।

Building a span from two vectors u v 2v (4, 7) w = 2u(4, 7) ✗
  1. একটি vector, একটি রেখা। u = (2, 1). এর সব গুণিতক cu (c যেকোনো বাস্তব সংখ্যা, ঋণাত্মকও) মূলবিন্দু দিয়ে যাওয়া নীল ড্যাশ রেখাটি ভরায়: span{u} হলো রেখা y = x/2.
  2. দ্বিতীয় দিক। v = (1, 3) এই রেখায় নেই, কারণ x = ১ হলে রেখার y = ০.৫, কিন্তু v-এর y = ৩. তাই v একটি নতুন দিক আনে; তার নিজের span সবুজ রেখা।
  3. Scalar গুণ। 2·v = (2, 6): একই দিকে দ্বিগুণ লম্বা। গুণ দিক বদলায় না, শুধু দৈর্ঘ্য (ঋণাত্মক হলে উল্টো দিক)।
  4. যোগ: মাথায় লেজ। 2v-এর মাথা থেকে u বসালে পৌঁছাই (2 + 2, 6 + 1) = (4, 7). অর্থাৎ (4, 7) = 1·u + 2·v, span-এর একটি সদস্য। c-গুলো কীভাবে বের হলো, তা অংশ ৪-এ।
  5. পুরো সমতল। c1, c2 পূর্ণসংখ্যা নিলে বেগুনি বিন্দুগুলো আসে; ভগ্নাংশ নিলে মাঝের ফাঁকও ভরে যায়। দুটি ভিন্ন দিকের vector দিয়ে R2-এর যেকোনো বিন্দু লেখা যায়: span{u, v} = R2.
  6. ভুল জোড়া। v-এর বদলে w = (4, 2) নিলে w = 2u, একই রেখায়। তখন span{u, w} আবার শুধু রেখা y = x/2, আর (4, 7) অধরা: 7 ≠ 4/2. দুটি vector থাকলেও দিক একটিই।

শেষ ধাপটি পুরো পর্বের মূল প্রশ্ন: কয়টি vector আছে, তা নয়; কয়টি সত্যিকারের ভিন্ন দিক আছে, সেটাই গুরুত্বপূর্ণ। একটি লক্ষ্য vector b কয়েকটি vector-এর span-এ আছে কি না, তা আসলে একটি linear system-এর প্রশ্ন: vector-গুলোকে কলাম করে matrix A বানালে “b ∈ span” মানে Ax = b-এর অন্তত একটি সমাধান আছে। কম্পিউটারে সহজ পরীক্ষা: A-তে b-কে আরেকটি কলাম হিসেবে জুড়ে দিলে যদি নতুন দিক না আসে (rank না বাড়ে), তাহলে b আগেই span-এ ছিল। Rank-এর পূর্ণ সংজ্ঞা অংশ ৫-এ; আপাতত “স্বাধীন দিকের সংখ্যা” ধরে নিন।

৩ · Linear independence — কোনো vector কি বাড়তি?

v1, …, vk vector-গুলো linearly independent, যদি

c1v1 + c2v2 + … + ckvk = 0 হলে অবশ্যই c1 = c2 = … = ck = 0

অর্থাৎ শূন্যে পৌঁছানোর একমাত্র উপায় “কিছুই না নেওয়া”। যদি সব-শূন্য নয় এমন কোনো c দিয়ে শূন্য পাওয়া যায়, vector-গুলো dependent, আর তখন যে vj-এর cj ≠ 0, তাকে বাকিদের মিশ্রণ হিসেবে লেখা যায়: vj = −(1/cj)·(বাকি পদের যোগফল)। সে span-এ নতুন কিছু যোগ করে না, বাদ দিলেও span একই থাকে। চায়ের দোকানের হিসাব খাতায় “চা”, “বিস্কুট” আর “চা + বিস্কুট মোট” তিনটি কলাম থাকলে তৃতীয়টি বাড়তি: প্রথম দুটি জানলেই সেটি জানা।

হাতে একটি উদাহরণ। R3-এ a = (1, 0, 2), b = (0, 1, 1), c = (2, 3, 7). c = αa + βb লেখার চেষ্টা করি: প্রথম উপাদান থেকে α = 2, দ্বিতীয় থেকে β = 3, আর তৃতীয়তে 2·2 + 3·1 = 7, মিলে গেছে। তাই 2a + 3b − c = 0, একটি সব-শূন্য নয় এমন combination (2, 3, −1). তিনটি vector dependent; তাদের span R3 নয়, একটি সমতল, যার প্রতিটি বিন্দু (x, y, 2x + y) আকারের। এই সমতলে (3, −1, 5) আছে (2·3 − 1 = 5), কিন্তু (1, 1, 1) নেই, কারণ 2 + 1 ≠ 1.

তিনটি দ্রুত নিয়ম

(১) শূন্য vector যে সেটে আছে, সেটি সবসময় dependent (1·0 = 0). (২) Rn-এ n-এর বেশি vector সবসময় dependent: n-মাত্রার জগতে n-এর বেশি স্বাধীন দিক নেই। (৩) দুটি vector dependent ঠিক তখনই, যখন একটি অন্যটির গুণিতক (একই রেখায়)। তিন বা বেশি vector-এ জোড়ায় জোড়ায় গুণিতক না হয়েও dependent হতে পারে, যেমন ওপরের a, b, c.

নিচের ব্লক এই কথাগুলো NumPy দিয়ে যাচাই করে। np.linalg.matrix_rank একটি matrix-এর স্বাধীন কলামের সংখ্যা দেয়; কলামের সংখ্যার সমান হলে কলামগুলো independent. শেষ অংশে একটি নতুন basis-এ coordinates বের করা হয়েছে, যার ছবি অংশ ৪-এ।

import numpy as np
np.set_printoptions(precision=3, suppress=True)

u, v, w = np.array([2., 1.]), np.array([1., 3.]), np.array([4., 2.])
for name, M in [("u, v", np.column_stack([u, v])), ("u, w", np.column_stack([u, w]))]:
    r = np.linalg.matrix_rank(M)
    print(f"{name}: rank {r} of {M.shape[1]} ->", "independent" if r == M.shape[1] else "dependent")

a, b, c = np.array([1., 0., 2.]), np.array([0., 1., 1.]), np.array([2., 3., 7.])
A = np.column_stack([a, b, c])
print("rank [a b c] =", np.linalg.matrix_rank(A), "| c - 2a - 3b =", c - 2 * a - 3 * b)

for t in (np.array([3., -1., 5.]), np.array([1., 1., 1.])):     # t কি span-এ আছে?
    r1 = np.linalg.matrix_rank(A)
    r2 = np.linalg.matrix_rank(np.column_stack([A, t]))
    print(t, "in span" if r1 == r2 else "NOT in span", f"(rank A = {r1}, rank [A|t] = {r2})")

B = np.column_stack([u, v])          # নতুন basis {u, v}, কলাম হিসেবে
p = np.array([4., 7.])
coords = np.linalg.solve(B, p)       # B @ coords = p
print("p in basis {u, v}:", coords, "| check B @ coords =", B @ coords)
q = np.array([1., -1.])
print("q in basis {u, v}:", np.linalg.solve(B, q))

আসল আউটপুট (ব্রাউজারের Python):

u, v: rank 2 of 2 -> independent
u, w: rank 1 of 2 -> dependent
rank [a b c] = 2 | c - 2a - 3b = [0. 0. 0.]
[ 3. -1.  5.] in span (rank A = 2, rank [A|t] = 2)
[1. 1. 1.] NOT in span (rank A = 2, rank [A|t] = 3)
p in basis {u, v}: [1. 2.] | check B @ coords = [4. 7.]
q in basis {u, v}: [ 0.8 -0.6]

প্রথম দুই লাইন stepper-এর শেষ দুই ধাপ: u, v-এর rank ২ (পুরো সমতল), u, w-এর rank ১ (একটি রেখা)। তৃতীয় লাইনে তিনটি ৩-মাত্রার vector-এর rank মাত্র ২, আর c − 2a − 3b ঠিক শূন্য vector: হাতের হিসাব মিলেছে। চতুর্থ ও পঞ্চম লাইন span-পরীক্ষা: (3, −1, 5) জুড়লে rank ২-ই থাকে, তাই সেটি আগেই সমতলে ছিল; (1, 1, 1) জুড়লে rank ৩ হয়, অর্থাৎ নতুন দিক, তাই span-এর বাইরে। শেষ দুই লাইনের অর্থ অংশ ৪-এ।

৪ · Basis, dimension আর coordinates — একই বিন্দুর নতুন ঠিকানা

একটি subspace W-এর basis হলো এমন vector-এর সেট যা (ক) W-কে span করে আর (খ) linearly independent. প্রথম শর্ত বলে “যথেষ্ট আছে”, দ্বিতীয়টি বলে “বাড়তি নেই”। একটি গুরুত্বপূর্ণ উপপাদ্য: একই W-এর সব basis-এ vector-এর সংখ্যা সমান। এই সংখ্যার নাম W-এর dimension, dim W. Rn-এর dimension n; সবচেয়ে পরিচিত basis হলো standard basis e1 = (1, 0, …, 0), …, en = (0, …, 0, 1). অংশ ৩-এর সমতলের dimension ২, কারণ a আর b তার একটি basis.

Basis-এর সবচেয়ে কাজের বৈশিষ্ট্য: W-এর প্রতিটি vector-কে basis-এর combination হিসেবে ঠিক একভাবে লেখা যায়। প্রমাণ এক লাইনের: দুইভাবে লেখা গেলে, x = ∑cibi = ∑dibi, বিয়োগ করলে ∑(ci − di)bi = 0, আর independence বলে প্রতিটি ci − di = 0. এই একক সংখ্যাগুলোই x-এর coordinates সেই basis-এ, লেখা হয় [x]B. ঢাকার একটি বাড়ির ঠিকানা “রোড ৪, বাড়ি ৭” বা GPS-এর অক্ষাংশ-দ্রাঘিমাংশ, দুই রকমই হয়; বাড়ি একটিই, ঠিকানার ব্যবস্থা আলাদা।

Basis B-এর vector-গুলোকে কলাম করে matrix B বানালে x = B·[x]B, তাই নতুন coordinates পেতে একটি linear system সমাধান করতে হয়: B c = x. এটিই change of basis. নিচের stepper p = (4, 7)-এর ঠিকানা B = {u, v}-তে বের করে।

Changing basis for one point e₁e₂ uv p q
  1. পুরোনো ঠিকানা। Standard basis-এ p = (4, 7) মানে 4·e1 + 7·e2: ডানে ৪ ঘর, তারপর ওপরে ৭ ঘর। সংখ্যা দুটি basis-এর ওপর নির্ভর করে, এটা আমরা সাধারণত খেয়াল করি না।
  2. নতুন grid. u = (2, 1) আর v = (1, 3) দিয়ে বেগুনি বাঁকা grid: একটি রেখার পরিবার u-এর দিকে, অন্যটি v-এর দিকে। প্রতিটি ছেদবিন্দু c1u + c2v, পূর্ণসংখ্যা c-তে।
  3. সমীকরণ। খুঁজছি c1, c2 যাতে c1(2, 1) + c2(1, 3) = (4, 7). উপাদান ধরে: 2c1 + c2 = 4 আর c1 + 3c2 = 7. Matrix রূপে B c = p, যেখানে B-এর কলাম u আর v.
  4. সমাধান। det B = 2·3 − 1·1 = ৫ ≠ ০, তাই একক উত্তর আছে। 2 × 2-এর inverse সূত্রে c = (1/5)·(3·4 − 1·7, −1·4 + 2·7) = (1/5)·(5, 10) = (1, 2).
  5. নতুন ঠিকানা। বাঁকা grid-এ ১ ঘর u-এর দিকে, তারপর ২ ঘর v-এর দিকে: ঠিক p-তে। তাই [p]B = (1, 2). বিন্দু একই, সংখ্যা বদলেছে।
  6. আরেকটি বিন্দু। q = (1, −1)-এর জন্য একই হিসাবে c = (1/5)·(3 + 1, −1 − 2) = (0.8, −0.6): ০.৮ ঘর u-এর দিকে, তারপর ০.৬ ঘর v-এর উল্টো দিকে। যাচাই: 0.8·(2, 1) − 0.6·(1, 3) = (1, −1).

অংশ ৩-এর ব্লকের শেষ দুই লাইন ঠিক এই সংখ্যা দুটি দেয়: solve(B, p) = (1, 2) আর solve(B, q) = (0.8, −0.6). ML-এ basis বদল সব জায়গায়: AI-এর ভিত্তি কোর্সের পর্ব ৬৫-এর PCA ডেটাকে একটি নতুন orthonormal basis-এ লেখে, যার প্রথম কয়েকটি coordinate বেশিরভাগ variance ধরে; পর্ব ০৮ (Eigenvalue আর eigenvector — ধারণা থেকে PCA পর্যন্ত) সেই basis কোথা থেকে আসে তা দেখাবে। Standardization বা unit বদল (টাকা থেকে হাজার টাকা) সরলতম basis বদল: প্রতিটি অক্ষ আলাদাভাবে টানা।

কেন orthonormal basis প্রিয়? Basis-এর vector-গুলো পরস্পর সমকোণে আর দৈর্ঘ্য ১ হলে (orthonormal basis) coordinates বের করতে কোনো সমীকরণ সমাধান লাগে না: ci = bi · x, শুধু dot product. ওপরের u, v সমকোণে নয় (u · v = 2 + 3 = ৫ ≠ ০), তাই solve লেগেছে। যেকোনো basis থেকে orthonormal basis বানানোর পদ্ধতি Gram–Schmidt, পর্ব ০৭ (Matrix-এর জ্যামিতি — projection, rotation আর least squares)-এ।

৫ · Row reduction দিয়ে rank — খাতায় হিসাব

একটি m × n matrix A-এর (m সারি, n কলাম) rank হলো তার স্বাধীন কলামের সর্বোচ্চ সংখ্যা। হাতে বের করার পথ Gaussian elimination, বা row reduction: একটি সারির গুণিতক আরেকটি থেকে বিয়োগ করা, সারি অদলবদল, বা একটি সারিকে শূন্য-নয় সংখ্যা দিয়ে গুণ। এই তিন কাজে কলামগুলোর মধ্যের linear সম্পর্ক বদলায় না (প্রমাণের ভাব: প্রতিটি কাজ একটি invertible matrix দিয়ে বাম দিক থেকে গুণ, আর Ax = 0-এর সমাধান একই থাকে)। লক্ষ্য row echelon form: প্রতিটি শূন্য-নয় সারির প্রথম শূন্য-নয় সংখ্যা, যাকে pivot বলে, আগের সারির pivot-এর ডানে, আর সব-শূন্য সারি নিচে। তখন rank = pivot-এর সংখ্যা.

প্রায় দুই হাজার বছর আগের চীনা গণিত-গ্রন্থ Nine Chapters on the Mathematical Art-এ (সংকলনের সময় নিয়ে মতভেদ আছে) প্রায় এই পদ্ধতিতেই একঘাত সমীকরণ সমাধান করা হয়েছে; Gauss-এর নাম যুক্ত হয়েছে অনেক পরে। নিচের stepper একটি ৩ × ৪ matrix ধাপে ধাপে কমায়, তারপর তার থেকে column space আর null space পড়ে।

A, কলাম c1 … c4সারির কাজ

            
  1. শুরু। তিন সারি, চার কলাম। প্রথম কলামের ১-টিকে pivot ধরে নিচের ২ আর ৩-কে শূন্য করা লক্ষ্য। খেয়াল করুন, R3 আসলে R1 + R2; ধাপগুলো সেটি নিজেই খুঁজে বের করবে।
  2. R2 থেকে 2·R1 বিয়োগ। নতুন R2 = (0, 0, 1, 2). দ্বিতীয় কলামও শূন্য হয়ে গেল, কারণ c2 = 2·c1; তাই দ্বিতীয় pivot c2-তে নয়, c3-তে।
  3. R3 থেকে 3·R1 বিয়োগ। নতুন R3 = (0, 0, 1, 2), নতুন R2-এর হুবহু সমান।
  4. R3 থেকে R2 বিয়োগ। R3 সব-শূন্য হলো। এটি row echelon form: pivot দুটি, c1 আর c3-এ (বন্ধনীতে)। তাই rank A = ২. এখানে R1-এর c3-এর ঘর আগে থেকেই ০, তাই এটি reduced রূপও।
  5. Column space পড়া। Pivot কলামের নম্বর দেখে আসল A থেকে সেই কলামগুলো নিলে column space-এর basis: (1, 2, 3) আর (0, 1, 1). বাকিরা তাদের মিশ্রণ: c2 = 2·c1, c4 = c1 + 2·c3, যেমন (1, 4, 5) = (1, 2, 3) + 2·(0, 1, 1).
  6. Null space পড়া। Echelon form থেকে Ax = 0-এর দুটি সমীকরণ। Free চলক x2 = s, x4 = t যেকোনো মান নিতে পারে; বাকিরা তাদের দিয়ে লেখা যায়। ফলে null space-এর basis দুটি vector, nullity ২, আর ২ + ২ = ৪ = কলামের সংখ্যা।

পরীক্ষার খাতায় প্রচলিত ভুল: column space-এর basis হিসেবে echelon form-এর কলাম লেখা। Row operation কলামের সম্পর্ক রাখে, কিন্তু কলামগুলো নিজে বদলে যায়: echelon form-এর সব কলামের তৃতীয় উপাদান ০, অথচ A-এর column space-এ (1, 2, 3) আছে। Pivot-এর অবস্থান echelon form থেকে, কলাম আসল A থেকে।

৬ · Column space, null space আর rank–nullity

একটি m × n matrix A দুটি জগতের মধ্যে সেতু: x ∈ Rn নিয়ে Ax ∈ Rm দেয়। এতে দুটি স্বাভাবিক subspace তৈরি হয়।

  • Column space C(A) ⊆ Rm: A-এর কলামগুলোর span, অর্থাৎ সব সম্ভাব্য Ax. Ax = b সমাধানযোগ্য ঠিক তখনই, যখন b ∈ C(A). dim C(A) = rank A.
  • Null space N(A) ⊆ Rn: যেসব x-এর জন্য Ax = 0. এর dimension-কে বলে nullity. N(A) সবসময় subspace: A·0 = 0, আর An1 = An2 = 0 হলে A(n1 + c·n2) = 0.
Rank–nullity উপপাদ্য

Rank–nullity অনুযায়ী, যেকোনো m × n matrix A-এর জন্য rank A + nullity A = n (কলামের সংখ্যা)। অন্তর্দৃষ্টি: row reduction-এ প্রতিটি কলাম হয় pivot কলাম (rank-এ গোনা), নয়তো free কলাম, যা একটি free চলক আর null space-এর একটি basis vector দেয়। দুই দলের যোগফল সব কলাম।

এর একটি জ্যামিতিক ব্যাখ্যা আছে: A ইনপুটের n-টি মাত্রার কিছু “পিষে” শূন্যে পাঠায় (null space), আর বাকিগুলো আউটপুটে টিকে থাকে (column space). কোনো মাত্রা হারায় না, শুধু ভাগ হয়। আরও একটি অবাক করা তথ্য: row space-এর (সারিগুলোর span) dimension-ও rank-এর সমান। অর্থাৎ স্বাধীন সারির সংখ্যা = স্বাধীন কলামের সংখ্যা, যদিও সারি থাকে Rn-এ আর কলাম Rm-এ। কারণ: row operation row space বদলায় না, আর echelon form-এর শূন্য-নয় সারি, অর্থাৎ pivot-যুক্ত সারি, স্বাধীন; তাদের সংখ্যাই pivot-এর সংখ্যা। তাই rank A ≤ min(m, n).

A দিয়ে R4 থেকে R3 — ইনপুটের চার মাত্রা কোথায় যায়

The null space is sent to 0; everything else lands in the column space. rank 2 + nullity 2 = 4 columns

Rank-nullity: null space maps to zero, the rest fills the column space R⁴ (ইনপুট x) R³ (আউটপুট Ax) N(A), dim 2 C(A), dim 2 A xAx0 rank 2 + nullity 2 = 4 কলাম
ছবি ৬.২ — অংশ ৫-এর A দিয়ে আঁকা। চার মাত্রার ইনপুটের দুটি মাত্রা (কমলা null space) পুরোপুরি শূন্যে যায়; বাকি দুই মাত্রা আউটপুটের দুই-মাত্রার column space (বেগুনি সমতল) ভরায়। R3-এর তৃতীয় দিকে কোনো Ax কখনো পৌঁছায় না। ছবিটি স্কিম, মাপমতো নয়।

একটি ফল ML-এর জন্য সোনার মতো: x আর x + n একই আউটপুট দেয়, যদি n ∈ N(A), কারণ A(x + n) = Ax + An = Ax. অর্থাৎ null space শূন্য না হলে Ax = b-এর সমাধান (থাকলে) অসংখ্য। নিচের ব্লক SciPy-র scipy.linalg.null_space দিয়ে stepper-এর সব কথা যাচাই করে। এই function SVD দিয়ে null space-এর একটি orthonormal basis দেয়, তাই তার vector-গুলো হাতে পাওয়া (−2, 1, 0, 0)-এর মতো সুন্দর দেখাবে না; কিন্তু একই subspace span করে কি না, তা rank দিয়ে পরীক্ষা করা যায়।

import numpy as np
from scipy.linalg import null_space
np.set_printoptions(precision=3, suppress=True)

A = np.array([[1, 2, 0, 1],
              [2, 4, 1, 4],
              [3, 6, 1, 5]], dtype=float)
r = np.linalg.matrix_rank(A)
N = null_space(A)                          # null space-এর orthonormal basis, কলামে
print("shape", A.shape, "| rank", r, "| nullity", N.shape[1], "| rank + nullity =", r + N.shape[1])
print("null space basis (columns):\n", N)
print(f"max |A @ N| = {np.abs(A @ N).max():.1e}")

n1, n2 = np.array([-2., 1, 0, 0]), np.array([-1., 0, -2, 1])   # হাতে row reduction থেকে
print("A @ n1 =", A @ n1, "| A @ n2 =", A @ n2)
print("rank [N n1 n2] =", np.linalg.matrix_rank(np.column_stack([N, n1, n2])))

C = A[:, [0, 2]]                           # pivot কলাম: column space-এর basis
for j in (1, 3):
    k = np.round(np.linalg.lstsq(C, A[:, j])[0], 6) + 0.0
    print(f"col{j} = {k[0]:g}*col0 + {k[1]:g}*col2")

x = np.array([1., 1, 1, 1])
print("A @ x =", A @ x, "| A @ (x + 5*n1) =", A @ (x + 5 * n1))

আসল আউটপুট (ব্রাউজারের Python):

shape (3, 4) | rank 2 | nullity 2 | rank + nullity = 4
null space basis (columns):
 [[ 0.898 -0.042]
 [-0.438 -0.198]
 [ 0.045 -0.876]
 [-0.022  0.438]]
max |A @ N| = 1.1e-15
A @ n1 = [0. 0. 0.] | A @ n2 = [0. 0. 0.]
rank [N n1 n2] = 2
col1 = 2*col0 + 0*col2
col3 = 1*col0 + 2*col2
A @ x = [ 4. 11. 15.] | A @ (x + 5*n1) = [ 4. 11. 15.]

প্রথম লাইন rank–nullity: ২ + ২ = ৪. SciPy-র null space basis-এর দুটি কলাম পরস্পর সমকোণে আর দৈর্ঘ্য ১; A দিয়ে গুণ করলে সবচেয়ে বড় মানও 10−15-এর ঘরে, যা float-এর গোলমাল, আসলে শূন্য (অংশ ৮)। হাতে পাওয়া n1, n2 ঠিক শূন্য দেয়, আর SciPy-র দুটি কলামের সঙ্গে জুড়লেও rank ২-ই থাকে: চারটি vector একই দুই-মাত্রার subspace-এ। এরপর lstsq দিয়ে stepper-এর সম্পর্ক যাচাই: c2 = 2·c0 আর c3 = 1·c0 + 2·c2 (কোডে কলাম নম্বর ০ থেকে শুরু, তাই stepper-এর c1, c3 এখানে col0, col2 নামে)। শেষ লাইন সোনার ফলটি: x-এর সঙ্গে null space-এর একটি vector-এর পাঁচগুণ যোগ করলেও আউটপুট হুবহু একই।

৭ · ML-এ rank — বাড়তি কলাম, dummy trap আর অস্থির coefficient

Linear model-এ অনুমান ŷ = Xw, যেখানে design matrix X-এর প্রতিটি সারি একজন গ্রাহক আর প্রতিটি কলাম একটি feature. এখন অংশ ৬-এর সব কথা সরাসরি খাটে। সব সম্ভাব্য অনুমান ŷ মিলে X-এর column space; least squares y-এর সবচেয়ে কাছের ŷ এই subspace থেকে বাছে (তার জ্যামিতি, অর্থাৎ projection, পর্ব ০৭-এ)। আর X-এর null space শূন্য না হলে, w আর w + n একই ŷ দেয়: সবচেয়ে ভালো অনুমান একটিই, কিন্তু তা দেওয়ার মতো coefficient অসংখ্য। এই অবস্থার নাম rank-ঘাটতি (rank deficient), আর উল্টোটি, rank = কলামের সংখ্যা, হলো full column rank.

বাস্তবে এটি প্রায়ই নিরীহ চেহারায় আসে। বাজারঘরের analyst গ্রাহকের খাবার, মুদি আর অন্যান্য খরচের পাশাপাশি “মোট খরচ” কলামও রাখলেন। মোট = তিনটির যোগফল, অর্থাৎ X-এর null space-এ (0, 1, 1, 1, −1) vector আছে। একইভাবে one-hot encoding-এ তিনটি জেলার তিনটি 0/1 কলামের যোগফল প্রতিটি সারিতে ১, যা intercept-এর সব-1 কলামের সমান: null space-এ (1, −1, −1, −1). এটিই dummy-variable trap, এখন rank-এর ভাষায়। AI-এর ভিত্তি কোর্সের পর্ব ৫৮-এ এর ব্যবহারিক রূপ এসেছে; নিচের ব্লক তার কারণ দেখায়: null vector খুঁজে বের করে, তার বরাবর coefficient সরিয়ে দেখায় অনুমান বদলায় না, তারপর দেখায় “প্রায়” নির্ভরশীল কলাম আরও বিপজ্জনক।

import numpy as np
from scipy.linalg import null_space

rng = np.random.default_rng(42)
n = 40                                    # কাল্পনিক বাজারঘরের ৪০ জন গ্রাহক, খরচ হাজার টাকায়
food = rng.uniform(1, 8, n).round(2)
groc = rng.uniform(1, 6, n).round(2)
other = rng.uniform(0, 4, n).round(2)
y = 0.10 * food + 0.15 * groc + 0.05 * other + rng.normal(0, 0.05, n)  # মাসিক লাভ
one = np.ones(n)
total = food + groc + other               # “মোট খরচ”: বাকি তিনটির যোগফল

def fit(X, label):
    w, _, r, s = np.linalg.lstsq(X, y)
    print(f"{label:<13} rank {r}/{X.shape[1]}  cond {s[0] / s[-1]:.1e}  w = {np.round(w, 3)}")
    return w

np.set_printoptions(suppress=True)
X5 = np.column_stack([one, food, groc, other, total])
w_a = fit(X5, "with total")
nv = null_space(X5)[:, 0]
print("null vector:", np.round(nv / nv[1], 3) + 0.0)
w_b = w_a + 2.0 * nv / nv[1]              # null space বরাবর সরানো আরেকটি সমাধান
print("other w     :", np.round(w_b, 3), " max pred diff", f"{np.abs(X5 @ w_a - X5 @ w_b).max():.1e}")
X5n = X5.copy(); X5n[:, 4] += rng.normal(0, 0.001, n)   # “মোট”-এ প্রায় ১ টাকার গোলমাল
fit(X5n, "total+noise")
fit(np.column_stack([one, food, groc, other]), "drop total")
Z = np.eye(3)[rng.integers(0, 3, n)]      # ঢাকা, চট্টগ্রাম, সিলেটের one-hot
D = np.column_stack([one, Z])
print("one-hot + intercept: rank", np.linalg.matrix_rank(D), "of", D.shape[1],
      " null:", np.round(null_space(D)[:, 0] / null_space(D)[0, 0], 3) + 0.0)

আসল আউটপুট (ব্রাউজারের Python):

with total    rank 4/5  cond 9.3e+15  w = [-0.039  0.023  0.079 -0.024  0.078]
null vector: [ 0.  1.  1.  1. -1.]
other w     : [-0.039  2.023  2.079  1.976 -1.922]  max pred diff 1.0e-14
total+noise   rank 5/5  cond 2.7e+04  w = [-0.042 -3.813 -3.756 -3.859  3.914]
drop total    rank 4/4  cond 2.6e+01  w = [-0.039  0.101  0.158  0.054]
one-hot + intercept: rank 3 of 4  null: [ 1. -1. -1. -1.]

লাইন ১: পাঁচটি কলাম, rank ৪; condition number প্রায় 1016, অর্থাৎ XTX কার্যত singular. তবু কোনো error নেই! lstsq অসংখ্য সমাধানের মধ্যে একটি দিয়েছে (সবচেয়ে ছোট দৈর্ঘ্যের সমাধান; কেন এটি, তা পর্ব ০৯-এ pseudo-inverse প্রসঙ্গে)। লক্ষ করুন, খাবারের “আসল” প্রভাব এখানে দুই জায়গায় ভাগ হয়ে আছে: food-এর coefficient আর total-এর coefficient যোগ করলে আসল ০.১০-এর কাছে আসে। লাইন ২–৩: SciPy যে null vector দিল তা ঠিক (0, 1, 1, 1, −1) (স্কেল করে); তার দুইগুণ যোগ করে সম্পূর্ণ আলাদা coefficient, অথচ অনুমানের পার্থক্য 10−14-এর ঘরে। কোন coefficient “সঠিক”, ডেটা তা বলতে পারে না।

লাইন ৪: “মোট”-এ এক টাকার মতো ছোট গোলমাল (যেমন রাউন্ডিং) ঢুকলে কলামগুলো আর নিখুঁতভাবে নির্ভরশীল নয়, rank ৫/৫. কিন্তু condition number তখনো বিশাল, আর coefficient ভয়ংকর: আলাদাভাবে প্রায় −৩.৮ আর +৩.৯, যদিও যোগফল আবার প্রায় ০.১০. এগুলো আসলে গোলমালটুকু fit করছে; ডেটা একটু বদলালেই চিহ্ন উল্টে যেতে পারে। নিখুঁত নির্ভরশীলতার চেয়ে প্রায়-নির্ভরশীলতা বেশি প্রতারক, কারণ rank পরীক্ষায় ধরা পড়ে না। লাইন ৫, সমাধান: বাড়তি কলাম বাদ দিলে rank ৪/৪, condition number মাত্র কয়েক দশ, আর coefficient আসল নিয়মের (০.১০, ০.১৫, ০.০৫) কাছে। শেষ লাইন: intercept-সহ সব one-hot কলাম রাখলে rank ৩, null vector (1, −1, −1, −1): dummy trap.

তিনটি সমাধান প্রচলিত, প্রতিটির নিজস্ব দাম। (১) বাড়তি কলাম বাদ দেওয়া: one-hot-এ একটি category বাদ (OneHotEncoder(drop="first") বা pandas-এর drop_first=True), তখন বাকিদের coefficient সেই বাদ দেওয়া category-র তুলনায় পড়তে হয়। (২) Ridge regression: loss-এ λ‖w‖² যোগ করলে XTX + λI সবসময় invertible (λ > 0), তাই একক উত্তর আসে; null space বরাবর সরানো coefficient-এর দৈর্ঘ্য বাড়ায়, তাই ridge সবচেয়ে ছোটটি বাছে। কেন এমন হয়, পর্ব ১০ (Positive definite matrix)-এ আর পর্ব ১৭ (Regularization-এর তত্ত্ব)-এ। (৩) অনুমানের জন্য কিছু না করা: শুধু ŷ দরকার হলে rank-ঘাটতি অনুমান নষ্ট করে না, কারণ ŷ column space-এর একটি বিন্দু, একক। সমস্যা শুধু coefficient-এর ব্যাখ্যায়, আর ভবিষ্যতে যদি সম্পর্কটি ভাঙে, যেমন production-এ “মোট”-এ ডেলিভারি চার্জ যোগ হলো, তখন। Multicollinearity-র পরিসংখ্যানিক দিক (VIF, standard error) AI-এর ভিত্তি কোর্সের পর্ব ৫৮-এ আছে।

সব “সম্পর্ক” rank কমায় না। rank শুধু linear নির্ভরশীলতা ধরে। revenue = price × qty থাকলে price, qty আর revenue তিনটি কলামের rank সাধারণত ৩: গুণফল linear combination নয়। আবার বয়স আর জন্মসাল দুটি থাকলে, বয়স = ২০২৬ − জন্মসাল, যা intercept কলামের ২০২৬ গুণ থেকে জন্মসাল বিয়োগ: linear, তাই intercept থাকলে rank কমে। Tree-ভিত্তিক model (পর্ব ৩২) এই ঘাটতিতে ভাঙে না, কারণ সেখানে কোনো linear system সমাধান করা হয় না; তবে feature importance দুই কলামে ভাগ হয়ে বিভ্রান্তিকর হতে পারে।

৮ · Numerical rank — float-এ “শূন্য” কত ছোট

খাতায় rank গোনা সহজ: সারি শূন্য হলো কি না দেখলেই হয়। কম্পিউটারে floating-point সংখ্যায় হিসাবের প্রতিটি ধাপে সামান্য রাউন্ডিং হয়, তাই “শূন্য” প্রায় কখনো ঠিক শূন্য থাকে না; অংশ ৬-এর ব্লকে A @ N-এর মান 10−15-এর ঘরে ছিল। তাই matrix_rank row reduction করে না। সে SVD দিয়ে matrix-এর singular value-গুলো বের করে, যা অ-ঋণাত্মক সংখ্যা σ1 ≥ σ2 ≥ … ≥ 0; নিখুঁত হিসাবে শূন্য-নয় singular value-এর সংখ্যাই rank. SVD-র পূর্ণ জ্যামিতি পর্ব ০৯ (SVD — low-rank approximation, pseudo-inverse আর recommender-এর ভিত্তি)-এ; এখানে শুধু এটুকু দরকার: সবচেয়ে ছোট singular value বলে matrix নির্ভরশীলতার কত কাছে আছে।

কোনটিকে শূন্য ধরা হবে, তার জন্য একটি সীমা বা tolerance লাগে। NumPy-র ডিফল্ট, ডকুমেন্টেশন অনুযায়ী MATLAB-এর সঙ্গে একই:

tol = σmax × max(m, n) × εmach

এখানে σmax সবচেয়ে বড় singular value, m × n matrix-এর আকার, আর εmach হলো machine epsilon, float64-এ প্রায় 2.2 × 10−16. যে singular value tol-এর চেয়ে বড়, শুধু সেগুলো গোনা হয়; এই গণনাকে বলে numerical rank. NumPy 2.0 থেকে rtol প্যারামিটারও আছে, যা সীমাটিকে σmax-এর ভগ্নাংশ হিসেবে নেয়। নিচের ব্লকে তৃতীয় কলাম = প্রথম দুটির যোগফল + delta × গোলমাল, delta শূন্য থেকে 10−3 পর্যন্ত।

import numpy as np
import matplotlib.pyplot as plt

rng = np.random.default_rng(42)
n = 50
x1 = rng.normal(size=n)
x2 = rng.normal(size=n)
noise = rng.normal(size=n)
eps = np.finfo(float).eps
print(f"machine eps = {eps:.2e}")
plt.figure(figsize=(6.4, 3.4), layout="constrained")
for delta in [0, 1e-15, 1e-12, 1e-8, 1e-3]:
    X = np.column_stack([x1, x2, x1 + x2 + delta * noise])   # তৃতীয় কলাম প্রায় নির্ভরশীল
    s = np.linalg.svd(X, compute_uv=False)
    tol = s[0] * max(X.shape) * eps                          # NumPy-র ডিফল্ট সীমা
    r_def = np.linalg.matrix_rank(X)
    r_loose = np.linalg.matrix_rank(X, rtol=1e-6)            # ডেটার নিজের নির্ভুলতা ধরে
    print(f"delta={delta:<6g} s_min={s[-1]:.1e} tol={tol:.1e} rank={r_def} rank(rtol=1e-6)={r_loose}")
    plt.semilogy([1, 2, 3], s, "o-", label=f"delta = {delta:g}")
plt.axhline(tol, color="k", ls="--", lw=1, label="default tol")
plt.xticks([1, 2, 3]); plt.xlabel("singular value index"); plt.ylabel("singular value (log)")
plt.title("A nearly dependent column: the smallest singular value"); plt.legend(fontsize=7)
plt.show()

আসল আউটপুট (ব্রাউজারের Python; ছবিটি কোডের নিচে আঁকা হয়):

machine eps = 2.22e-16
delta=0      s_min=2.3e-15 tol=1.0e-13 rank=2 rank(rtol=1e-6)=2
delta=1e-15  s_min=5.1e-15 tol=1.0e-13 rank=2 rank(rtol=1e-6)=2
delta=1e-12  s_min=4.0e-12 tol=1.0e-13 rank=3 rank(rtol=1e-6)=2
delta=1e-08  s_min=4.0e-08 tol=1.0e-13 rank=3 rank(rtol=1e-6)=2
delta=0.001  s_min=4.0e-03 tol=1.0e-13 rank=3 rank(rtol=1e-6)=3

delta = 0: তৃতীয় কলাম নিখুঁতভাবে প্রথম দুটির যোগফল, তবু সবচেয়ে ছোট singular value ঠিক শূন্য নয়, 10−15-এর ঘরে: রাউন্ডিংয়ের ছাপ। tol (প্রায় 10−13) তার চেয়ে বড়, তাই rank ২, সঠিক উত্তর। delta = 10−15: গোলমাল রাউন্ডিংয়ের সমান মাপের, তাই এখনো rank ২. delta = 10−12: s_min tol ছাড়িয়েছে, ডিফল্টে rank ৩! কিন্তু এমন ক্ষুদ্র পার্থক্য কোনো আসল মাপজোখে অর্থহীন; rtol = 10−6 ধরলে (অর্থাৎ σmax-এর দশ লাখ ভাগের এক ভাগের নিচে যা, তা শূন্য) rank আবার ২. delta = 10−3: এবার দুই সীমাতেই rank ৩. ছবিতে প্রথম দুটি singular value সব রেখায় প্রায় এক; শুধু তৃতীয়টি delta-র সঙ্গে ওঠানামা করে।

শিক্ষাটি হলো, numerical rank একটি সিদ্ধান্ত, শুধু হিসাব নয়। ডিফল্ট tol শুধু রাউন্ডিংয়ের ভুল ধরে; আপনার ডেটা যদি টাকায় পূর্ণসংখ্যায় মাপা হয়, বা সেন্সরের নির্ভুলতা তিন অঙ্ক, তাহলে তার চেয়ে ছোট পার্থক্য তথ্য নয়, গোলমাল। NumPy-র ডকুমেন্টেশনও বলে, ডেটার মাপের অনিশ্চয়তা জানা থাকলে সেই অনুযায়ী tolerance বাছা উচিত। Condition number = σmax / σmin; অংশ ৭-এর “total+noise” ক্ষেত্রটি rank পরীক্ষায় পাস করেছিল, কিন্তু condition number প্রায় 104 জানিয়ে দিয়েছিল যে coefficient-এ ভরসা কম। তাই বাস্তবে rank-এর সঙ্গে সবসময় singular value বা condition number-ও দেখুন।

আরও গভীরে: SVD হিসাবের স্থিতিশীল পদ্ধতি Gene Golub আর William Kahan-এর ১৯৬৫ সালের প্রবন্ধ থেকে এসেছে, আর পরে Golub–Reinsch (১৯৭০) পদ্ধতিটি প্রচলিত হয়; আজকের LAPACK এই ধারার উত্তরসূরি। SVD দামি বলে বড় matrix-এ rank-revealing QR (column pivoting-সহ QR) প্রায়ই সস্তা বিকল্প। np.linalg.lstsq LAPACK-এর SVD-ভিত্তিক একটি রুটিন ডাকে, যার rcond ঠিক এই tolerance-এর কাজ করে; scikit-learn-এর LinearRegression dense ডেটায় SciPy-র lstsq ব্যবহার করে, তাই অংশ ৭-এর মতো rank-ঘাটতিতেও সে চুপচাপ একটি উত্তর দেয়। Rank শব্দটি matrix-এর জন্য সাধারণত Frobenius-এর (১৮৭৯) নামে যুক্ত করা হয়।

পরীক্ষা ও ইন্টারভিউতে:

  • ৫ × ৮ matrix-এর rank ৩ হলে nullity কত? rank–nullity: ৮ − ৩ = ৫. আর rank কখনো ৫-এর বেশি হতে পারে না (min(5, 8)).
  • R3-এ চারটি vector কি independent হতে পারে? না; n-মাত্রায় সর্বোচ্চ n-টি স্বাধীন vector.
  • Basis আর spanning set-এর পার্থক্য? Basis = spanning + independent; spanning set-এ বাড়তি vector থাকতে পারে।
  • Dummy trap-কে linear algebra-র ভাষায় বলুন। সব dummy-র যোগফল intercept কলাম, তাই X-এর null space-এ (1, −1, …, −1); rank এক কম, coefficient একক নয়।
  • matrix_rank কীভাবে rank বের করে? SVD-র singular value গুনে, যেগুলো σmax · max(m, n) · ε-এর চেয়ে বড়।

৯ · AI-এর যুগে — linear algebra-র দাবি আর AI-এর কোড যাচাই

AI assistant linear algebra-র সংজ্ঞা সাধারণত ঠিক বলে, কিন্তু হাতের হিসাবে (row reduction, null space) আর NumPy-র খুঁটিনাটিতে আত্মবিশ্বাসী ভুল করে। ML কোডে এর প্রভাব নীরব, কারণ rank-ঘাটতি কোনো error দেয় না।

AI প্রায়ই যা করেকেন ভুলকীভাবে ধরবেন
Echelon form-এর কলামকে column space-এর basis বলেRow operation কলাম বদলায়, শুধু সম্পর্ক রাখেউত্তরের basis vector-গুলো আসল A-এর কলাম কি না দেখুন; rank দিয়ে span মিলিয়ে নিন
Determinant বা inv দিয়ে rank বা independence “পরীক্ষা” করেdet অ-বর্গ matrix-এ নেই, আর float-এ det-এর মাপ স্কেলে বদলায়matrix_rank আর singular value দেখুন
সব dummy আর intercept রেখে coefficient-এর অর্থ ব্যাখ্যা করেNull space আছে, coefficient একক নয়X-এর rank আর কলামের সংখ্যা তুলনা করুন
“rank পূর্ণ, তাই সমস্যা নেই” বলেপ্রায়-নির্ভরশীল কলামে rank পূর্ণ কিন্তু coefficient অস্থিরCondition number আর সবচেয়ে ছোট singular value দেখুন; কয়েকটি seed বা bootstrap-এ coefficient কতটা নড়ে মাপুন
পুরোনো বা বানানো API দেয় (যেমন lstsq-এ rcond=-1 ধরে নেওয়া, বা নেই এমন null_space প্যারামিটার)NumPy 2.0-তে ডিফল্ট বদলেছে; বানানো প্যারামিটার চলবে নানিজের version-এর অফিসিয়াল docs পড়ুন, ছোট উদাহরণে চালান

হাতের হিসাব চাইলে প্রতিটি ধাপ আর যাচাইয়ের কোড একসঙ্গে চেয়ে নিন; শেষ লাইনটি সবচেয়ে জরুরি।

আমার ৩ × ৪ matrix A = [[1, 2, 0, 1], [2, 4, 1, 4], [3, 6, 1, 5]]. ১. Row reduction-এর প্রতিটি ধাপ আলাদা লাইনে লেখো (কোন সারি থেকে কোনটির কত গুণ বিয়োগ), শেষে pivot কোন কোন কলামে। ২. Rank, column space-এর একটি basis (আসল A-এর কলাম থেকে) আর null space-এর একটি basis দাও। ৩. Rank–nullity দিয়ে উত্তর মিলিয়ে দেখাও। ৪. NumPy 2.x আর SciPy দিয়ে একটি ছোট যাচাই-কোড লেখো: matrix_rank, scipy.linalg.null_space, আর A @ n ≈ 0. ৫. তোমার উত্তরের কোন ধাপে ভুল হওয়ার ঝুঁকি বেশি, সেটিও বলো।

AI-এর দেওয়া হিসাব আর কোড হাতে পেলে — যাচাইয়ের চেকলিস্ট

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

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

প্র ০১স্বাধীন সারির সংখ্যা আর স্বাধীন কলামের সংখ্যা সবসময় সমান কেন? ডেটার ভাষায় এর মানে কী?

প্রথম দেখায় ব্যাপারটি অদ্ভুত। ১,০০০ জন গ্রাহক আর ২০টি feature-এর একটি X নিন। সারিগুলো R20-এর vector, কলামগুলো R1000-এর; দুটি সম্পূর্ণ আলাদা জগৎ। তবু “স্বাধীন গ্রাহকের সংখ্যা” আর “স্বাধীন feature-এর সংখ্যা” সমান হতে বাধ্য।

একটি সহজ যুক্তি: ধরুন column space-এর dimension r, আর তার একটি basis-কে কলাম করে একটি m × r matrix C বানাই। A-এর প্রতিটি কলাম C-এর কলামের combination, তাই A = C R লেখা যায়, যেখানে R একটি r × n matrix (প্রতিটি কলামে সেই combination-এর সংখ্যা)। এখন উল্টো দিক থেকে পড়ুন: A-এর প্রতিটি সারি হলো R-এর r-টি সারির একটি combination (C-এর সংশ্লিষ্ট সারির সংখ্যা দিয়ে)। তাই row space-এর dimension ≤ r = column rank. একই যুক্তি AT-এ চালালে উল্টো অসমতাও আসে, অতএব দুটি সমান। অংশ ৫-এর A-তে এটি চোখে দেখা যায়: R3 = R1 + R2, আর c2, c4 বাড়তি; দুই দিকেই ২.

ML-এর জন্য এর সবচেয়ে বড় ফল rank X ≤ min(n, d). Text-এ TF-IDF বা জিনের ডেটায় প্রায়ই feature-এর সংখ্যা d উদাহরণের সংখ্যা n-এর চেয়ে অনেক বেশি; তখন rank ≤ n < d, তাই null space-এর dimension অন্তত d − n, আর সাধারণ least squares-এর coefficient কখনোই একক নয়, কোনো কলাম বাদ না দিলেও। এজন্যই উচ্চ-মাত্রার ডেটায় ridge বা lasso-র মতো regularization প্রায় আবশ্যিক, আর কেন তা কাজ করে তা পর্ব ১৭-এ আসবে।

আরেকটি দিক: সারির নির্ভরশীলতা মানে কিছু গ্রাহক অন্যদের “মিশ্রণ”, যেমন একই গ্রাহকের ডুপ্লিকেট সারি। এটি rank-এ তত ক্ষতি করে না যতক্ষণ সারির সংখ্যা যথেষ্ট, কিন্তু train আর test-এ একই সারি থাকলে leakage ঘটায় (AI-এর ভিত্তি কোর্সের পর্ব ৫৬)।

মূল উপলব্ধি: একটি ডেটাসেটে কত “আসল তথ্যের দিক” আছে, তা একটিই সংখ্যা, সারি দিয়ে গুনুন বা কলাম দিয়ে। আর সেই সংখ্যা উদাহরণ আর feature, দুটির ছোটটিকে ছাড়াতে পারে না।

প্র ০২Dummy trap-এর তিনটি সমাধান — একটি category বাদ, intercept বাদ, না regularization — কোনটি কখন?

তিনটিই null space থেকে মুক্তি দেয়, কিন্তু coefficient-এর অর্থ আলাদা করে। ধরুন বাজারঘরের ডেলিভারি সময়ের model-এ জেলা ঢাকা, চট্টগ্রাম, সিলেট।

একটি category বাদ (ঢাকা): intercept তখন ঢাকার গড় (অন্য feature শূন্য ধরে), আর চট্টগ্রামের coefficient মানে “ঢাকার তুলনায় কত মিনিট বেশি”। এটি পরিসংখ্যানে প্রচলিত, statsmodels-এর formula-ও ডিফল্টে এমন করে। দাম: কোনটি reference হবে তা একটি পছন্দ, আর reference-এ খুব কম উদাহরণ থাকলে সব coefficient-এর অনিশ্চয়তা বাড়ে। সাধারণত সবচেয়ে বড় বা স্বাভাবিক category-কে reference রাখা হয়।

Intercept বাদ, সব dummy রাখা: সব-1 কলাম নেই, তাই null vector (1, −1, −1, −1) আর নেই। প্রতিটি জেলার coefficient তখন সেই জেলার নিজস্ব গড়। কিন্তু দ্বিতীয় একটি category feature (যেমন পণ্যের ধরন) যোগ করলেই আবার একই সমস্যা: দুই দলের dummy-র যোগফল দুটিই সব-1, তাই তাদের পার্থক্য null space-এ। তাই একাধিক category-তে এই পথ চলে না।

Regularization (ridge), সব dummy রাখা: λ > 0 হলে উত্তর একক, আর কোনো category বিশেষ সুবিধা পায় না; ridge null space বরাবর সবচেয়ে ছোট coefficient বাছে, তাই জেলার প্রভাবগুলো গড়ের চারপাশে ভারসাম্যপূর্ণভাবে ভাগ হয়। Prediction-কেন্দ্রিক ML-এ এটি খুব প্রচলিত; scikit-learn-এর OneHotEncoder-এর ডিফল্ট drop=None, অর্থাৎ সব কলাম রাখা, এই চর্চার সঙ্গে মেলে। দাম: coefficient এখন λ-নির্ভর, পরিসংখ্যানিক পরীক্ষা (p-value) সরলভাবে খাটে না।

Tree-ভিত্তিক model-এ (পর্ব ৩২–৩৬) কোনো linear system নেই, তাই সব dummy রাখলেও গাণিতিক সমস্যা নেই; সেখানে প্রশ্নটি বরং অনেক category-র কলাম-বিস্ফোরণ। আর deep learning-এ category-র জন্য embedding ব্যবহার হয়, সেখানেও “একক” coefficient কেউ আশা করে না।

মূল উপলব্ধি: সমাধানটি বাছুন আপনার প্রশ্ন দেখে। ব্যাখ্যা চাইলে reference category, শুধু অনুমান চাইলে regularization; আর যেটিই নিন, coefficient-এর অর্থ রিপোর্টে লিখে দিন।

প্র ০৩Tolerance কে ঠিক করবে — library-র ডিফল্ট, না ডেটার মালিক? ভুল tolerance-এ কী হয়?

Library-র ডিফল্ট tol = σmax · max(m, n) · ε একটি খুব নির্দিষ্ট প্রশ্নের উত্তর দেয়: “যদি ইনপুটের সংখ্যাগুলো একদম নিখুঁত হতো, তাহলে SVD হিসাবের রাউন্ডিং কতটা গোলমাল আনতে পারে?” NumPy-র ডকুমেন্টেশন নিজেই বলে, এটি MATLAB আর Numerical Recipes-এর পরিচিত সীমা, আর ডেটার অনিশ্চয়তা জানা থাকলে অন্য সীমা বেছে নেওয়া উচিত।

বাস্তব ডেটা নিখুঁত নয়। বাজারঘরের খরচ টাকায় রাউন্ড করা, ডেলিভারির দূরত্ব GPS থেকে কয়েক মিটার ভুলসহ, সেন্সরের মাপ তিন-চার অঙ্ক পর্যন্ত। অংশ ৮-এর ব্লকে delta = 10−12-এর কলাম ডিফল্টে “স্বাধীন”, কিন্তু কোনো আসল মাপে এই পার্থক্য অর্থহীন। ভুল দিক দুটি: tol খুব ছোট হলে প্রায়-নির্ভরশীল কলাম স্বাধীন ধরা হয়, আর সমাধান সেই ক্ষুদ্র পার্থক্যকে বিশাল coefficient দিয়ে fit করে (অংশ ৭-এর −৩.৮ আর +৩.৯); tol খুব বড় হলে আসল তথ্যের একটি দিক ফেলে দেওয়া হয়, model দুর্বল হয়।

Numerical analysis-এ এজন্য “effective rank” বা “ε-rank” ধারণা আছে: σk+1 যদি ডেটার গোলমালের মাপের নিচে থাকে, তাহলে k-ই কার্যকর rank. ব্যবহারিক কৌশল: singular value-গুলো log স্কেলে আঁকুন (অংশ ৮-এর ছবির মতো); প্রায়ই একটি স্পষ্ট লাফ দেখা যায়, যেখানে সংকেত শেষ আর গোলমাল শুরু। লাফ না থাকলে, অর্থাৎ singular value ধীরে ধীরে কমলে, কোনো একক “সঠিক” rank নেই; তখন regularization একটি মসৃণ বিকল্প, কারণ ridge ছোট singular value-এর দিকগুলোকে ধীরে ধীরে দমায়, হঠাৎ কেটে ফেলে না। এর হিসাব পর্ব ০৯ আর ১৭-এ।

আরেকটি সূক্ষ্মতা: tolerance আপেক্ষিক (σmax-এর গুণিতক), তাই কলামের স্কেল গুরুত্বপূর্ণ। একটি কলাম টাকায় আর আরেকটি কোটি টাকায় হলে ছোট স্কেলের কলামের তথ্যও “ছোট singular value” হয়ে কাটা পড়তে পারে। Rank বা condition number দেখার আগে কলামগুলো standardize করা ভালো অভ্যাস।

মূল উপলব্ধি: ডিফল্ট tolerance কম্পিউটারের ভুল সামলায়, আপনার ডেটার ভুল নয়। ডেটার নির্ভুলতা জানেন আপনি, তাই সীমা ঠিক করার দায়ও আপনার।

প্র ০৪Rank-ঘাটতি অনুমানের ক্ষতি করে না, তাহলে এত সতর্কতা কেন? কখন এটি সত্যিই বিপদ?

কথাটি অর্ধেক সত্য। অংশ ৭-এ w আর w + 2n একই ŷ দিয়েছে, পার্থক্য 10−14. কারণ ŷ = Xw সবসময় column space-এর একটি বিন্দু, আর least squares-এর সেরা বিন্দুটি একক (পর্ব ০৭-এ projection হিসেবে দেখবেন)। তাই train ডেটায়, আর একই নিয়ম মেনে চলা ভবিষ্যৎ ডেটায়, অনুমান ঠিক থাকে।

বিপদ তিন জায়গায়। প্রথম, সম্পর্ক ভেঙে গেলে। “মোট = তিনটির যোগফল” train-এ সত্য, কিন্তু ছয় মাস পর ডেটা দল “মোট”-এ ডেলিভারি চার্জ যোগ করল। এখন নতুন সারি null space-এর দিকেও একটু সরে গেছে, আর null space বরাবর coefficient এলোমেলো (lstsq-এর বাছাই, বা প্রায়-নির্ভরশীলতায় বিশাল), তাই অনুমান হঠাৎ অদ্ভুত হয়। অংশ ৭-এর −৩.৮ / +৩.৯ coefficient-এ “মোট” ১,০০০ টাকা বাড়লে অনুমান প্রায় ৩.৯ হাজার টাকা লাফায়। এটি distribution shift-এর একটি রূপ, যা পর্ব ৫৯-এ আসবে।

দ্বিতীয়, ব্যাখ্যা। ব্যবসায়ী দল জানতে চায় “মুদি খরচ এক হাজার বাড়লে লাভ কত বাড়ে”। rank-ঘাটতিতে এর উত্তর ডেটায় নেই; যেকোনো সংখ্যা বলা যায়। AI-এর ভিত্তি কোর্সের পর্ব ৫৮-এর মতো ঋণাত্মক coefficient দেখে “মুদি বিক্রি লাভ কমায়” সিদ্ধান্ত বিপজ্জনক। Feature importance বা SHAP-এর মতো ব্যাখ্যা-পদ্ধতিতেও (পর্ব ৫৬–৫৭) সম্পর্কযুক্ত feature-এর মধ্যে কৃতিত্ব ভাগ নিয়ে একই ধরনের অস্পষ্টতা আসে।

তৃতীয়, সংখ্যাগত স্থিতি। নিখুঁত নির্ভরশীলতা ধরা সহজ; প্রায়-নির্ভরশীলতায় কিছু solver (বিশেষ করে normal equations-এ inv(XTX)) রাউন্ডিংয়ে বড় ভুল করে, কারণ XTX-এর condition number X-এর condition number-এর বর্গ। AI-এর ভিত্তি কোর্সের পর্ব ১৭-এর “inverse নয়, solve/lstsq” নিয়মের কারণ এটাই।

মূল উপলব্ধি: rank-ঘাটতি বলে, “ডেটা এই প্রশ্নের উত্তর জানে না।” অনুমান টেকে যতক্ষণ পৃথিবী train ডেটার নিয়ম মানে; ব্যাখ্যা টেকে না কখনোই।

প্র ০৫৭৬৮-মাত্রার embedding বা লাখো parameter-এর network-এ “dimension” আর “rank” কথাগুলোর মানে কী থাকে?

Text embedding (AI-এর ভিত্তি কোর্সের পর্ব ৬৯) প্রায়ই কয়েকশো মাত্রার vector. কিন্তু হাজার হাজার বাক্যের embedding সারি করে matrix বানালে তার singular value প্রায়ই দ্রুত কমে; অর্থাৎ ডেটা পুরো R768 জুড়ে ছড়ানো নয়, কিছু কম মাত্রার subspace বা বাঁকা পৃষ্ঠের কাছাকাছি থাকে। “Ambient dimension” (যে জগতে vector রাখা) আর “effective” বা “intrinsic dimension” (ডেটা আসলে যত মাত্রা ব্যবহার করে) আলাদা। কিছু গবেষণায় দেখা গেছে embedding-এর কিছু দিক প্রায় সব vector-এ একই রকম থাকে, যাকে anisotropy বলে; তবে মাত্রা আর মডেল ভেদে ফল আলাদা, তাই সাধারণ সংখ্যা বলা যায় না। PCA বা SVD দিয়ে মাত্রা কমানোর যুক্তি এখান থেকেই আসে, পর্ব ০৯-এ।

Neural network-এ parameter-এর সংখ্যা প্রায়ই train উদাহরণের চেয়ে বেশি। একটি linear model-এ এর মানে d > n, তাই X-এর null space-এর dimension অন্তত d − n: train ভুল শূন্য করার মতো অসংখ্য w আছে। তাহলে gradient descent কোনটি বেছে নেয়? Linear least squares-এ একটি পরিচিত ফল: শূন্য থেকে শুরু করলে gradient-এর প্রতিটি ধাপ XT(…) আকারের, অর্থাৎ row space-এর ভেতরে; null space-এর দিকে w কখনো সরে না। তাই gradient descent সবচেয়ে ছোট norm-এর সমাধানে পৌঁছায়, ঠিক lstsq-এর মতো। এই “implicit bias” পর্ব ০৩-এর double descent আলোচনার একটি গাণিতিক ভিত্তি; non-linear network-এ ছবিটি আরও জটিল আর গবেষণা চলছে।

আরেকটি আধুনিক ব্যবহার: বড় language model fine-tune করার LoRA পদ্ধতি (Hu ও সহকর্মীরা, ২০২১) ধরে নেয় যে weight-এর পরিবর্তন ΔW একটি low-rank matrix, তাই সেটিকে দুটি সরু matrix-এর গুণফল BA হিসেবে শেখানো হয়; শেখার parameter অনেক কমে। এটি একটি অনুমান যা অনেক কাজে ভালো চলে বলে রিপোর্ট হয়েছে, সব কাজে নয়। Deep Learning আর Generative AI কোর্সে এর বিস্তার আসবে।

মূল উপলব্ধি: মাত্রা গোনা সহজ, rank বোঝা কঠিন। বড় model-এ প্রশ্নটি “কত মাত্রা আছে” নয়, “ডেটা আর শেখা কতগুলো দিক আসলে ব্যবহার করছে, আর বাকি দিকগুলোতে কী ঘটছে”।

অনুশীলন

হিসাবগুলো খাতায় করুন, তারপর উত্তর মেলান। একটির জন্য কোড লেখা লাগবে।

  1. Row reduction-এর numerical: M = [[1, 2, 3], [2, 4, 7], [1, 2, 4]]. (ক) Row reduction দিয়ে rank বের করুন। (খ) Column space-এর একটি basis আর null space-এর একটি basis দিন; rank–nullity মিলিয়ে দেখান। (গ) b = (1, 3, 2) কি column space-এ আছে? থাকলে column space-এর basis-এ তার coordinates কত?

    (ক) R2 ← R2 − 2R1 = (0, 0, 1); R3 ← R3 − R1 = (0, 0, 1); R3 ← R3 − R2 = (0, 0, 0). Echelon form [[1, 2, 3], [0, 0, 1], [0, 0, 0]], pivot c1 আর c3-এ, rank ২.

    (খ) Column space-এর basis আসল M থেকে: (1, 2, 1) আর (3, 7, 4). Null space: x3 = 0 আর x1 + 2x2 + 3x3 = 0, x2 = s ধরে x = s(−2, 1, 0). nullity ১, আর ২ + ১ = ৩ কলাম। যাচাই: M·(−2, 1, 0) = (−2 + 2, −4 + 4, −2 + 2) = (0, 0, 0).

    (গ) α(1, 2, 1) + β(3, 7, 4) = (1, 3, 2): প্রথম দুটি থেকে α + 3β = 1 আর 2α + 7β = 3, তাই β = 1, α = −2. তৃতীয় উপাদানে −2 + 4 = 2, মিলেছে। তাই b column space-এ, আর ওই basis-এ তার coordinates (−2, 1). (Mx = b-এর একটি সমাধান x = (−2, 0, 1); তার সঙ্গে null space-এর যেকোনো গুণিতক যোগ করলেও সমাধান।)

  2. সমালোচনা ও নকশা: বাজারঘরের একজন analyst একটি linear model-এর জন্য এই feature-গুলো বানালেন: intercept, price, qty, revenue (= price × qty), food_share, grocery_share, other_share (তিনটি খরচের ভাগ, যোগফল সবসময় ১), age আর birth_year (age = 2026 − birth_year). কোন কোন সেট rank-ঘাটতি তৈরি করে, কোনটি করে না, আর আপনি feature তালিকা কীভাবে ঠিক করবেন?

    ঘাটতি করে: (১) তিনটি share-এর যোগফল = intercept কলাম, null vector (1, −1, −1, −1) এই কলামগুলোর ওপর। (২) age + birth_year = 2026 × intercept, null vector-এ intercept-এর ঘরে 2026, age আর birth_year-এর ঘরে −1. মোট rank-ঘাটতি অন্তত ২.

    করে না: revenue = price × qty গুণফল, linear combination নয়, তাই rank কমায় না; তবে তিনটি কলাম সম্পর্কযুক্ত হতে পারে, তাই condition number দেখা দরকার। সমাধান: একটি share বাদ দিন (বাকি দুটির coefficient সেই বাদ পড়াটির তুলনায় পড়তে হবে), age বা birth_year-এর একটি রাখুন। তারপর X-এর rank = কলামের সংখ্যা কি না, আর condition number কত, তা কোডে পরীক্ষা করুন। শুধু অনুমান লক্ষ্য হলে ridge দিয়েও চলে, কিন্তু ব্যাখ্যার রিপোর্টে বাদ দেওয়াই পরিষ্কার।

  3. আউটপুট অনুমান করুন: চালানোর আগে লিখে ফেলুন নিচের কোড কী ছাপবে।
    import numpy as np
    from scipy.linalg import null_space
    A = np.array([[1., 2.], [2., 4.], [3., 6.]])
    B = np.array([[1., 0., 1.], [0., 1., 1.]])
    print(np.linalg.matrix_rank(A), null_space(A).shape)
    print(np.linalg.matrix_rank(B), null_space(B).shape)
    print(np.linalg.matrix_rank(np.eye(3) * 1e-20))
    1 (2, 1)
    2 (3, 1)
    3

    A-এর দ্বিতীয় কলাম প্রথমটির দ্বিগুণ: rank ১, আর কলাম ২টি, তাই nullity ১; null_space-এর shape (কলামের সংখ্যা, nullity) = (2, 1). B-এর দুটি সারি স্বাধীন: rank ২, কলাম ৩টি, nullity ১, shape (3, 1), basis vector (1, 1, −1)-এর দিকে। শেষ লাইনটি ফাঁদ: সব singular value 10−20, খুব ছোট, কিন্তু tolerance আপেক্ষিক (σmax × 3 × ε ≈ 1.3 × 10−35), তাই তিনটিই গোনা হয়: rank ৩. শুধু স্কেল ছোট হলে rank কমে না।

  4. কোড লিখুন: একটি function independent_columns(X) লিখুন, যা বাঁ থেকে ডানে কলাম দেখে শুধু সেই কলামের index রাখে যা rank বাড়ায়। intercept, food, grocery, other, total (= তিনটির যোগফল) কলামের একটি X-এ চালান; তারপর কলামের ক্রম উল্টে total আগে দিয়ে আবার চালান। কী পার্থক্য দেখলেন, আর এর অর্থ কী?
    import numpy as np
    
    def independent_columns(X):
        keep = []
        for j in range(X.shape[1]):
            if np.linalg.matrix_rank(X[:, keep + [j]]) > len(keep):
                keep.append(j)
        return keep
    
    rng = np.random.default_rng(7)
    f, g, o = rng.uniform(1, 8, 6), rng.uniform(1, 6, 6), rng.uniform(0, 4, 6)
    X = np.column_stack([np.ones(6), f, g, o, f + g + o])
    print(independent_columns(X))
    print(independent_columns(X[:, [4, 1, 2, 3, 0]]))

    সত্যিকারের run (ডেস্কটপ, Python 3.14.4, NumPy 2.5.1):

    [0, 1, 2, 3]
    [0, 1, 2, 4]

    প্রথম ক্রমে total (index 4) বাদ পড়ে, কারণ সেটি আগের তিনটির যোগফল। দ্বিতীয় ক্রমে [total, food, grocery, other, intercept]: total, food, grocery রাখা হয়, other (index 3) বাদ পড়ে, কারণ other = total − food − grocery; শেষে intercept রাখা হয়। শিক্ষা: কোন কলাম “বাড়তি”, তা একক নয়; নির্ভরশীল সেটের যেকোনো একটিকে বাদ দেওয়া যায়, আর কোনটি বাদ যাবে তা ক্রমের ওপর নির্ভর করে। তাই কোনটি রাখবেন, তা ব্যাখ্যার সুবিধা দেখে নিজে ঠিক করুন, algorithm-এর ওপর ছেড়ে দেবেন না। (এই greedy পদ্ধতি প্রতিবার SVD চালায়, তাই বড় X-এ ধীর; বড় ডেটায় pivoting-সহ QR একই কাজ সস্তায় করে।)

নিজেকে যাচাই করুন

ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।

ক্রমএকটি matrix-এর rank আর null space হাতে বের করার ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)

  1. প্রথম কলামে একটি শূন্য-নয় pivot বেছে তার নিচের সংখ্যাগুলো row operation দিয়ে শূন্য করা
  2. পরের সারি আর কলামে একই কাজ চালিয়ে row echelon form-এ পৌঁছানো
  3. Pivot গুনে rank, আর pivot কলামের নম্বর দেখে আসল matrix থেকে column space-এর basis নেওয়া
  4. Free চলকগুলোকে প্যারামিটার ধরে Ax = 0-এর সাধারণ সমাধান লেখা, যা null space-এর basis দেয়
  5. rank + nullity = কলামের সংখ্যা মিলিয়ে, আর A·n = 0 কষে উত্তর যাচাই করা

R2-এর নিচের কোন উপসংগ্রহটি subspace?

  • রেখা y = 2x + 1-এর সব বিন্দু
  • x-অক্ষ আর y-অক্ষের সব বিন্দু একসঙ্গে
  • যেসব (x, y)-এ x + y = 0
  • যেসব (x, y)-এ x ≥ 0 আর y ≥ 0

একটি 5 × 8 matrix-এর rank ৩. তার null space-এর dimension (nullity) কত?

  • ২
  • ৫
  • ৮
  • ৩

a = (1, 2, 3), b = (2, 4, 6), c = (0, 1, 1) — এই তিনটি vector সম্পর্কে কোনটি সত্য?

  • Dependent, আর তাদের span একটি সমতল (dimension ২)
  • Independent, তাই তারা R³-এর একটি basis
  • Dependent, আর তাদের span একটি রেখা
  • R³-এ তিনটি vector সবসময় dependent

Basis B = {u = (1, 1), v = (1, −1)}-এ বিন্দু p = (3, 1)-এর coordinates কত?

  • (3, 1)
  • (1, 2)
  • (1, 1)
  • (2, 1)

একটি linear regression-এ intercept-এর সঙ্গে চারটি জেলার চারটি one-hot কলামই রাখা হয়েছে (প্রতিটি সারিতে ঠিক একটি ১)। Design matrix-এ মোট ৫টি কলাম, সারি অনেক। কোনটি ঘটে?

  • Library সঙ্গে সঙ্গে error দিয়ে থেমে যায়
  • Rank ৫, কিন্তু condition number একটু বড়
  • Rank ৪; অনুমান একক, কিন্তু coefficient অসংখ্য উপায়ে লেখা যায়
  • Rank ৪, তাই অনুমানও অনির্দিষ্ট

একটি 50 × 3 matrix-এর singular value 9.1, 6.7 আর 4 × 10−12; NumPy-র ডিফল্ট tolerance প্রায় 1 × 10−13. ডেটা মাপা হয়েছে প্রায় তিন অঙ্কের নির্ভুলতায়। সবচেয়ে যুক্তিসঙ্গত সিদ্ধান্ত কোনটি?

  • ডিফল্টে rank ৩, তাই তিনটি কলামই স্বাধীন তথ্য দেয়
  • কার্যকর rank ২; একটি কলাম প্রায় নির্ভরশীল, তাই বাদ দেওয়া বা regularization বিবেচনা করা উচিত
  • Singular value-এর হিসাবে ভুল হয়েছে, আবার চালানো উচিত
  • Rank ১, কারণ একটি singular value খুব ছোট

শব্দকোষ

লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:

মনে রাখুন

  1. Subspace পরীক্ষা: শূন্য আছে, যোগে বন্ধ, গুণে বন্ধ। মূলবিন্দু দিয়ে না যাওয়া রেখা subspace নয়।
  2. Span = সব linear combination; independent = শূন্যে পৌঁছানোর একমাত্র উপায় সব c = 0; basis = spanning + independent; তার আকার dimension.
  3. Basis-এ coordinates একক, পেতে B c = x সমাধান: u = (2, 1), v = (1, 3)-এ (4, 7)-এর ঠিকানা (1, 2).
  4. Rank = pivot-এর সংখ্যা = dim C(A) = dim row space; rank + nullity = কলামের সংখ্যা; x আর x + n (n ∈ N(A)) একই Ax দেয়।
  5. ML-এ rank-ঘাটতি (বাড়তি কলাম, dummy trap) মানে অসংখ্য coefficient, একই অনুমান; প্রায়-নির্ভরশীলতা আরও বিপজ্জনক। matrix_rank singular value গোনে tolerance মেনে; ডেটার নির্ভুলতা দেখে সীমা বাছুন আর condition number-ও দেখুন।

পরের পর্বে: এই পর্বে matrix ছিল কলামের সংগ্রহ। পর্ব ০৭ (Matrix-এর জ্যামিতি — projection, rotation আর least squares) matrix-কে একটি রূপান্তর হিসেবে দেখবে: ঘোরানো, টানা, প্রতিফলন আর projection; আর দেখাবে least squares আসলে y-কে column space-এ ফেলা ছায়া, যার residual column space-এর সঙ্গে সমকোণে।

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

এই পর্বটি শেয়ার করুন:
এই পর্বে ভুল পেয়েছেন? জানান