Faza 01 · lecția 02
Vectori, matrice și operații
Scopul lecției: Orice rețea neuronală este doar o înmulțire matricială, însoțită de câțiva pași suplimentari.
Versiunea curentă AlexBred.com: primele 100 de lecții ale programului în limba română.
Cuprinsul lecției
- Obiective de învățare
- Problema
- Conceptul
- Vectori: liste ordonate de numere
- Matrice: tablouri de numere
- De ce contează dimensiunile
- Harta operațiilor
- Înmulțirea element cu element și înmulțirea matricelor
- Extinderea automată (broadcasting)
- Implementare
- Pasul 1: clasa Vector
- Pasul 2: clasa Matrix cu operațiile de bază
- Pasul 3: testați implementarea
- Pasul 4: legătura cu rețelele neuronale
- Utilizarea implementării
- Livrarea rezultatului
- Exerciții
- Termeni-cheie
- Lecturi suplimentare
Orice rețea neuronală este doar o înmulțire matricială, însoțită de câțiva pași suplimentari.
Tip: Construire Limbaje: Python, Julia Cerințe preliminare: Faza 1, lecția 01 (Intuiție pentru algebra liniară) Durată: ~60 de minute
Obiective de învățare
- Construirea unei clase Matrix cu operații element cu element, înmulțirea matricelor, transpunere, determinant și inversă
- Deosebirea înmulțirii element cu element de înmulțirea matricelor și explicarea situațiilor în care se aplică fiecare
- Implementarea unui singur strat dens al unei rețele neuronale (
relu(W @ x + b)) folosind numai clasa Matrix construită de la zero - Explicarea regulilor de broadcasting și a modului în care funcționează adăugarea biasului în frameworkurile pentru rețele neuronale
Problema
Doriți să construiți o rețea neuronală. Citiți codul și vedeți următoarea expresie:
output = activation(weights @ input + bias)
Operatorul @ efectuează înmulțirea matricelor. weights este o matrice, iar input este un vector. Dacă nu știți ce fac aceste operații, linia pare magică. Dacă le înțelegeți, ea reprezintă întreaga propagare înainte printr-un strat, exprimată în trei operații.
Fiecare imagine procesată de model este o matrice de valori ale pixelilor. Fiecare reprezentare vectorială (embedding) a unui cuvânt este un vector. Fiecare strat al oricărei rețele neuronale este o transformare matricială. Nu puteți construi sisteme de IA fără să stăpâniți operațiile cu matrice, la fel cum nu puteți scrie cod fără să înțelegeți variabilele.
Această lecție vă ajută să stăpâniți aceste operații de la zero.
Conceptul
Vectori: liste ordonate de numere
Un vector este o listă de numere caracterizată prin direcție și modul. În IA, vectorii reprezintă puncte de date, caracteristici sau parametri.
v = [3, 4] -- a 2D vector
w = [1, 0, -2] -- a 3D vector
Vectorul bidimensional [3, 4] indică punctul de coordonate (3, 4) într-un plan. Lungimea sa (modulul) este 5 (triunghiul cu laturile 3, 4 și 5).
Matrice: tablouri de numere
O matrice este un tablou bidimensional, alcătuit din linii și coloane. O matrice m x n are m linii și n coloane.
A = | 1 2 3 | -- 2x3 matrix (2 rows, 3 columns)
| 4 5 6 |
În rețelele neuronale, matricele de ponderi transformă vectorii de intrare în vectori de ieșire. Un strat cu 784 de intrări și 128 de ieșiri folosește o matrice de ponderi 128x784.
De ce contează dimensiunile
Înmulțirea matricelor respectă o regulă strictă: (m x n) @ (n x p) = (m x p). Dimensiunile interioare trebuie să coincidă.
(128 x 784) @ (784 x 1) = (128 x 1)
ponderi intrare ieșire
Dimensiuni interioare: 784 = 784 -- valid
Acesta este motivul pentru care PyTorch raportează o eroare de incompatibilitate a dimensiunilor.
Harta operațiilor
| Operație | Ce face | Utilizare în rețele neuronale |
|---|---|---|
| Adunare | Combină elementele aflate pe poziții corespunzătoare | Adăugarea biasului la ieșire |
| Înmulțire cu un scalar | Scalează fiecare element | Rata de învățare * gradienți |
| Înmulțirea matricelor | Transformă vectori | Propagarea înainte prin strat |
| Transpunere | Interschimbă liniile și coloanele | Retropropagare |
| Determinant | Rezumă matricea printr-un singur număr | Verificarea inversabilității |
| Inversă | Anulează o transformare | Rezolvarea sistemelor liniare |
| Matrice unitate | Nu modifică vectorul | Inițializare, conexiuni reziduale |
Înmulțirea element cu element și înmulțirea matricelor
Această diferență le creează permanent probleme începătorilor.
La înmulțirea element cu element se înmulțesc valorile aflate pe poziții corespunzătoare. Cele două matrice trebuie să aibă aceleași dimensiuni.
| 1 2 | | 5 6 | | 5 12 |
| 3 4 | * | 7 8 | = | 21 32 |
La înmulțirea matricelor se calculează produsele scalare dintre linii și coloane. Dimensiunile interioare trebuie să coincidă.
| 1 2 | | 5 6 | | 1*5+2*7 1*6+2*8 | | 19 22 |
| 3 4 | @ | 7 8 | = | 3*5+4*7 3*6+4*8 | = | 43 50 |
Sunt operații diferite, cu rezultate și reguli diferite.
Extinderea automată (broadcasting)
Când adăugați un vector de bias la o matrice de ieșiri, dimensiunile nu coincid. Broadcastingul extinde tabloul mai mic pentru a se potrivi cu cel mai mare.
| 1 2 3 | + [10, 20, 30]
| 4 5 6 |
Broadcasting-ul extinde vectorul pe linii:
| 1 2 3 | | 10 20 30 | | 11 22 33 |
| 4 5 6 | + | 10 20 30 | = | 14 25 36 |
Orice framework modern face automat acest lucru. Înțelegerea mecanismului previne confuzia atunci când dimensiunile par greșite, dar codul rulează.
vector-projection
Implementare
Pasul 1: clasa Vector
class Vector:
def __init__(self, data):
self.data = list(data)
self.size = len(self.data)
def __repr__(self):
return f"Vector({self.data})"
def __add__(self, other):
return Vector([a + b for a, b in zip(self.data, other.data)])
def __sub__(self, other):
return Vector([a - b for a, b in zip(self.data, other.data)])
def __mul__(self, scalar):
return Vector([x * scalar for x in self.data])
def dot(self, other):
return sum(a * b for a, b in zip(self.data, other.data))
def magnitude(self):
return sum(x ** 2 for x in self.data) ** 0.5
Pasul 2: clasa Matrix cu operațiile de bază
class Matrix:
def __init__(self, data):
self.data = [list(row) for row in data]
self.rows = len(self.data)
self.cols = len(self.data[0])
self.shape = (self.rows, self.cols)
def __repr__(self):
rows_str = "\n ".join(str(row) for row in self.data)
return f"Matrix({self.shape}):\n {rows_str}"
def __add__(self, other):
return Matrix([
[self.data[i][j] + other.data[i][j] for j in range(self.cols)]
for i in range(self.rows)
])
def __sub__(self, other):
return Matrix([
[self.data[i][j] - other.data[i][j] for j in range(self.cols)]
for i in range(self.rows)
])
def scalar_multiply(self, scalar):
return Matrix([
[self.data[i][j] * scalar for j in range(self.cols)]
for i in range(self.rows)
])
def element_wise_multiply(self, other):
return Matrix([
[self.data[i][j] * other.data[i][j] for j in range(self.cols)]
for i in range(self.rows)
])
def matmul(self, other):
return Matrix([
[
sum(self.data[i][k] * other.data[k][j] for k in range(self.cols))
for j in range(other.cols)
]
for i in range(self.rows)
])
def transpose(self):
return Matrix([
[self.data[j][i] for j in range(self.rows)]
for i in range(self.cols)
])
def determinant(self):
if self.shape == (1, 1):
return self.data[0][0]
if self.shape == (2, 2):
return self.data[0][0] * self.data[1][1] - self.data[0][1] * self.data[1][0]
det = 0
for j in range(self.cols):
minor = Matrix([
[self.data[i][k] for k in range(self.cols) if k != j]
for i in range(1, self.rows)
])
det += ((-1) ** j) * self.data[0][j] * minor.determinant()
return det
def inverse_2x2(self):
det = self.determinant()
if det == 0:
raise ValueError("Matrix is singular, no inverse exists")
return Matrix([
[self.data[1][1] / det, -self.data[0][1] / det],
[-self.data[1][0] / det, self.data[0][0] / det]
])
@staticmethod
def identity(n):
return Matrix([
[1 if i == j else 0 for j in range(n)]
for i in range(n)
])
Pasul 3: testați implementarea
A = Matrix([[1, 2], [3, 4]])
B = Matrix([[5, 6], [7, 8]])
print("A + B =", (A + B).data)
print("A @ B =", A.matmul(B).data)
print("A^T =", A.transpose().data)
print("det(A) =", A.determinant())
print("A^-1 =", A.inverse_2x2().data)
I = Matrix.identity(2)
print("A @ A^-1 =", A.matmul(A.inverse_2x2()).data)
Pasul 4: legătura cu rețelele neuronale
import random
inputs = Matrix([[0.5], [0.8], [0.2]])
weights = Matrix([
[random.uniform(-1, 1) for _ in range(3)]
for _ in range(2)
])
bias = Matrix([[0.1], [0.1]])
def relu_matrix(m):
return Matrix([[max(0, val) for val in row] for row in m.data])
pre_activation = weights.matmul(inputs) + bias
output = relu_matrix(pre_activation)
print(f"Input shape: {inputs.shape}")
print(f"Weight shape: {weights.shape}")
print(f"Output shape: {output.shape}")
print(f"Output: {output.data}")
Acesta este un singur strat dens: output = relu(W @ x + b). Fiecare strat dens din orice rețea neuronală efectuează exact aceste operații.
Utilizarea implementării
NumPy efectuează toate operațiile de mai sus în mai puține linii și de câteva ordine de mărime mai rapid.
import numpy as np
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
print("A + B =\n", A + B)
print("A * B (element-wise) =\n", A * B)
print("A @ B (matrix multiply) =\n", A @ B)
print("A^T =\n", A.T)
print("det(A) =", np.linalg.det(A))
print("A^-1 =\n", np.linalg.inv(A))
print("I =\n", np.eye(2))
inputs = np.random.randn(3, 1)
weights = np.random.randn(2, 3)
bias = np.array([[0.1], [0.1]])
output = np.maximum(0, weights @ inputs + bias)
print(f"\nNeural network layer: {weights.shape} @ {inputs.shape} = {output.shape}")
print(f"Output:\n{output}")
Operatorul @ din Python apelează __matmul__. NumPy îl implementează prin rutine BLAS optimizate, scrise în C și Fortran. Aceeași matematică, dar de 100 de ori mai rapidă.
Broadcasting în NumPy:
matrix = np.array([[1, 2, 3], [4, 5, 6]])
bias = np.array([10, 20, 30])
print(matrix + bias)
NumPy extinde automat vectorul unidimensional de bias pe ambele linii. Astfel funcționează adăugarea biasului în orice framework pentru rețele neuronale.
Livrarea rezultatului
În urma acestei lecții obțineți un prompt pentru predarea operațiilor cu matrice prin intuiție geometrică. Consultați outputs/prompt-matrix-operations.md.
Clasa Matrix construită aici constituie baza mini-frameworkului pentru rețele neuronale pe care îl vom realiza în faza 3, lecția 10.
Exerciții
-
Verificați inversa. Înmulțiți
A @ A.inverse_2x2()și confirmați că obțineți matricea unitate. Încercați operația cu trei matrice 2x2 diferite. Ce se întâmplă când determinantul este zero? -
Implementați inversa unei matrice 3x3. Extindeți clasa Matrix astfel încât să calculeze inversele matricelor 3x3 prin metoda matricei adjuncte. Verificați rezultatul prin comparație cu
np.linalg.invdin NumPy. -
Construiți o rețea cu două straturi. Folosind numai clasa Matrix creată de dvs. (fără NumPy), construiți o rețea neuronală cu două straturi: intrare (3) -> ascuns (4) -> ieșire (2). Inițializați ponderi aleatorii, efectuați o propagare înainte și verificați dacă toate dimensiunile sunt corecte.
Termeni-cheie
| Termen | Cum îi spune lumea | Ce înseamnă de fapt |
|---|---|---|
| Vector | „O săgeată” | O listă ordonată de numere. În IA: un punct într-un spațiu cu multe dimensiuni. |
| Matrice | „Un tabel de numere” | O transformare liniară. Transformă vectorii dintr-un spațiu în altul. |
| Înmulțirea matricelor | „Doar înmulțiți numerele” | Produse scalare între fiecare linie a primei matrice și fiecare coloană a celei de-a doua. Ordinea contează. |
| Transpunere | „O răsturnați” | Interschimbarea liniilor cu coloanele. Transformă o matrice m x n într-o matrice n x m. Este esențială în retropropagare. |
| Determinant | „Un număr oarecare obținut din matrice” | Măsoară factorul cu care matricea scalează aria (în 2D) sau volumul (în 3D). Valoarea zero înseamnă că transformarea reduce o dimensiune la zero. |
| Inversă | „Anulați matricea” | Matricea care inversează transformarea. Există numai atunci când determinantul este nenul. |
| Matrice unitate | „Matricea banală” | Echivalentul matricial al înmulțirii cu 1. Este folosită în conexiunile reziduale (ResNet). |
| Broadcasting | „Corectarea magică a dimensiunilor” | Extinderea unui tablou mai mic pentru a corespunde unuia mai mare, prin repetare de-a lungul dimensiunilor care lipsesc. |
| Element cu element | „Înmulțirea obișnuită” | Înmulțirea valorilor aflate pe poziții corespunzătoare. Ambele tablouri trebuie să aibă aceleași dimensiuni sau să permită broadcasting. |
Lecturi suplimentare
- 3Blue1Brown: Essence of Linear Algebra - prezentare vizuală intuitivă a tuturor operațiilor abordate aici
- Documentația NumPy despre broadcasting - regulile exacte urmate de NumPy
- Stanford CS229 Linear Algebra Review - referință concisă despre algebra liniară pentru învățarea automată
Sursă: Vectors, Matrices & Operations — original
Navigare: înapoi: 01.01 — Intuiție pentru algebra liniară · Faza 1 — Fundamente matematice · Catalog complet · în continuare: 01.03 — Transformări matriciale.