Faza 01 · lecția 01

Intuiție pentru algebra liniară

Scopul lecției: Orice model IA nu este decât un ansamblu de calcule cu matrice, purtând o pălărie sofisticată.

Versiunea curentă AlexBred.com: primele 100 de lecții ale programului în limba română.

Curs
AI Engineering from Scratch
Fază
Fundamente matematice
Lectură
16 min.
Verificat
Cuprinsul lecției
  1. Obiective de învățare
  2. Problema
  3. Conceptul
  4. Vectorii sunt puncte (și direcții)
  5. Matricele sunt transformări
  6. Produsul scalar măsoară similaritatea
  7. Independența liniară
  8. Baza și rangul
  9. Proiecția
  10. Procesul Gram-Schmidt
  11. Construirea soluției
  12. Pasul 1: Vectori de la zero (Python)
  13. Pasul 2: Matrice de la zero (Python)
  14. Pasul 3: De ce este important pentru IA
  15. Pasul 4: Versiunea Julia
  16. Pasul 5: Independența liniară și proiecția de la zero (Python)
  17. Utilizarea soluției
  18. Rangul, proiecția și descompunerea QR cu NumPy
  19. PyTorch — tensorii sunt vectori cu diferențiere automată
  20. Livrarea rezultatului
  21. Legături
  22. Exerciții
  23. Termeni-cheie

Orice model IA nu este decât un ansamblu de calcule cu matrice, purtând o pălărie sofisticată.

Tip: Învățare Limbaje: Python, Julia Cerințe preliminare: Faza 0 Durată: ~60 de minute

Obiective de învățare

  • Implementarea de la zero în Python a operațiilor cu vectori și matrice: adunarea, produsul scalar și înmulțirea matricială
  • Explicarea geometrică a produsului scalar, a proiecției și a procesului Gram-Schmidt
  • Determinarea independenței liniare, a rangului și a bazei unui set de vectori prin reducerea matricei pe linii
  • Corelarea conceptelor de algebră liniară cu aplicațiile lor în IA: reprezentări vectoriale (embeddings), scoruri de atenție și LoRA

Problema

Deschideți orice lucrare despre învățarea automată (ML). Încă din prima pagină veți întâlni vectori, matrice, produse scalare și transformări. Fără intuiție pentru algebra liniară, acestea sunt doar simboluri. Cu această intuiție, puteți vedea ce face de fapt o rețea neuronală: deplasează puncte în spațiu.

Nu trebuie să fiți matematicieni. Trebuie să înțelegeți semnificația geometrică a acestor operații, apoi să le transpuneți chiar dumneavoastră în cod.

Conceptul

Vectorii sunt puncte (și direcții)

Un vector este doar o listă de numere. Însă aceste numere au o semnificație: sunt coordonate în spațiu.

Vectorul 2D [3, 2]:

x y Punct
3 2 Vectorul este orientat de la origine (0,0) către punctul (3, 2) din plan

Vectorul are norma sqrt(3^2 + 2^2) = sqrt(13) și este orientat în sus și spre dreapta.

În IA, vectorii reprezintă orice:

  • Un cuvânt → un vector cu 768 de numere („semnificația” sa în spațiul reprezentărilor vectoriale)
  • O imagine → un vector cu milioane de valori ale pixelilor
  • Un utilizator → un vector de preferințe

Matricele sunt transformări

O matrice transformă un vector în altul. Ea îl poate roti, îi poate modifica scara, îl poate întinde sau proiecta.

Диаграмма к уроку «Intuiție pentru algebra liniară»

În IA, matricele SUNT modelul:

  • Ponderile rețelelor neuronale → matrice care transformă intrarea în ieșire
  • Scorurile de atenție → matrice care stabilesc elementele asupra cărora se concentrează modelul
  • Reprezentările vectoriale (embeddings) → matrice care asociază cuvintele cu vectori

Produsul scalar măsoară similaritatea

Produsul scalar dintre doi vectori arată cât de asemănători sunt aceștia.

a · b = a₁×b₁ + a₂×b₂ + ... + aₙ×bₙ

Aceeași direcție:   a · b > 0  (similari)
Perpendiculari:     a · b = 0  (fără legătură)
Direcții opuse:     a · b < 0  (diferiți)

