Phase 01: Math Foundations

Vecteurs, matrices et opérations

Chaque réseau neural est juste une multiplication de matrice avec des étapes supplémentaires.

Type: Build

Languages: Python, Julia

Prerequisites: Phase 1, Lesson 01 (Linear Algebra Intuition)

Time: ~60 minutes

Objectifs d'apprentissage

  • Construire une classe de Matrix avec des opérations par élément, la multiplication de la matrice, la transposition, le déterminant et l'inverse
  • Distinguer la multiplication par élément de la multiplication par matrice et expliquer quand chaque élément s'applique
  • Implementer une seule couche de réseau neural dense (relu(W @ x + b)) utilisant uniquement la classe Matrix à partir de zéro
  • Expliquer les règles de radiodiffusion et comment l'addition de biais fonctionne dans les cadres de réseaux neuronaux

Le problème

Vous voulez construire un réseau neuronal, vous lisez le code et voyez ceci:

output = activation(weights @ input + bias)

Ça ...@est la multiplication de matrice.weightssont une matrice.inputSi vous ne savez pas ce que ces opérations font, cette ligne est magique. si vous le savez, c'est l'ensemble de la passée vers l'avant d'une couche en trois opérations.

Chaque image que votre modèle traite est une matrice de valeurs de pixels. Chaque mot intégré est un vecteur. Chaque couche de chaque réseau neural est une transformation de matrice. Vous ne pouvez pas construire des systèmes d'IA sans être fluide dans les opérations de matrice de la même manière que vous ne pouvez pas écrire de code sans comprendre les variables.

Cette leçon construit cette fluidité à partir de zéro.

Le concept

Vecteurs: listes de nombres ordonnées

Un vecteur est une liste de nombres avec une direction et une magnitude.

v = [3, 4]        -- a 2D vector
w = [1, 0, -2]    -- a 3D vector

Un vecteur 2D [3, 4]Il est le point de départ de la ligne de référence de la ligne de référence.

Matrices: grilles de nombres

Une matrice est une grille 2D. Les lignes et les colonnes.

A = | 1  2  3 |     -- 2x3 matrix (2 rows, 3 columns)
    | 4  5  6 |

Dans les réseaux neuronaux, les matrices de poids transforment les vecteurs d'entrée en vecteurs de sortie.

Pourquoi les formes comptent

La multiplication de matrice a une règle stricte:(m x n) @ (n x p) = (m x p)Les dimensions internes doivent être correspondantes.

(128 x 784) @ (784 x 1) = (128 x 1)
  weights       input       output

Inner dimensions: 784 = 784  -- valid

Si vous obtenez une erreur de déséquilibre de forme dans PyTorch, c'est pourquoi.

Carte des opérations

OperationWhat it doesNeural network use
AdditionElement-wise combineAdding bias to output
Scalar multiplyScale every elementLearning rate * gradients
Matrix multiplyTransform vectorsLayer forward pass
TransposeFlip rows and columnsBackpropagation
DeterminantSingle number summaryChecking invertibility
InverseUndo a transformationSolving linear systems
IdentityDo-nothing matrixInitialization, residual connections

Multiplication par élément par matrice

Cette distinction fait trébucher constamment les débutants.

Par élément: multipliez les positions correspondantes.

| 1  2 |   | 5  6 |   | 5  12 |
| 3  4 | * | 7  8 | = | 21 32 |

Multiplication de matrice: produits de points de lignes et de colonnes.

| 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 |

Des opérations différentes, des résultats différents, des règles différentes.

La radiodiffusion

Quand on ajoute un vecteur de biais à une matrice de sorties, les formes ne correspondent pas.

| 1  2  3 |   +   [10, 20, 30]
| 4  5  6 |

Broadcasting stretches the vector across rows:

| 1  2  3 |   | 10  20  30 |   | 11  22  33 |
| 4  5  6 | + | 10  20  30 | = | 14  25  36 |

Chaque cadre moderne le fait automatiquement, ce qui empêche la confusion lorsque les formes semblent erronées mais que le code fonctionne.

Faites-le

Étape 1: classe vectorielle

pythonclass 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

Étape 2: classe de matrice avec les opérations de base

pythonclass 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)
        ])

Étape 3: voir fonctionner

pythonA = 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)

Étape 4: Connectez-vous aux réseaux neuronaux

pythonimport 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}")

C' est une seule couche dense:output = relu(W @ x + b)Chaque couche dense de chaque réseau neural fait exactement ça.

Utilisez-le

NumPy fait tout ce qui est en haut en moins de lignes et des ordres de magnitude plus rapidement.

pythonimport 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}")

Le @opérateur dans les appels Python __matmul__NumPy le met en œuvre avec des routines BLAS optimisées écrites en C et Fortran.

La diffusion en numPy:

pythonmatrix = np.array([[1, 2, 3], [4, 5, 6]])
bias = np.array([10, 20, 30])
print(matrix + bias)

NumPy diffuse automatiquement le biais 1D sur les deux rangées. C'est ainsi que l'addition de biais fonctionne dans chaque cadre de réseau neuronal.

La faire partir

Cette leçon fournit un prompt pour enseigner les opérations de matrice par intuition géométrique.outputs/prompt-matrix-operations.md- Je suis désolé .

La classe Matrix construite ici est la base du framework de réseau mini-néural que nous construisons dans la phase 3, leçon 10.

Exercices

  1. Verify the inverse.MultipliezA @ A.inverse_2x2()et confirmez que vous obtenez la matrice d'identité. essayez avec trois matrices 2x2 différentes.
  1. Implement 3x3 inverse.Élargir la classe Matrix pour calculer les inverses pour les matrices 3x3 en utilisant la méthode adjugée.np.linalg.inv- Je suis désolé .
  1. Build a two-layer network.En utilisant uniquement votre classe Matrix (pas de NumPy), créez un réseau neural à deux couches: entrée (3) -> cachée (4) -> sortie (2). Initialize des poids aléatoires, exécutez un passage vers l'avant et vérifiez que toutes les formes sont correctes.

Les termes clés

TermWhat people sayWhat it actually means
Vector"An arrow"An ordered list of numbers. In AI: a point in high-dimensional space.
Matrix"A table of numbers"A linear transformation. It maps vectors from one space to another.
Matrix multiply"Just multiply the numbers"Dot products between every row of the first matrix and every column of the second. Order matters.
Transpose"Flip it"Swap rows and columns. Turns an m x n matrix into n x m. Critical in backpropagation.
Determinant"Some number from the matrix"Measures how much the matrix scales area (2D) or volume (3D). Zero means the transformation crushes a dimension.
Inverse"Undo the matrix"The matrix that reverses the transformation. Only exists when the determinant is not zero.
Identity matrix"The boring matrix"The matrix equivalent of multiplying by 1. Used in residual connections (ResNets).
Broadcasting"Magic shape fixing"Stretching a smaller array to match a larger one by repeating along missing dimensions.
Element-wise"Regular multiplication"Multiply matching positions. Both arrays must have the same shape (or be broadcastable).

Pour en savoir plus

This free lesson is part of the AI Engineering from Scratch curriculum. Read the full explanation, run the lesson code, and verify the result in the interactive reader or from the repository source.

Browse the complete course catalog or open this lesson on GitHub.