0Pricing
Pandas & NumPy Academy · درس

حل الأنظمة الخطية

حل Ax=b باستخدام np.linalg.solve، وقارن ذلك بالنهج الساذج القائم على ضرب المعكوس من حيث الاستقرار العددي

حل الأنظمة الخطية درس مجاني في Pandas & NumPy Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Pandas & NumPy Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Pandas & NumPy Academy 4 دروس في المجموع.

بعض أجزاء هذا الدرس لم تُترجم بعد وتظهر باللغة الإنجليزية.

What Is a Linear System?

A system of linear equations can be written in matrix form as Ax = b, where A is the coefficient matrix, x is the vector of unknowns, and b is the right-hand side vector. For example, two equations with two unknowns can be expressed as a 2×2 matrix equation. Solving the system means finding x such that A multiplied by x equals b. NumPy's np.linalg.solve(A, b) handles this efficiently and accurately.

import numpy as np

# System: 2x + y = 5
#         x + 3y = 10
A = np.array([[2.0, 1.0],
              [1.0, 3.0]])
b = np.array([5.0, 10.0])

x = np.linalg.solve(A, b)
print('Solution x:', x)
print('Verify A @ x == b:', np.allclose(A @ x, b))

Why Not Use the Inverse?

Mathematically, the solution to Ax = b is x = A⁻¹b. But computing np.linalg.inv(A) @ b is slower and less accurate than calling np.linalg.solve(A, b) directly. solve() uses LU decomposition internally, which requires fewer operations and accumulates less floating-point error. The rule of thumb: if you are solving for x in Ax=b, always use solve, never inv.

import numpy as np

A = np.random.rand(100, 100)
b = np.random.rand(100)

# Avoid this pattern
x_inv = np.linalg.inv(A) @ b

# Prefer this
x_solve = np.linalg.solve(A, b)

print('Max difference:', np.max(np.abs(x_inv - x_solve)))
# solve is faster AND more accurate

Requirements for solve()

np.linalg.solve(A, b) requires that A is square and non-singular. If A is singular (determinant is zero), the function raises np.linalg.LinAlgError: Singular matrix. A is singular when rows are linearly dependent — for example, one equation is just a multiple of another. Always check that your system is well-posed before calling solve. If A is not square, use np.linalg.lstsq() instead.

import numpy as np

# Well-posed system
A = np.array([[1.0, 2.0], [3.0, 4.0]])
b = np.array([5.0, 6.0])
print('Solution:', np.linalg.solve(A, b))

# Singular system (row 2 = 3 * row 1)
A_singular = np.array([[1.0, 2.0], [3.0, 6.0]])
try:
    np.linalg.solve(A_singular, b)
except np.linalg.LinAlgError as e:
    print('Error:', e)

LU Decomposition Under the Hood

np.linalg.solve internally applies LU decomposition: it factors A into a lower-triangular matrix L and an upper-triangular matrix U such that A = LU. Solving then becomes two simpler triangular solves (forward and back substitution), which are far more efficient than Gaussian elimination repeated from scratch. This is the same algorithm used by MATLAB, Fortran LAPACK, and virtually every scientific computing library.

import numpy as np
from scipy import linalg

A = np.array([[2.0, 1.0, -1.0],
              [-3.0, -1.0, 2.0],
              [-2.0, 1.0, 2.0]])
b = np.array([8.0, -11.0, -3.0])

# NumPy solve (uses LAPACK dgesv under the hood)
x = np.linalg.solve(A, b)
print('Solution:', x)
print('Check:', np.allclose(A @ x, b))

Solving Multiple Right-Hand Sides

np.linalg.solve(A, B) can handle a matrix B with multiple columns, solving for each column simultaneously. If B has shape (n, k), the result X has shape (n, k), where each column of X is the solution for the corresponding column of B. This is useful in physics simulations and machine learning where you need to solve the same coefficient matrix with many different right-hand sides.

import numpy as np

A = np.array([[3.0, 1.0],
              [1.0, 2.0]])

# Three right-hand side vectors at once
B = np.array([[9.0, 3.0, 6.0],
              [8.0, 4.0, 2.0]])

X = np.linalg.solve(A, B)
print('Solutions X shape:', X.shape)  # (2, 3)
print('Verify A @ X == B:', np.allclose(A @ X, B))

Least Squares with np.linalg.lstsq()

When the system is over-determined (more equations than unknowns), no exact solution exists. np.linalg.lstsq(A, b) finds the x that minimises the sum of squared residuals ||Ax - b||² — this is exactly what linear regression computes. It returns the solution x, residuals, rank, and singular values. The rcond=None argument suppresses a deprecation warning and sets the cutoff for treating singular values as zero.

import numpy as np

# Over-determined: 4 equations, 2 unknowns
A = np.array([[1.0, 1.0],
              [1.0, 2.0],
              [1.0, 3.0],
              [1.0, 4.0]])
b = np.array([2.0, 2.5, 3.5, 4.5])

x, residuals, rank, sv = np.linalg.lstsq(A, b, rcond=None)
print('Least-squares solution:', x)
print('Residuals:', residuals)
print('Rank:', rank)

Applying solve() in Linear Regression

