Фаза 01 · урок 01

Интуитивное понимание линейной алгебры

Цель урока: Откройте любую научную статью по машинному обучению. Уже на первой странице вы увидите векторы, матрицы, скалярные произведения и преобразования. Без интуитивного понимания линейной алгебры это просто символы. С ним вы сможете увидеть,…

Текущий релиз AlexBred.com: первые 100 уроков русскоязычной программы.

Курс
AI Engineering from Scratch
Фаза
Математические основы
Чтение
16 мин.
Проверено
Содержание урока
  1. Цели обучения
  2. Проблема
  3. Концепция
  4. Векторы — это точки (и направления)
  5. Матрицы — это преобразования
  6. Скалярное произведение измеряет сходство
  7. Линейная независимость
  8. Базис и ранг
  9. Проекция
  10. Процесс Грама — Шмидта
  11. Соберите это
  12. Шаг 1. Векторы с нуля (Python)
  13. Шаг 2. Матрицы с нуля (Python)
  14. Шаг 3. Почему это важно для AI
  15. Шаг 4. Версия на Julia
  16. Шаг 5. Линейная независимость и проекция с нуля (Python)
  17. Используйте это
  18. Ранг, проекция и QR-разложение с NumPy
  19. PyTorch — тензоры являются векторами с автоматическим дифференцированием
  20. Подготовьте результат
  21. Связи
  22. Упражнения
  23. Ключевые термины

Любая модель AI — это всего лишь матричная математика в нарядной шляпе.

Тип: Теория Языки: Python, Julia Предварительные требования: Фаза 0 Время: около 60 минут

Цели обучения

  • Реализовать с нуля на Python операции с векторами и матрицами: сложение, скалярное произведение и умножение матриц.
  • Геометрически объяснить, что делают скалярное произведение, проекция и процесс Грама — Шмидта.
  • Определять линейную независимость, ранг и базис набора векторов с помощью приведения матрицы к ступенчатому виду.
  • Связать понятия линейной алгебры с их применением в AI: эмбеддингами, оценками внимания и LoRA.

Проблема

Откройте любую научную статью по машинному обучению. Уже на первой странице вы увидите векторы, матрицы, скалярные произведения и преобразования. Без интуитивного понимания линейной алгебры это просто символы. С ним вы сможете увидеть, что нейронная сеть делает на самом деле: перемещает точки в пространстве.

Вам не нужно быть математиком. Нужно увидеть геометрический смысл этих операций, а затем самостоятельно запрограммировать их.

Концепция

Векторы — это точки (и направления)

Вектор — это просто список чисел. Но эти числа имеют смысл: они являются координатами в пространстве.

Двумерный вектор [3, 2]:

x y Точка
3 2 Вектор направлен от начала координат (0,0) к точке (3, 2) на плоскости

Длина вектора равна sqrt(3^2 + 2^2) = sqrt(13), а направлен он вверх и вправо.

В AI векторами представляют всё:

  • слово → вектор из 768 чисел (его «смысл» в пространстве эмбеддингов);
  • изображение → вектор из миллионов значений пикселей;
  • пользователь → вектор предпочтений.

Матрицы — это преобразования

Матрица преобразует один вектор в другой. Она может поворачивать, масштабировать, растягивать или проецировать.

Диаграмма к уроку «Интуитивное понимание линейной алгебры»

В AI матрицы И ЕСТЬ модель:

  • веса нейронной сети → матрицы, преобразующие входные данные в выходные;
  • оценки внимания → матрицы, определяющие, на чём сосредоточиться;
  • эмбеддинги → матрицы, сопоставляющие словам векторы.

Скалярное произведение измеряет сходство

Скалярное произведение двух векторов показывает, насколько они похожи.

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

Одно направление:       a · b > 0  (похожи)
Перпендикулярны:         a · b = 0  (не связаны)
Противоположные направления: a · b < 0  (не похожи)

Именно так работают поисковые системы, рекомендательные системы и RAG: они находят векторы с большими скалярными произведениями.

Линейная независимость

Векторы линейно независимы, если ни один вектор из набора нельзя выразить как комбинацию остальных. Если v1, v2 и v3 независимы, они порождают трёхмерное пространство. Если один из них является комбинацией остальных, вместе они порождают лишь плоскость.

Почему это важно для AI: столбцы вашей матрицы признаков должны быть линейно независимыми. Если два признака идеально коррелируют друг с другом, то есть линейно зависимы, модель не может различить их влияние. Это вызывает мультиколлинеарность в регрессии: матрица весов становится неустойчивой, а небольшие изменения входных данных приводят к резким скачкам выходных значений.