Exact astfel funcționează motoarele de căutare, sistemele de recomandare și RAG: găsesc vectorii cu produse scalare mari.

Independența liniară

Vectorii sunt liniar independenți dacă niciun vector din set nu poate fi scris ca o combinație a celorlalți. Dacă v1, v2 și v3 sunt independenți, ei generează un spațiu tridimensional. Dacă unul este o combinație a celorlalți, vectorii generează doar un plan.

De ce contează acest lucru în IA: coloanele matricei de caracteristici trebuie să fie liniar independente. Dacă două caracteristici sunt perfect corelate, adică liniar dependente, modelul nu poate distinge efectele lor. În regresie, aceasta produce multicoliniaritate: matricea ponderilor devine instabilă, iar mici modificări ale intrării provoacă variații foarte mari ale ieșirii.

Exemplu concret:

v1 = [1, 0, 0]
v2 = [0, 1, 0]
v3 = [2, 1, 0]   # v3 = 2*v1 + v2

v1 și v2 sunt independenți: niciunul nu este un multiplu scalar sau o combinație a celuilalt. Dar v3 = 2*v1 + v2, deci {v1, v2, v3} este un set dependent. Toți cei trei vectori se află în planul xy. Indiferent cum îi combinați, nu puteți ajunge la [0, 0, 1]. Aveți trei vectori, dar numai două dimensiuni de libertate.

Într-un set de date, dacă feature_3 = 2*feature_1 + feature_2, adăugarea feature_3 nu îi oferă modelului nicio informație nouă. Mai rău, aceasta face ca ecuațiile normale să fie singulare: nu există o soluție unică pentru ponderi.

Baza și rangul

O bază este un set minimal de vectori liniar independenți care generează întregul spațiu. Numărul vectorilor bazei este dimensiunea spațiului.

Baza canonică a spațiului tridimensional este {[1,0,0], [0,1,0], [0,0,1]}. Însă orice trei vectori independenți din spațiul tridimensional formează o bază validă. Alegerea bazei înseamnă alegerea unui sistem de coordonate.

Rangul unei matrice = numărul coloanelor liniar independente = numărul liniilor liniar independente. Dacă rangul < min(numărul de linii, numărul de coloane), matricea este deficientă în rang. Aceasta înseamnă că:

  • Sistemul are o infinitate de soluții sau nu are nicio soluție
  • În timpul transformării se pierd informații
  • Matricea nu poate fi inversată
Situație Rang Ce înseamnă pentru ML
Rang complet (rang = min(m, n)) Maximul posibil Există o soluție unică în sensul celor mai mici pătrate. Modelul este bine condiționat.
Rang deficient (rang < min(m, n)) Sub valoarea maximă Caracteristicile sunt redundante. Există o infinitate de soluții pentru ponderi. Este necesară regularizarea.
Rang 1 1 Fiecare coloană este un multiplu scalar al aceluiași vector. Toate datele se află pe o dreaptă.
Aproape deficientă în rang (valori singulare mici) Rang numeric redus Matricea este prost condiționată. Perturbații infime ale intrării provoacă variații mari ale ieșirii. Utilizați trunchierea SVD sau regresia ridge.

Proiecția

Proiecția vectorului a pe vectorul b este componenta lui a pe direcția lui b:

proj_b(a) = (a dot b / b dot b) * b

Reziduul (a - proj_b(a)) este perpendicular pe b. Această descompunere ortogonală stă la baza ajustării prin metoda celor mai mici pătrate.

Proiecția este prezentă pretutindeni în ML:

  • Regresia liniară minimizează distanța dintre observații și spațiul coloanelor: soluția ESTE o proiecție
  • PCA proiectează datele pe direcțiile de varianță maximă
  • Mecanismul de atenție din arhitecturile Transformer calculează proiecțiile vectorilor de interogare (queries) pe vectorii-cheie (keys)

Диаграмма к уроку «Intuiție pentru algebra liniară»

Exemplu: a = [3, 4], b = [1, 0]

proj_b(a) = (31 + 40) / (11 + 00) * [1, 0] = 3 * [1, 0] = [3, 0]