The normal equations of ordinary least squares are A.T @ A @ x = A.T @ b, which is a square system solvable with np.linalg.solve. This gives the same result as lstsq when A.T @ A is well-conditioned. In practice, lstsq is preferred because it uses SVD and is stable even when columns are nearly collinear, but the normal equations help you understand the math behind regression.

import numpy as np

np.random.seed(0)
X = np.column_stack([np.ones(50), np.random.rand(50) * 10])
y = 3.0 + 2.0 * X[:, 1] + np.random.randn(50)

# Solve normal equations
coeffs = np.linalg.solve(X.T @ X, X.T @ y)
print('Intercept:', round(coeffs[0], 3))
print('Slope:', round(coeffs[1], 3))

Checking the Condition Number

Before solving, it is good practice to check the condition number with np.linalg.cond(A). A condition number close to 1 means the system is well-conditioned and the solution is reliable. A very large condition number (e.g., 1e12) means the matrix is nearly singular: small changes in b produce huge changes in x, and the solution may be numerically unreliable. In that case, consider regularisation (ridge regression) or using a more robust solver.

import numpy as np

# Well-conditioned
A1 = np.array([[2.0, 1.0], [1.0, 3.0]])
print('Condition number (well):', np.linalg.cond(A1))

# Ill-conditioned (nearly linearly dependent rows)
A2 = np.array([[1.0, 1.0], [1.0, 1.0001]])
print('Condition number (ill):', np.linalg.cond(A2))

Sparse Systems: When Not to Use linalg

For very large systems where A has mostly zero entries (a sparse matrix), storing the full matrix wastes memory and using dense np.linalg.solve is slow. SciPy provides scipy.sparse and scipy.sparse.linalg.spsolve that exploit sparsity for huge systems like finite element models or network problems. Understanding when your matrix is sparse is an important performance consideration in scientific computing.

import numpy as np

# Dense solve is fine for small-to-medium systems
A = np.random.rand(200, 200)
b = np.random.rand(200)
x = np.linalg.solve(A, b)
print('Dense solve OK, solution shape:', x.shape)

# For large sparse systems, use scipy.sparse.linalg.spsolve instead
# from scipy.sparse.linalg import spsolve
# x = spsolve(A_sparse, b)

Interpreting the Solution Vector

Once you have the solution vector x from np.linalg.solve(A, b), always verify it by computing A @ x and checking it against b using np.allclose(A @ x, b). In floating-point arithmetic, you rarely get exact equality — allclose checks within a small tolerance. The residual ||Ax - b|| should be near machine epsilon times the scale of the problem for a well-conditioned system.

import numpy as np

A = np.array([[4.0, 3.0, 2.0],
              [1.0, 5.0, 3.0],
              [2.0, 1.0, 6.0]])
b = np.array([10.0, 20.0, 15.0])

x = np.linalg.solve(A, b)
print('Solution:', np.round(x, 4))

# Residual check
residual = np.linalg.norm(A @ x - b)
print('Residual ||Ax - b||:', residual)
print('Valid:', np.allclose(A @ x, b))

Solving in Machine Learning Pipelines

Linear solvers appear throughout machine learning: linear regression solves the normal equations, Gaussian processes solve kernel matrix systems, and Kalman filters solve state-update equations. By understanding np.linalg.solve and lstsq, you can implement these algorithms from scratch and debug them when results are unexpected. NumPy's linalg module gives you the same numerical tools used in production scientific libraries.

import numpy as np

# Ridge regression: (X.T @ X + lambda * I) @ w = X.T @ y
np.random.seed(42)
X = np.random.rand(100, 5)
y = np.random.rand(100)
lambda_reg = 0.1
n_features = X.shape[1]

A = X.T @ X + lambda_reg * np.eye(n_features)
bvec = X.T @ y
w = np.linalg.solve(A, bvec)
print('Ridge regression weights:', np.round(w, 4))

Quick Check

Test your understanding of Data Analysis concepts from this lesson.

Lesson Recap

In this lesson you learned: np.linalg.solve(A, b) efficiently solves square linear systems using LU decomposition, np.linalg.lstsq() finds the least-squares solution for over-determined systems, and the condition number measures numerical stability — large values warn of near-singular matrices. Next up we explore eigenvalues and the SVD, which underpin PCA and many ML algorithms.

الأسئلة الشائعة

هل درس «حل الأنظمة الخطية» مجاني؟

نعم — نص درس «حل الأنظمة الخطية» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Pandas & NumPy Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Pandas & NumPy Academy 4 دروس في المجموع.

ماذا ستتعلم في «حل الأنظمة الخطية»؟

حل Ax=b باستخدام np.linalg.solve، وقارن ذلك بالنهج الساذج القائم على ضرب المعكوس من حيث الاستقرار العددي تتمرن على Pandas & NumPy Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Pandas & NumPy Academy؟

لا تُشترط خبرة سابقة. Pandas & NumPy Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «حل الأنظمة الخطية»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Pandas & NumPy Academy هذا؟

نعم. كل درس في Pandas & NumPy Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. ضرب المصفوفات باستخدام np.matmul و@
  2. المحددات والمعكوسات والمنقولات
  3. حل الأنظمة الخطية
  4. نظرة عامة على القيم الذاتية وSVD
← العودة إلى Pandas & NumPy Academy