Конкретный пример:

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

Векторы v1 и v2 независимы: ни один из них не является скалярным кратным или комбинацией другого. Но v3 = 2*v1 + v2, поэтому {v1, v2, v3} — зависимый набор. Все три вектора лежат в плоскости xy. Как бы вы их ни комбинировали, получить [0, 0, 1] не удастся. У вас есть три вектора, но лишь две степени свободы.

В наборе данных, если feature_3 = 2*feature_1 + feature_2, добавление feature_3 не даёт модели никакой новой информации. Более того, из-за него нормальные уравнения становятся вырожденными: единственного решения для весов не существует.

Базис и ранг

Базис — это минимальный набор линейно независимых векторов, порождающих всё пространство. Число базисных векторов равно размерности пространства.

Стандартный базис трёхмерного пространства — {[1,0,0], [0,1,0], [0,0,1]}. Но любые три независимых вектора в трёхмерном пространстве образуют корректный базис. Выбор базиса — это выбор системы координат.

Ранг матрицы = число линейно независимых столбцов = число линейно независимых строк. Если rank < min(rows, cols), матрица имеет неполный ранг. Это означает следующее:

  • система имеет бесконечно много решений или не имеет ни одного;
  • при преобразовании теряется информация;
  • матрицу нельзя обратить.
Ситуация Ранг Что это означает для ML
Полный ранг (rank = min(m, n)) Максимально возможный Существует единственное решение задачи наименьших квадратов. Модель хорошо обусловлена.
Неполный ранг (rank < min(m, n)) Ниже максимального Признаки избыточны. Существует бесконечно много решений для весов. Нужна регуляризация.
Ранг 1 1 Каждый столбец — масштабированная копия одного вектора. Все данные лежат на прямой.
Ранг почти неполный (малые сингулярные значения) Численно низкий Матрица плохо обусловлена. Малейший шум во входных данных вызывает большие изменения на выходе. Используйте усечение SVD или гребневую регрессию.

[!warning] Уточнение переводчика Полный ранг rank = min(m, n) сам по себе не гарантирует ни единственности решения задачи наименьших квадратов, ни хорошей обусловленности. Для единственного решения по весам обычно нужен полный столбцовый ранг rank = n при m >= n; широкая матрица с m < n даже при полном строковом ранге допускает бесконечно много решений. Обусловленность определяется, в частности, отношением сингулярных значений, а не только рангом.

Проекция

Проецирование вектора a на вектор b даёт составляющую a в направлении b:

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

Остаток (a - proj_b(a)) перпендикулярен b. Это ортогональное разложение лежит в основе аппроксимации методом наименьших квадратов.

Проекции встречаются в ML повсюду:

  • линейная регрессия минимизирует расстояние от наблюдений до пространства столбцов — решение И ЕСТЬ проекция;
  • PCA проецирует данные на направления максимальной дисперсии;
  • механизм внимания в трансформерах вычисляет проекции запросов на ключи.

[!warning] Уточнение переводчика Стандартное scaled dot-product attention не вычисляет ортогональную проекцию по формуле выше. Оно получает оценки сходства из масштабированных скалярных произведений запросов и ключей, применяет softmax и формирует взвешенную сумму векторов значений.

Диаграмма к уроку «Интуитивное понимание линейной алгебры»

Пример: a = [3, 4], b = [1, 0]

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

Проекция отбрасывает y-составляющую. Это уменьшение размерности в простейшем виде: отбросьте направления, которые вас не интересуют.

Процесс Грама — Шмидта

Он преобразует любой набор независимых векторов в ортонормированный базис. «Ортонормированный» означает, что каждый вектор имеет длину 1, а каждая пара векторов перпендикулярна.

Алгоритм:

  1. Возьмите первый вектор и нормализуйте его.
  2. Возьмите второй вектор, вычтите его проекцию на первый и нормализуйте результат.
  3. Возьмите третий вектор, вычтите его проекции на все предыдущие векторы и нормализуйте результат.
  4. Повторите для оставшихся векторов.
Вход:  v1, v2, v3, ... (линейно независимые)

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|

Выход: u1, u2, u3, ... (ортонормированный базис)

Именно так внутри устроено QR-разложение. Q представляет ортонормированный базис, а R содержит коэффициенты проекций. QR-разложение применяется для:

  • решения систем линейных уравнений более устойчивым способом, чем метод Гаусса;
  • вычисления собственных значений с помощью QR-алгоритма;
  • регрессии методом наименьших квадратов как стандартный численный метод.