Proiecția elimină componenta y. Aceasta este reducerea dimensionalității în forma sa cea mai simplă: eliminați direcțiile care nu vă interesează.

Procesul Gram-Schmidt

Procesul Gram-Schmidt transformă orice set de vectori independenți într-o bază ortonormată. Ortonormată înseamnă că fiecare vector are norma 1, iar oricare doi vectori sunt perpendiculari.

Algoritmul:

  1. Luați primul vector și normalizați-l
  2. Luați al doilea vector, scădeți proiecția sa pe primul și normalizați rezultatul
  3. Luați al treilea vector, scădeți proiecțiile sale pe toți vectorii anteriori și normalizați rezultatul
  4. Repetați pentru vectorii rămași
Intrare: v1, v2, v3, ... (liniar independenți)

u1 = v1 / |v1|

w2 = v2 - (v2 dot u1) * u1
u2 = w2 / |w2|

w3 = v3 - (v3 dot u1) * u1 - (v3 dot u2) * u2
u3 = w3 / |w3|

Ieșire: u1, u2, u3, ... (bază ortonormată)

Astfel funcționează intern descompunerea QR. Q este baza ortonormată, iar R conține coeficienții proiecțiilor. Descompunerea QR este utilizată pentru:

  • Rezolvarea sistemelor liniare, cu o stabilitate mai bună decât eliminarea gaussiană
  • Calcularea valorilor proprii prin algoritmul QR
  • Regresia prin metoda celor mai mici pătrate, ca metodă numerică standard
eigen-directions

Construirea soluției

Pasul 1: Vectori de la zero (Python)

class Vector:
    def __init__(self, components):
        self.components = list(components)
        self.dim = len(self.components)

    def __add__(self, other):
        return Vector([a + b for a, b in zip(self.components, other.components)])

    def __sub__(self, other):
        return Vector([a - b for a, b in zip(self.components, other.components)])

    def dot(self, other):
        return sum(a * b for a, b in zip(self.components, other.components))

    def magnitude(self):
        return sum(x**2 for x in self.components) ** 0.5

    def normalize(self):
        mag = self.magnitude()
        return Vector([x / mag for x in self.components])

    def cosine_similarity(self, other):
        return self.dot(other) / (self.magnitude() * other.magnitude())

    def __repr__(self):
        return f"Vector({self.components})"


a = Vector([1, 2, 3])
b = Vector([4, 5, 6])

print(f"a + b = {a + b}")
print(f"a · b = {a.dot(b)}")
print(f"|a| = {a.magnitude():.4f}")
print(f"cosine similarity = {a.cosine_similarity(b):.4f}")

Pasul 2: Matrice de la zero (Python)

class Matrix:
    def __init__(self, rows):
        self.rows = [list(row) for row in rows]
        self.shape = (len(self.rows), len(self.rows[0]))

    def __matmul__(self, other):
        if isinstance(other, Vector):
            return Vector([
                sum(self.rows[i][j] * other.components[j] for j in range(self.shape[1]))
                for i in range(self.shape[0])
            ])
        rows = []
        for i in range(self.shape[0]):
            row = []
            for j in range(other.shape[1]):
                row.append(sum(
                    self.rows[i][k] * other.rows[k][j]
                    for k in range(self.shape[1])
                ))
            rows.append(row)
        return Matrix(rows)

    def transpose(self):
        return Matrix([
            [self.rows[j][i] for j in range(self.shape[0])]
            for i in range(self.shape[1])
        ])

    def __repr__(self):
        return f"Matrix({self.rows})"


rotation_90 = Matrix([[0, -1], [1, 0]])
point = Vector([3, 1])

rotated = rotation_90 @ point
print(f"Original: {point}")
print(f"Rotated 90°: {rotated}")

Pasul 3: De ce este important pentru IA

import random

random.seed(42)
weights = Matrix([[random.gauss(0, 0.1) for _ in range(3)] for _ in range(2)])
input_vector = Vector([1.0, 0.5, -0.3])

output = weights @ input_vector
print(f"Input (3D): {input_vector}")
print(f"Output (2D): {output}")
print("This is what a neural network layer does -- matrix multiplication.")

