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

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

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

Линейная алгебра

Линейная алгебра посвящена работе с такими вещами, как векторы. Векторы можно складывать вместе и растягивать или сжимать (умножать) для создания новых векторов. Возможно, вы помните, что видели в школе «геометрические векторы», которые обычно обозначаются маленькой стрелкой над буквой. Эти векторы не просто стрелки; это объекты, которые следуют определенным правилам. Когда вы добавляете или растягиваете их, вы всегда получаете другой вектор. Но вот что интересно: такие вещи, как R^n и даже математические полиномы, тоже могут вести себя как векторы.

Вот как вы можете создать вектор или матрицу, используя numpy в python.

import numpy as np

A = np.array([
        [2, -1, 3],
        [1, 2, 4],
        [3, 0, -2]
    ], dtype=np.dtype(float))

b = np.array([7, 3, 8], dtype=np.dtype(float))

Почему это полезно

Матрицы служат мощным инструментом для представления изображений. В контексте монохромного изображения интенсивность каждого пикселя инкапсулируется одним числом, отражающим его оттенок серого. Когда дело доходит до RGB, изображения расширяют концепцию матрицы. Здесь каждый пиксель представлен тремя числами, обозначающими его отдельные цветовые каналы — красный, зеленый и синий.

Таким образом, матричные представления являются мостом между визуальными эффектами и вычислениями. Матрицы позволяют компьютерам обрабатывать, анализировать и манипулировать изображениями с поразительной точностью. Это особенно полезно при использовании таких методов, как сверточные нейронные сети (CNN), которые используют матричные операции для идентификации шаблонов и объектов в изображениях.

Системы линейных уравнений

Системы линейных уравнений лежат в основе практических приложений линейной алгебры. Систему линейных уравнений можно представить в виде:

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

Матрицы можно использовать как компактный способ формулирования систем линейных уравнений: Ax = b

Вот как их решить в Python (при условии, что вы уже импортировали numpy как np):

x = np.linalg.solve(A, b)

print(f"Solution: {x}")

Решение: массив([ 2,85 , -0,475, 0,275])

Определитель и ранг

Детерминант и ранг являются ключевыми понятиями при работе с матрицами.

При работе с квадратной матрицей, если определитель det(A) не равен 0, то A обратим. Как мы позже увидим, это ключевой результат при вычислении собственных значений, выполнении диагонализации и погружении в разложение по сингулярным значениям (SVD).

d = np.linalg.det(A)

print(f"Determinant of matrix A: {d:.2f}")

Выход: Определитель матрицы A: -40.00

Если матрица обратима (det(A) ≠ 0), она также имеет полный ранг. Это означает, что его ранг rk(A) равен n

Собственные значения и собственные векторы

Прежде чем понять полезность собственных значений и собственных векторов, давайте дадим им определение.

Вычисление собственных значений и собственных векторов в python выполняется просто с помощью numpy.

eigenvalues, eigenvectors = np.linalg.eig(A)

Почему это полезно. Собственные значения особенно полезны при уменьшении размерности, которое обычно используется при работе с многомерными данными. Идея, лежащая в основе этого, заключается в том, что многомерные данные часто имеют некоторую базовую структуру, которая может быть захвачена представлением более низкого измерения.

Одним из самых популярных методов уменьшения размерности является анализ главных компонентов (PCA). Когда мы вычисляем собственные значения матрицы, они показывают, сколько дисперсии захватывает каждый собственный вектор (главный компонент). В контексте уменьшения размерности мы стремимся сохранить собственные векторы с наибольшими собственными значениями, поскольку они соответствуют направлениям максимальной дисперсии данных. Один критерий, называемый «критерием Кайзера», заключается в сохранении компонентов, собственные значения которых больше 1. Вычисление собственных значений также полезно при выполнении разложения по сингулярным значениям (SVD).

Разложение по единственному значению (SVD)

Разложение по сингулярным числам (SVD) — это фундаментальный метод матричной факторизации в линейной алгебре. Он используется для разложения матрицы на три более простые матрицы. Теорему SVD можно сформулировать следующим образом:

где :

  • U — ортогональная матрица размером m×m, столбцы которой являются левыми сингулярными векторами матрицы A.
  • Σ — диагональная матрица m×n с неотрицательными действительными числами на диагонали, известными как сингулярные значения A.
  • V — ортогональная матрица n×n, столбцы которой являются правыми сингулярными векторами матрицы A.

Вы можете выполнить SVD в Python, используя numpy

import numpy as np

# Create a matrix
A = np.array([[1, 2, 3],
              [4, 5, 6],
              [7, 8, 9]])

# Perform SVD
U, S, VT = np.linalg.svd(A)

print("U:\n", U)
print("S:\n", S)
print("VT:\n", VT)

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

Основная идея использования SVD для матричной аппроксимации и представления низкого ранга заключается в том, что вы можете сохранить только первые k сингулярные значения и соответствующие им сингулярные векторы.

где U:,:k​ представляет первые k столбцы матрицы U,Σ:k ,:k​ относится к верхней левой подматрице k×k матрицы Σ и V :k,:T​ представляет первые k строк матрицы V^T.

Это также может быть выражено как сумма матриц ранга 1.

Где:

  • ui​ – это i-й столбец U:,:k​.
  • σi​ – это i-е единственное число из Σ:k,:k​.
  • vi​ – это iя строка V:k,:T​ .

Это представление помогает понять, как аппроксимация фиксирует основные закономерности в данных при использовании меньшего количества терминов. Другими словами, если вы усекаете SVD до промежуточного значения k (где kr, r равно ранг исходной матрицы A), вы получаете аппроксимацию ранга k исходной матрицы A.

Матричные разложения (Холески, Лу)

Разложение Холецкого — это метод матричной факторизации, специально разработанный для симметричных положительно определенных матриц. Он разлагает такую ​​матрицу на произведение нижней треугольной матрицы и ее сопряженного транспонирования (что совпадает с его обычным транспонированием из-за симметрии).

LU-разложение: LU-разложение (нижний-верхний) — еще один важный метод матричной факторизации. Он разлагает матрицу на произведение нижней треугольной матрицы L и верхней треугольной матрицы U. LU-разложение широко используется при решении систем линейных уравнений и обращении матриц.

Вы можете выполнять декомпозицию Cholesky и LU в Python, используя такие библиотеки, как NumPy и Scipy.

import numpy as np
import scipy.linalg

# Create a symmetric positive definite matrix
A = np.array([[4, 2, -1],
              [2, 5, 3],
              [-1, 3, 9]])

# Perform Cholesky decomposition
L = np.linalg.cholesky(A)

print("L:\n", L)

# Perform LU decomposition
P, L, U = scipy.linalg.lu(A)

Почему это полезно. Матричная декомпозиция — это мощный инструмент для различных операций в науке о данных. Разложение LU помогает эффективно решать системы линейных уравнений.

В моделях машинного обучения, таких как вариационные автоэнкодеры (VAE) и других глубоких вероятностных моделях, градиенты имеют решающее значение для оптимизации во время обучения, особенно для таких задач, как вариационный вывод и обратное распространение через вероятностные слои. Разложение Холецкого используется в этих моделях для эффективного вычисления градиентов по отношению к параметрам модели.

В следующей главе мы увидим, как эти декомпозиции также находят применение в стохастике и теории вероятностей, особенно в контексте многомерных распределений и моделирования. Эти методы обычно используются при оценке рисков, финансовом моделировании и моделировании методом Монте-Карло, где необходимо зафиксировать корреляции между переменными. Держите в курсе!