eigen-directions

Соберите это

Шаг 1. Векторы с нуля (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}")

Шаг 2. Матрицы с нуля (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}")

Шаг 3. Почему это важно для AI

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.")

Шаг 4. Версия на 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.")

Шаг 5. Линейная независимость и проекция с нуля (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}")

Используйте это

Теперь сделаем то же самое с NumPy — именно так вы будете работать на практике:

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

Ранг, проекция и QR-разложение с 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 — тензоры являются векторами с автоматическим дифференцированием

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

Градиент скалярного произведения по x — это просто y. PyTorch вычислил его автоматически. Каждая операция в нейронной сети строится из подобных операций — умножений матриц, скалярных произведений и проекций, — а автоматическое дифференцирование отслеживает прохождение градиентов через каждую из них.

Вы только что с нуля реализовали то, что NumPy делает одной строкой. Теперь вы знаете, что происходит внутри.

Подготовьте результат

В этом уроке создаётся:

  • outputs/prompt-linear-algebra-tutor.md — промпт для AI-ассистентов, который помогает обучать линейной алгебре через геометрическую интуицию.

Связи

Всё в этом уроке связано с конкретными составляющими современного AI:

Понятие Где оно встречается
Скалярное произведение Оценки внимания в трансформерах, косинусное сходство в RAG
Умножение матриц Каждый слой нейронной сети, каждое линейное преобразование
Линейная независимость Отбор признаков, предотвращение мультиколлинеарности
Ранг Определение разрешимости системы, LoRA (низкоранговая адаптация)
Проекция Линейная регрессия (проецирование на пространство столбцов), PCA
Грам — Шмидт / QR Численные решатели, вычисление собственных значений
Ортонормированный базис Устойчивые численные вычисления, преобразования отбеливания

LoRA заслуживает отдельного упоминания. Этот метод дообучает большие языковые модели, раскладывая обновления весов на матрицы низкого ранга. Вместо обновления матрицы весов 4096x4096, содержащей 16 млн параметров, LoRA обновляет две матрицы размерами 4096x16 и 16x4096, в которых всего 131 тыс. параметров. Ограничение ранга значением 16 означает, что LoRA предполагает: обновление весов находится в 16-мерном подпространстве полного 4096-мерного пространства. Вот как линейная алгебра выполняет реальную работу.

Упражнения

  1. Реализуйте Vector.angle_between(other), возвращающий угол между двумя векторами в градусах.
  2. Создайте двумерную матрицу масштабирования, которая удваивает x-координату и утраивает y-координату, а затем примените её к вектору [1, 1].
  3. Для 5 случайных векторов, подобных векторам слов, размерности 50 найдите два наиболее похожих с помощью косинусного сходства.
  4. Убедитесь, что результат процесса Грама — Шмидта действительно ортонормирован: проверьте, что скалярное произведение каждой пары равно 0, а длина каждого вектора равна 1.
  5. Создайте матрицу 3x3 ранга 2. Проверьте ранг с помощью метода rank(). Затем объясните, какой геометрический объект порождают её столбцы.
  6. Спроецируйте вектор [1, 2, 3] на [1, 1, 1]. Что полученный результат представляет геометрически?

[!warning] Уточнение переводчика Показанный в уроке класс Matrix не реализует метод rank(). Для упражнения используйте np.linalg.matrix_rank(matrix.data) либо сначала добавьте в класс соответствующий метод.

Ключевые термины

Термин Что обычно говорят Что это означает на самом деле
Вектор «Стрелка» Список чисел, представляющий точку или направление в n-мерном пространстве
Матрица «Таблица чисел» Преобразование, отображающее векторы из одного пространства в другое
Скалярное произведение «Перемножить и сложить» Мера сонаправленности двух векторов — основа поиска по сходству
Эмбеддинг «Какая-то магия AI» Вектор, представляющий смысл чего-либо: слова, изображения или пользователя
Линейная независимость «Они не перекрываются» Ни один вектор из набора нельзя представить как комбинацию остальных
Ранг «Сколько измерений» Число линейно независимых столбцов или строк матрицы
Проекция «Тень» Составляющая одного вектора в направлении другого
Базис «Координатные оси» Минимальный набор независимых векторов, порождающих пространство
Ортонормированный «Перпендикулярные единичные векторы» Векторы, взаимно перпендикулярные и имеющие длину 1

Источник: Linear Algebra Intuition — оригинал Навигация: назад: 00.12 — Отладка и профилирование · Фаза 1 — Математические основы · Полный каталог · далее: 01.02 — Векторы, матрицы и операции.