Pasul 4: Versiunea Julia

a = [1.0, 2.0, 3.0]
b = [4.0, 5.0, 6.0]

println("a + b = ", a + b)
println("a · b = ", a  b)       # Julia supports unicode operators
println("|a| = ", (a  a))
println("cosine = ", (a  b) / ((a  a) *(b  b)))

# Matrix-vector multiplication
W = [0.1 -0.2 0.3; 0.4 0.5 -0.1]
x = [1.0, 0.5, -0.3]
println("Wx = ", W * x)
println("This is a neural network layer.")

Pasul 5: Independența liniară și proiecția de la zero (Python)

def is_linearly_independent(vectors):
    n = len(vectors)
    dim = len(vectors[0].components)
    mat = Matrix([v.components[:] for v in vectors])
    rows = [row[:] for row in mat.rows]
    rank = 0
    for col in range(dim):
        pivot = None
        for row in range(rank, len(rows)):
            if abs(rows[row][col]) > 1e-10:
                pivot = row
                break
        if pivot is None:
            continue
        rows[rank], rows[pivot] = rows[pivot], rows[rank]
        scale = rows[rank][col]
        rows[rank] = [x / scale for x in rows[rank]]
        for row in range(len(rows)):
            if row != rank and abs(rows[row][col]) > 1e-10:
                factor = rows[row][col]
                rows[row] = [rows[row][j] - factor * rows[rank][j] for j in range(dim)]
        rank += 1
    return rank == n


def project(a, b):
    scalar = a.dot(b) / b.dot(b)
    return Vector([scalar * x for x in b.components])


def gram_schmidt(vectors):
    orthonormal = []
    for v in vectors:
        w = v
        for u in orthonormal:
            proj = project(w, u)
            w = w - proj
        if w.magnitude() < 1e-10:
            continue
        orthonormal.append(w.normalize())
    return orthonormal


v1 = Vector([1, 0, 0])
v2 = Vector([1, 1, 0])
v3 = Vector([1, 1, 1])
basis = gram_schmidt([v1, v2, v3])
for i, u in enumerate(basis):
    print(f"u{i+1} = {u}")
    print(f"  |u{i+1}| = {u.magnitude():.6f}")

print(f"u1 · u2 = {basis[0].dot(basis[1]):.6f}")
print(f"u1 · u3 = {basis[0].dot(basis[2]):.6f}")
print(f"u2 · u3 = {basis[1].dot(basis[2]):.6f}")

Utilizarea soluției

Acum să efectuăm aceleași operații cu NumPy, biblioteca pe care o veți utiliza în practică:

import numpy as np

a = np.array([1, 2, 3], dtype=float)
b = np.array([4, 5, 6], dtype=float)

print(f"a + b = {a + b}")
print(f"a · b = {np.dot(a, b)}")
print(f"|a| = {np.linalg.norm(a):.4f}")
print(f"cosine = {np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)):.4f}")

W = np.random.randn(2, 3) * 0.1
x = np.array([1.0, 0.5, -0.3])
print(f"Wx = {W @ x}")

Rangul, proiecția și descompunerea QR cu NumPy

import numpy as np

A = np.array([[1, 2], [2, 4]])
print(f"Rank: {np.linalg.matrix_rank(A)}")

a = np.array([3, 4])
b = np.array([1, 0])
proj = (np.dot(a, b) / np.dot(b, b)) * b
print(f"Projection of {a} onto {b}: {proj}")

Q, R = np.linalg.qr(np.random.randn(3, 3))
print(f"Q is orthogonal: {np.allclose(Q @ Q.T, np.eye(3))}")
print(f"R is upper triangular: {np.allclose(R, np.triu(R))}")

PyTorch — tensorii sunt vectori cu diferențiere automată

import torch

x = torch.randn(3, requires_grad=True)
y = torch.tensor([1.0, 0.0, 0.0])

similarity = torch.dot(x, y)
similarity.backward()

print(f"x = {x.data}")
print(f"y = {y.data}")
print(f"dot product = {similarity.item():.4f}")
print(f"d(dot)/dx = {x.grad}")

Gradientul produsului scalar în raport cu x este chiar y. PyTorch l-a calculat automat. Fiecare operație dintr-o rețea neuronală este construită din operații de acest tip: înmulțiri matriciale, produse scalare și proiecții, iar diferențierea automată urmărește gradienții prin toate aceste operații.

Tocmai ați construit de la zero ceea ce NumPy realizează într-o singură linie. Acum știți ce se întâmplă în culise.

Livrarea rezultatului

Această lecție produce:

  • outputs/prompt-linear-algebra-tutor.md — un prompt prin care asistenții IA predau algebra liniară folosind intuiția geometrică

Legături

Toate noțiunile din această lecție se regăsesc în componente concrete ale IA moderne:

Concept Unde apare
Produs scalar Scorurile de atenție din arhitecturile Transformer, similaritatea cosinus în RAG
Înmulțire matricială Fiecare strat al unei rețele neuronale, fiecare transformare liniară
Independență liniară Selectarea caracteristicilor, evitarea multicoliniarității
Rang Stabilirea posibilității de rezolvare a unui sistem, LoRA (adaptare de rang redus)
Proiecție Regresie liniară (proiecția pe spațiul coloanelor), PCA
Gram-Schmidt / QR Metode numerice de rezolvare, calcularea valorilor proprii
Bază ortonormată Calcule numerice stabile, transformări de albire (whitening)

LoRA merită o mențiune specială. Această metodă realizează ajustarea fină (fine-tuning) a modelelor lingvistice mari prin descompunerea actualizărilor ponderilor în matrice de rang redus. În loc să actualizeze o matrice de ponderi 4096x4096 (16M parametri), LoRA actualizează două matrice cu dimensiunile 4096x16 și 16x4096 (131K parametri). Constrângerea de rang 16 înseamnă că LoRA presupune că actualizarea ponderilor se află într-un subspațiu 16-dimensional al spațiului complet 4096-dimensional. Acesta este un exemplu în care algebra liniară are un rol concret.

Exerciții

  1. Implementați Vector.angle_between(other), care returnează în grade unghiul dintre doi vectori
  2. Creați o matrice de scalare 2D care dublează coordonata x și triplează coordonata y, apoi aplicați-o vectorului [1, 1]
  3. Pentru cinci vectori aleatori care simulează reprezentări de cuvinte, fiecare cu dimensiunea 50, găsiți-i pe cei mai asemănători folosind similaritatea cosinus
  4. Verificați dacă rezultatul procesului Gram-Schmidt este cu adevărat ortonormat: confirmați că produsul scalar al oricăror doi vectori este 0 și că fiecare vector are norma 1
  5. Creați o matrice 3x3 cu rangul 2. Verificați-l folosind metoda rank(). Apoi explicați ce obiect geometric generează coloanele.
  6. Proiectați vectorul [1, 2, 3] pe [1, 1, 1]. Ce reprezintă geometric rezultatul?

Termeni-cheie

Termen Formulare uzuală Ce înseamnă de fapt
Vector „O săgeată” O listă de numere care reprezintă un punct sau o direcție într-un spațiu n-dimensional
Matrice „Un tabel de numere” O transformare care asociază vectorii dintr-un spațiu cu vectori din alt spațiu
Produs scalar „Înmulțire și însumare” O măsură a gradului de aliniere a doi vectori, aflată la baza căutării după similaritate
Reprezentare vectorială (embedding) „Un fel de magie IA” Un vector care reprezintă semnificația unui element, precum un cuvânt, o imagine sau un utilizator
Independență liniară „Nu se suprapun” Niciun vector din set nu poate fi scris ca o combinație a celorlalți
Rang „Câte dimensiuni” Numărul coloanelor sau al liniilor liniar independente dintr-o matrice
Proiecție „Umbra” Componenta unui vector pe direcția altui vector
Bază „Axele de coordonate” Un set minimal de vectori independenți care generează spațiul
Ortonormat „Vectori unitari perpendiculari” Vectori reciproc perpendiculari, fiecare având norma 1

Sursă: Linear Algebra Intuition — originalul Navigare: Faza 1 — Fundamente matematice · Catalog complet · în continuare: 01.02 — Vectori, matrice și operații.