В этом параграфе мы разберём понятие определителя
. Обычно его рассматривают очень формально — как некоторую числовую характеристику матрицы.
Однако у него есть куда более глубокое значение, которое можно понять, рассмотрев его геометрическую интерпретацию в векторном пространстве. Для этого мы построим наглядные интерактивные визуализации. Также разберём, как можно с помощью различных библиотек вычислять определитель.
Определитель
можно представить как числовой «коэффициент масштабирования», который показывает, во сколько раз линейное преобразование изменяет объём (или площадь) пространства, а также указывает на сохранение или изменение его ориентации.

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

На рисунке выше мы видим, что исходный вектор повернулся на 270 градусов под действием умножения матрицы . Данная матрица — это частный случай матрицы поворота
, которая в двумерном пространстве имеет следующий вид:
Рассмотрим теперь другой наглядный пример действия матричного умножения на исходный вектор. В качестве матрицы возьмем :
Умножим вектор на матрицу слева и получим новый вектор :

На рисунке выше мы видим, что исходный вектор трансформировался под действием умножения матрицы : развернулся по обоим осям и растянулся в два раза по оси абсцисс. Данная матрица — это частный случай матрицы растяжения
, которая в двумерном пространстве имеет следующий вид:
Мы рассмотрели как с помощью матрицы можно задавать деформацию вектора, а также увидели, какие есть наглядные примеры таких деформаций. Давайте пойдём дальше и попробуем понять, как матрица действует на всё множество векторов, то есть на векторное пространство в целом.
Линейная деформация пространства
Зная, как матрица действует на отдельные векторы, теперь мы можем проследить, как деформируется всё пространство. Для этого нам нужно построить все возможные векторы из данного пространства и к каждому из них применить деформацию, задаваемую некоторой матрицей.
Применяя матрицу ко всем векторам, мы получаем целостное представление о том, как изменяются форма, объём и ориентация всего пространства. Представить, что в таком случае произойдёт с пространством, может быть достаточно сложно, поэтому попробуем визуализировать это схематично. Для наглядности также будем работать в векторном пространстве .
- Шаг 1: представим каждый вектор пространства не как стрелку, а как точку, которая соответствует конечной точке вектора.
- Шаг 2: множество всех таких точек можно представить как новую координатную сетку, наложенную на исходную.
- Шаг 3: применим деформацию ко всем векторам пространства, тогда каждая точка будет двигаться в какую-то другую точку на плоскости, а новая координатная сетка — деформироваться. При этом также сохраним и исходную координатную сетку, чтобы понять, как подействовала деформация относительно начального положения.

Таким образом, применяя линейное преобразование ко всем векторам пространства, мы не просто изменяем отдельные точки, а получаем новое представление о том, как преобразуется всё пространство: его форма, ориентация и масштаб. Это позволяет нам перейти от локального понимания действия матрицы к глобальному — увидеть, как матрица изменяет само полотно пространства.
💡В линейной алгебре множество допустимых деформаций не является произвольным: все они должны удовлетворять определённым свойствам. Более строго эти свойства будут сформулированы при рассмотрении линейных отображений.
Сейчас же нам важнее утверждения, которые следуют из этих свойств. При деформации пространства:
- Все линии координатной сетки остаются параллельными и на равных расстояниях.
- Начало координат зафиксировано и не меняется.
Чтобы вы смогли более наглядно пронаблюдать, как изменяется заданный вектор и всё пространство в целом под действием деформации, мы подготовили код с интерактивной визуализацией с помощью библиотек plotly
и streamlit
.
Код для визуализации линейной деформации двумерного пространства
Для запуска:
- Создайте
.py
файл, напримерapp.py
. - Вставьте туда написанный ниже код.
- Установите необходимые зависимости.
- Запустите приложение командой:
streamlit run app.py
1from typing import Any
2import numpy as np
3import plotly.graph_objects as go
4from plotly.subplots import make_subplots
5import streamlit as st
6
7
8def create_figure(a: float, b: float, c: float, d: float,
9 vector: np.ndarray, grid_range: int = 5, grid_step: int = 1
10 ) -> go.Figure:
11 """
12 Создаёт фигуру с двумя подграфиками (1x2):
13
14 1) Исходное пространство с заданным вектором v.
15 2) Деформированное пространство с образом вектора v'.
16
17 Параметры:
18 a, b, c, d (float): Элементы матрицы A = [[a, b], [c, d]].
19 vector (np.ndarray): Исходный вектор (длина 2).
20 grid_range (int): Диапазон значений координатной сетки.
21 grid_step (int): Шаг между линиями сетки.
22
23 Возвращает:
24 go.Figure: Фигура с двумя подграфиками.
25 """
26 xs: np.ndarray = np.arange(-grid_range, grid_range + grid_step, grid_step)
27 ys: np.ndarray = np.arange(-grid_range, grid_range + grid_step, grid_step)
28 matrix: np.ndarray = np.array([[a, b], [c, d]])
29
30 fig: go.Figure = make_subplots(
31 rows=1,
32 cols=2,
33 subplot_titles=["Исходное пространство", "Деформированное пространство"],
34 horizontal_spacing=0.02
35 )
36
37 def add_vector_annotation(x: float, y: float, xref: str, yref: str,
38 color: str, label: str,
39 row: int = 1, col: int = 1,
40 text_xshift: int = 10, text_yshift: int = -10) -> None:
41 """Добавляет стрелку и подпись в указанном подграфике."""
42 fig.add_annotation(
43 x=x, y=y,
44 ax=0, ay=0,
45 xref=xref, yref=yref,
46 axref=xref, ayref=yref,
47 showarrow=True,
48 arrowhead=3,
49 arrowcolor=color,
50 arrowsize=1,
51 arrowwidth=2,
52 text="",
53 row=row,
54 col=col
55 )
56 fig.add_annotation(
57 x=x, y=y,
58 xref=xref, yref=yref,
59 text=label,
60 showarrow=False,
61 xshift=text_xshift,
62 yshift=text_yshift,
63 row=row,
64 col=col
65 )
66
67 # Исходное пространство
68 for x_val in xs:
69 fig.add_trace(
70 go.Scatter(
71 x=[x_val, x_val],
72 y=[-grid_range, grid_range],
73 mode='lines',
74 line=dict(color='lightgray', dash='dash'),
75 showlegend=False
76 ),
77 row=1, col=1
78 )
79 for y_val in ys:
80 fig.add_trace(
81 go.Scatter(
82 x=[-grid_range, grid_range],
83 y=[y_val, y_val],
84 mode='lines',
85 line=dict(color='lightgray', dash='dash'),
86 showlegend=False
87 ),
88 row=1, col=1
89 )
90 add_vector_annotation(1, 0, "x", "y", "red", "i", row=1, col=1)
91 add_vector_annotation(0, 1, "x", "y", "green", "j", row=1, col=1)
92 add_vector_annotation(vector[0], vector[1], "x", "y", "blue", "v", row=1, col=1)
93
94 # Деформированное пространство
95 for x_val in xs:
96 line_y = np.linspace(-grid_range, grid_range, 100)
97 original_points = np.array([[x_val, y_val] for y_val in line_y])
98 transformed = original_points @ matrix.T
99 fig.add_trace(
100 go.Scatter(
101 x=transformed[:, 0],
102 y=transformed[:, 1],
103 mode='lines',
104 line=dict(color='lightgray', dash='dash'),
105 showlegend=False
106 ),
107 row=1, col=2
108 )
109 for y_val in ys:
110 line_x = np.linspace(-grid_range, grid_range, 100)
111 original_points = np.array([[x_val, y_val] for x_val in line_x])
112 transformed = original_points @ matrix.T
113 fig.add_trace(
114 go.Scatter(
115 x=transformed[:, 0],
116 y=transformed[:, 1],
117 mode='lines',
118 line=dict(color='lightgray', dash='dash'),
119 showlegend=False
120 ),
121 row=1, col=2
122 )
123
124 v_prime: np.ndarray = matrix @ vector
125 add_vector_annotation(v_prime[0], v_prime[1], "x2", "y2", "blue", "v'", row=1, col=2)
126 i_prime: np.ndarray = matrix @ np.array([1, 0])
127 j_prime: np.ndarray = matrix @ np.array([0, 1])
128 add_vector_annotation(i_prime[0], i_prime[1], "x2", "y2", "red", "i'", row=1, col=2)
129 add_vector_annotation(j_prime[0], j_prime[1], "x2", "y2", "green", "j'", row=1, col=2)
130
131 fig.update_layout(
132 width=1000,
133 height=500,
134 margin=dict(l=0, r=0, t=50, b=50),
135 xaxis=dict(
136 domain=[0, 0.45],
137 range=[-grid_range, grid_range],
138 scaleanchor="y",
139 scaleratio=1,
140 constrain="domain"
141 ),
142 yaxis=dict(
143 domain=[0, 1],
144 range=[-grid_range, grid_range],
145 scaleanchor="x",
146 scaleratio=1,
147 constrain="domain"
148 ),
149 xaxis2=dict(
150 domain=[0.55, 1],
151 range=[-grid_range, grid_range],
152 scaleanchor="y2",
153 scaleratio=1,
154 constrain="domain"
155 ),
156 yaxis2=dict(
157 domain=[0, 1],
158 range=[-grid_range, grid_range],
159 scaleanchor="x2",
160 scaleratio=1,
161 constrain="domain"
162 )
163 )
164
165 return fig
166
167def main() -> None:
168 """Главная функция приложения Streamlit."""
169 st.title("Интерактивная визуализация линейной деформации")
170
171 st.subheader("Коэффициенты матрицы линейного отображения")
172 col1, col2 = st.columns(2)
173 a: float = col1.number_input("a:", value=1.0, step=0.1)
174 b: float = col2.number_input("b:", value=0.0, step=0.1)
175 col3, col4 = st.columns(2)
176 c: float = col3.number_input("c:", value=0.0, step=0.1)
177 d: float = col4.number_input("d:", value=1.0, step=0.1)
178
179 st.subheader("Координаты исходного вектора")
180 v1: float = st.number_input("v₁:", value=2.0, step=0.1)
181 v2: float = st.number_input("v₂:", value=1.0, step=0.1)
182 vector: np.ndarray = np.array([v1, v2])
183
184 fig: go.Figure = create_figure(a, b, c, d, vector)
185 st.plotly_chart(fig, use_container_width=True)
186
187if __name__ == '__main__':
188 main()
189
Итак, теперь у нас есть визуальная интуиция, которая поможет лучше понять линейные деформации: как они изменяют и отдельные векторы, и всё пространство в целом. Таким образом, у нас есть все необходимые знания, чтобы понять, какой смысл скрывается за определителем.
Геометрический смысл определителя
Теперь давайте попробуем разобраться, какой именно геометрический смысл скрывается за понятием определителя.
Мы уже видели, как матрица деформирует пространство, — теперь настало время количественно оценить результат этой деформации. Для этого мы рассмотрим, как меняется площадь при линейном преобразовании, и выясним, какую роль в этом играет определитель.
Изменение площади пространства при деформации
Рассматривая примеры выше, вы могли заметить, что какие-то из деформаций сжимают исходное пространство, а другие — наоборот, растягивают его. Поэтому, чтобы лучше понять, как действует та или иная деформация, хочется уметь оценивать коэффициент изменения исходной площади пространства под действием деформации.
Этот коэффициент по модулю как раз и будет равен определителю
. Чтобы его найти, давайте рассмотрим единичный квадрат, натянутый на векторы нашего базиса и :

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

При линейной деформации пространства исходный единичный квадрат может перейти в параллелограмм, отрезок или точку. Напомним формулу для подсчёта площади параллелограмма: , где — сторона параллелограмма, а — высота, проведённая к этой стороне. Тогда после деформации пространства матрицей коэффициент изменения площади равен: .
Отражение пространства
Теперь добавим к рассмотренному выше растяжению пространства его отражение. Возьмём следующую матрицу :
Найдём новые координаты наших базисных векторов и :
Теперь отобразим исходный единичный квадрат, а также полученный прямоугольник:

По аналогии с предыдущим примером рассчитаем коэффициент изменения площади: . Однако в этом примере стоит обратить внимание на то, что наши базисные векторы тоже изменили свою ориентацию в пространстве.
Если мы представим рассматриваемую плоскость как белый лист бумаги, на котором отложены наши базисные векторы, то, чтобы поменять направление базисных векторов так, как показано на рисунке выше, нам обязательно придётся перевернуть лист на другую сторону — можете проделать данное упражнение. Также можно смотреть на это и иначе: в исходном пространстве вектор находится слева от вектора ; если после деформации пространства вектор оказывается справа от вектора , это означает, что ориентация пространства была обращена.
Таким образом, при изучении деформаций пространства полезно понимать не только как изменяется площадь, но и происходит ли изменение ориентации. Выше мы сказали, что коэффициент изменения исходной площади пространства под действием деформации по модулю равен определителю
. Если учесть смену ориентации как изменение знака коэффициента, то получим в точности значение определителя
. То есть в примере выше определитель
будет равен .
Скос пространства
Возьмём следующую матрицу :
Найдём новые координаты наших базисных векторов и :
Теперь отобразим исходный единичный квадрат, а также полученный параллелограмм:

В данном случае легко заметить, что изменения площади не произошло, и после деформации она по-прежнему равна .
-
Связь с нормализующими потоками в глубинном обучении
В задачах глубинного обучения можно отметить интересную связку с определителем. В современных генеративных моделях, таких как нормализующие потоки (например, RealNVP или Glow), используется формула изменения плотности:
где — якобиан одного слоя преобразования. Когда преобразование сохраняет объём (то есть ), оно становится проще и эффективнее в вычислениях. Такие преобразования называются volume-preserving.
Примеры: поворот, скос, ортогональные матрицы — всё это деформации, при которых определитель равен . Они активно используются в слоях типа affine coupling или -свёртках, параметризуемых с помощью LU-разложений. Например, в PyTorch логарифм определителя можно быстро посчитать так:
1P, L, U = torch.linalg.lu(W) # W — матрица свёртки 2logdet = torch.sum(torch.log(torch.abs(torch.diag(U))))
👉🏽 А значит, снова срабатывает хорошо знакомое правило: если матрица треугольная — определитель равен произведению диагонали.
Сплющивание пространства
Возьмём следующую матрицу :
Найдём новые координаты наших базисных векторов и :
Теперь отобразим исходный единичный квадрат и полученный отрезок:

Мы видим, что в данном случае единичный квадрат, натянутый на базисные векторы, сплющило в отрезок. Это важный пример, который показывает, как сильно линейная деформация может изменить пространство. Тут полезно вспомнить про рассмотренную ранее линейную независимость и внимательно посмотреть на векторы, которые получаются после деформации. В данном примере определитель
равен нулю.
Пояснение
Выше мы везде считали определитель как изменение площади единичного квадрата при деформации. Это было сделано для лучшего визуального понимания. В действительности мы можем считать определитель как ориентированную площадь (учитывая знак, который показывает, сохраняется или меняется ориентация) параллелограмма, натянутого на векторы, которые уложены как векторы-столбцы в матрицу , задающую деформацию:
Если мы подействуем матрицей на наши базисные векторы, то полученные образы этих векторов и будут в точности столбцы матрицы . Вы могли убедиться в этом на примерах, рассмотренных выше.
Чтобы вы смогли более наглядно увидеть, как под действием деформации изменяется пространство и базисные векторы, а также чему равен определитель, мы подготовили код с интерактивной визуализацией посредством библиотек plotly
и streamlit
.
Код для визуализации линейной деформации двумерного пространства и изменения площади
Алгоритм запуска кода тот же.
1import streamlit as st
2import numpy as np
3import plotly.graph_objects as go
4from plotly.subplots import make_subplots
5from typing import Any
6
7def create_figure(a: float, b: float, c: float, d: float, grid_range: int = 5, grid_step: int = 1
8 ) -> go.Figure:
9 """
10 Создаёт фигуру с двумя подграфиками (1x2):
11
12 1) Исходное пространство и единичный квадрат.
13 2) Деформированное пространство с образом единичного квадрата.
14
15 Параметры:
16 a, b, c, d (float): Элементы матрицы A = [[a, b], [c, d]].
17 grid_range (int): Диапазон значений координатной сетки.
18 grid_step (int): Шаг между линиями сетки.
19
20 Возвращает:
21 go.Figure: Фигура с двумя подграфиками.
22 """
23 # Создаём сетку координат
24 xs: np.ndarray = np.arange(-grid_range, grid_range + grid_step, grid_step)
25 ys: np.ndarray = np.arange(-grid_range, grid_range + grid_step, grid_step)
26 matrix: np.ndarray = np.array([[a, b], [c, d]])
27
28 # Создаём подграфики
29 fig: go.Figure = make_subplots(
30 rows=1,
31 cols=2,
32 subplot_titles=["Исходное пространство", "Деформированное пространство"],
33 horizontal_spacing=0.02
34 )
35
36 def add_vector_annotation(x: float, y: float, xref: str, yref: str,
37 color: str, label: str,
38 row: int = 1, col: int = 1,
39 text_xshift: int = 10, text_yshift: int = -10) -> None:
40 """
41 Добавляет на фигуру стрелку (от (0,0) до (x,y)) и текстовую подпись рядом.
42 """
43 # Стрелка
44 fig.add_annotation(
45 x=x, y=y,
46 ax=0, ay=0,
47 xref=xref, yref=yref,
48 axref=xref, ayref=yref,
49 showarrow=True,
50 arrowhead=3,
51 arrowcolor=color,
52 arrowsize=1.0,
53 arrowwidth=2,
54 text="",
55 row=row,
56 col=col
57 )
58 # Подпись вектора
59 fig.add_annotation(
60 x=x, y=y,
61 xref=xref, yref=yref,
62 text=label,
63 showarrow=False,
64 xshift=text_xshift,
65 yshift=text_yshift,
66 row=row,
67 col=col
68 )
69
70 # -----------------------------
71 # 1) Исходное пространство
72 # -----------------------------
73 # Рисуем координатную сетку
74 for x_val in xs:
75 fig.add_trace(
76 go.Scatter(
77 x=[x_val, x_val],
78 y=[-grid_range, grid_range],
79 mode='lines',
80 line=dict(color='lightgray', dash='dash'),
81 showlegend=False
82 ),
83 row=1, col=1
84 )
85 for y_val in ys:
86 fig.add_trace(
87 go.Scatter(
88 x=[-grid_range, grid_range],
89 y=[y_val, y_val],
90 mode='lines',
91 line=dict(color='lightgray', dash='dash'),
92 showlegend=False
93 ),
94 row=1, col=1
95 )
96
97 # Рисуем базис: i, j
98 add_vector_annotation(1, 0, "x", "y", "red", "i", row=1, col=1)
99 add_vector_annotation(0, 1, "x", "y", "green", "j", row=1, col=1)
100
101 # Рисуем единичный квадрат (параллелограмм) в исходном пространстве
102 square: np.ndarray = np.array([[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]])
103 fig.add_trace(
104 go.Scatter(
105 x=square[:, 0],
106 y=square[:, 1],
107 mode='lines',
108 fill='toself',
109 fillcolor='rgba(255,165,0,0.15)', # оранжевый, прозрачность 15%
110 line=dict(color='orange'),
111 showlegend=False
112 ),
113 row=1, col=1
114 )
115
116 fig.update_xaxes(range=[-grid_range, grid_range], scaleanchor="y", scaleratio=1, row=1, col=1)
117 fig.update_yaxes(range=[-grid_range, grid_range], row=1, col=1)
118
119 # -----------------------------
120 # 2) Деформированное пространство
121 # -----------------------------
122 for x_val in xs:
123 line_y = np.linspace(-grid_range, grid_range, 100)
124 original_points = np.array([[x_val, y_val] for y_val in line_y])
125 transformed = original_points @ matrix.T
126 fig.add_trace(
127 go.Scatter(
128 x=transformed[:, 0],
129 y=transformed[:, 1],
130 mode='lines',
131 line=dict(color='lightgray', dash='dash'),
132 showlegend=False
133 ),
134 row=1, col=2
135 )
136 for y_val in ys:
137 line_x = np.linspace(-grid_range, grid_range, 100)
138 original_points = np.array([[x_val, y_val] for x_val in line_x])
139 transformed = original_points @ matrix.T
140 fig.add_trace(
141 go.Scatter(
142 x=transformed[:, 0],
143 y=transformed[:, 1],
144 mode='lines',
145 line=dict(color='lightgray', dash='dash'),
146 showlegend=False
147 ),
148 row=1, col=2
149 )
150
151 # Образы базиса: i -> i' и j -> j'
152 i_prime: np.ndarray = matrix @ np.array([1, 0])
153 j_prime: np.ndarray = matrix @ np.array([0, 1])
154 add_vector_annotation(i_prime[0], i_prime[1], "x2", "y2", "red", "i'", row=1, col=2)
155 add_vector_annotation(j_prime[0], j_prime[1], "x2", "y2", "green", "j'", row=1, col=2)
156
157 # Рисуем образ единичного квадрата в деформированном пространстве
158 square_transformed: np.ndarray = square @ matrix.T
159 fig.add_trace(
160 go.Scatter(
161 x=square_transformed[:, 0],
162 y=square_transformed[:, 1],
163 mode='lines',
164 fill='toself',
165 fillcolor='rgba(255,165,0,0.15)',
166 line=dict(color='orange'),
167 showlegend=False
168 ),
169 row=1, col=2
170 )
171
172 # Настройка осей и размеров подграфиков
173 fig.update_layout(
174 width=1000,
175 height=500,
176 margin=dict(l=0, r=0, t=50, b=50),
177 xaxis=dict(
178 domain=[0, 0.45],
179 range=[-grid_range, grid_range],
180 scaleanchor="y",
181 scaleratio=1,
182 constrain="domain"
183 ),
184 yaxis=dict(
185 domain=[0, 1],
186 range=[-grid_range, grid_range],
187 scaleanchor="x",
188 scaleratio=1,
189 constrain="domain"
190 ),
191 xaxis2=dict(
192 domain=[0.55, 1],
193 range=[-grid_range, grid_range],
194 scaleanchor="y2",
195 scaleratio=1,
196 constrain="domain"
197 ),
198 yaxis2=dict(
199 domain=[0, 1],
200 range=[-grid_range, grid_range],
201 scaleanchor="x2",
202 scaleratio=1,
203 constrain="domain"
204 )
205 )
206
207 return fig
208
209def main() -> None:
210 """Главная функция приложения Streamlit."""
211 st.title("Интерактивная визуализация линейной деформации")
212
213 st.subheader("Коэффициенты матрицы линейного отображения")
214 col1, col2 = st.columns(2)
215 a: float = col1.number_input("a:", value=1.0, step=0.1)
216 b: float = col2.number_input("b:", value=0.0, step=0.1)
217 col3, col4 = st.columns(2)
218 c: float = col3.number_input("c:", value=0.0, step=0.1)
219 d: float = col4.number_input("d:", value=1.0, step=0.1)
220
221 # Вычисляем площадь (|det A|) и выводим в отдельном блоке
222 matrix: np.ndarray = np.array([[a, b], [c, d]])
223 area_scale: float = np.linalg.det(matrix)
224 st.markdown(f"**det A:** {area_scale:.2f}")
225 st.markdown(f"**Изменение площади (|det A|):** {abs(area_scale):.2f}")
226
227 fig: go.Figure = create_figure(a, b, c, d)
228 st.plotly_chart(fig, use_container_width=True)
229
230if __name__ == '__main__':
231 main()
232
Теперь давайте посмотрим на результат кода выше.
Пусть дана матрица , такая что:
Тогда деформация пространства под действием линейного отображения, заданного матрицей , будет выглядеть следующим образом:

Итак, мы рассмотрели, какая визуальная интуиция стоит за линейными деформациями, на примере пространства . В пространстве можно привести аналогичные рассуждения, только вместо единичного квадрата мы будем оперировать единичным кубом, а при деформациях получать уже не параллелограмм, а параллелепипед, и оценивать не площадь, а объём. То есть эти рассуждения справедливы и для пространства . Таким образом, можно кратко заключить:
💡 Определитель — это -мерный ориентированный объём, натянутый на векторы матрицы, задающей линейное отображение (деформацию пространства).
Связь с анализом данных: важность определителя в PCA
Одна из самых известных задач в анализе данных — это задача понижения размерности. Она возникает, когда у нас есть высокоразмерные данные (например, каждый объект описан сотней признаков), а мы хотим свести их к меньшему числу характеристик, сохранив как можно больше информации.
Метод главных компонент (Principal Component Analysis, PCA) решает эту задачу. Он находит новое ортонормированное базисное пространство (новые оси), в котором можно выразить данные, и при этом:
- эти новые оси упорядочены по убыванию дисперсии — то есть первая главная компонента направлена туда, где у данных наибольший разброс;
- если оставить только первые компонент (осей), то в проекции на это ‑мерное подпространство данные сохраняют максимум своей изменчивости.
Но есть и геометрический взгляд на PCA: если — ковариационная матрица наших данных (то есть матрица, которая описывает, как признаки расползлись в пространстве), а — матрица из ортонормированных векторов (направлений, вдоль которых мы хотим проектировать данные), то PCA ищет такие векторы , чтобы максимизировать объём проекции точек данных. Этот объём можно выразить через определитель:
Здесь — это ковариационная матрица уже после проекции, а — ориентированный объём, занимаемый данными в новом ‑мерном пространстве. Таким образом, PCA стремится найти те направления, вдоль которых данные сохраняют наибольший объём, а не «сплющиваются».
Теперь, когда у нас есть интуитивное представление о геометрическом смысле определителя как коэффициента масштабирования объёма, перейдём к его строгому математическому определению.
Это поможет нам не только закрепить интуицию, но и понять, как определитель вычисляется формально, особенно в случае размерностей выше трёх, где визуализация уже не столь очевидна.
Формальное определение
Для квадратной матрицы её определитель обозначается как (от англ. determinant) и вычисляется по формуле:
где:
- — перестановка;
- — множество всех перестановок на -элементном множестве;
- — знак перестановки ;
- — элемент матрицы , выбираемый из -й строки и -го столбца.
Как вы видите, в формуле используются перестановки
. Разбирать подробно, что это такое, сейчас мы не будем. Но для контекста дадим формальное определение, покажем, как их можно задавать и как задаётся знак перестановки.
Перестановки
Пусть — конечное множество из занумерованных элементов. Перестановкой
называется биективное отображение .
Как задавать перестановки
С помощью таблицы значений, где под каждым элементом пишется его образ :
Знак перестановки
Обычно знак перестановки определяют в виде , где — число инверсий
. Пусть и — пара различных элементов, тогда эта пара называется инверсией
, если влечёт , а влечёт .
Теперь давайте снова вернёмся к формальному определению определителя и попробуем его разобрать, уже зная, что такое перестановки. Внутри суммы стоят произведения вида , где первый индекс — это индекс строки в матрице и эти индексы идут по порядку от до .
Второй индекс записан так, что мы получаем его из перестановки . То есть мы каждый раз выбираем элементы так, чтобы из каждой строки и каждого столбца взять строго один элемент. Все эти элементы перемножаем, добавляем знак и получаем одно слагаемое. Затем мы берём другую перестановку из и повторяем процедуру, получая новое слагаемое. В итоге всего получится слагаемых.
Возможно, теперь стало наглядно понятно, что без визуальной интуиции довольно сложно понять смысл, который стоит за определителем, именно поэтому мы так много внимания уделили его геометрической интерпретации. Кроме этого, определитель очень тесно связан с невырожденными матрицами
, давайте рассмотрим этот момент подробнее.
Невырожденные матрицы
Ранее, когда мы рассматривали обратные матрицы, то сделали оговорку, что обратимые матрицы также называют невырожденными, так как, по существу, эти два термина отражают одно и то же свойство квадратной матрицы — существование обратной матрицы. Теперь, познакомившись с определителем, можно дать определение невырожденной матрицы.
Невырожденная матрица
— это квадратная матрица, определитель которой отличен от нуля. В противном случае матрица называется вырожденной
.
Произвольная матрица является невырожденной
, если удовлетворяет любому из следующих эквивалентных условий и наоборот.
- Система линейных уравнений имеет только нулевое решение .
- Матрица представляется в виде произведения матриц элементарных преобразований.
- Матрица обратима.
- Определитель матрицы отличен от нуля.
На практике, чтобы понять, является ли произвольная матрица обратимой, можно, например, проверить, выполняется ли самое простое условие: .
Вычисление в малых размерностях
Из формулы определителя видно, что вычислять его достаточно сложно — нужно получить слагаемых. Поэтому в реальной жизни данной формулой пользуются крайне редко. Обычно используют уже знакомое нам LU
-разложение, так как для треугольных матриц можно очень легко посчитать определитель, просто перемножив диагональные элементы.
Для пространств малой размерности существуют явные формулы (которые выводятся из формулы, приведённой в определении определителя), и по ним легко вычислять определитель. Давайте их рассмотрим.
- Если :
- Если :
Схематично данную формулу можно изобразить так:

Пример:
- Если :
Схематично данную формулу можно изобразить так:

Пример:
Здесь полезно, глядя на формулы вычисления определителя, задуматься о виде матриц, для которых его вычисление будет намного проще. Рассмотрим верхне- и нижнетреугольные матрицы.
Для них определитель будет вычисляться следующим образом:
Для доказательства нужно посчитать определитель по определению через перестановки и увидеть, что все слагаемые, кроме одного, где берутся только диагональные элементы, будут равны нулю. Таким образом, для подобного рода матриц можно очень быстро найти определитель, следовательно, полезно попытаться привести исходную матрицу именно к такому виду.
Как вы думаете, чему равен определитель для каждой из матриц, задающих элементарные преобразования?
Ответ (не открывайте сразу, сначала подумайте сами!)
- Прибавление одной строки к другой с множителем ():
- Перестановка двух строк:
- Умножение строки на ненулевую константу :
Давайте рассмотрим свойства определителя, чтобы понять, какие операции можно совершать с исходной матрицей, не повлияв на значение определителя.
Свойства определителя
Определитель напрямую по формуле вычислять сложно — слагаемых слишком много. Но, если использовать его свойства, можно упростить задачу: привести матрицу к такому виду, при котором это будет сделать проще.
Пусть , тогда на неё можно смотреть как на набор из векторов, уложенных как вектор-столбцы, то есть:
Тогда определитель можно рассматривать как функцию от столбцов матрицы , то есть:
И можно сформулировать следующие свойства:
-
Линейность определителя по каждому столбцу:
-
При изменении позиции столбца меняется знак определителя:
-
Если у матрицы есть два одинаковых столбца, то определитель равен нулю:
-
Если один из столбцов умножить на одно и то же число, то и весь определитель умножится на это же число:
-
Если к одному столбцу матрицы прибавить другой, умноженный на коэффициент, то определитель не изменится:
-
Все сформулированные выше свойства для столбцов также верны и для строк, так как:
-
Мультипликативность определителя:
-
Определитель от обратной матрицы:
Как видите, на практике может быть эффективно приводить исходную матрицу элементарными преобразованиями к треугольному виду, попутно запоминая некоторые коэффициенты, которые можно вынести за определитель. Давайте рассмотрим ещё один способ вычисления определителя через разложение по строке (столбцу).
Миноры и алгебраические дополнения
Мы рассмотрели, как можно вычислить определитель через явную формулу, а также раскрыли её для случаев малой размерности. Давайте рассмотрим ещё один способ подсчёта определителя.
Для этого введём ряд дополнительных понятий. Пусть — некоторая матрица с элементом . Рассмотрим матрицу , полученную путем вычёркивания строки и столбца из матрицы .
где — это в общем случае матрицы, оставшиеся в исходной матрице после вычёркивания -строки и -столбца. Такой вид записи матрицы называют блочным, так как мы записываем матрицу не отдельными элементами, а сразу блоками из других матриц.
Определитель матрицы обозначается и называется минором
матрицы или -минором. Число называется алгебраическим дополнением
элемента или -алгебраическим дополнением матрицы .
Также выделяют присоединённую матрицу
для , которая определяется так:
То есть нужно сперва рассчитать для каждого элемента его алгебраическое дополнение и уложить их в матрицу согласно -индексу, а затем полученную матрицу транспонировать. Также часто присоединённую матрицу
для обозначают как , то есть . С помощью присоединённой матрицы и определителя можно найти обратную матрицу:
Присоединённая матрица в ML
Если размер матрицы небольшой () и требуется вычислить производную по обратной матрице, можно использовать следующую формулу:
Такой подход используется в DL-библиотеках (например, JAX, PyTorch) при написании кастомных градиентов для маленьких матриц , особенно в задачах обучения свёрточных фильтров с фиксированным размером ядра (например, в 2D SPP‑модулях). Это быстрее и точнее, чем использовать универсальный torch.inverse()
.
Теперь, когда у нас есть представление о минорах и алгебраических дополнениях, мы можем использовать их для альтернативного способа вычисления определителя.
Этот способ называется разложением по строке или столбцу, и он особенно удобен, когда в выбранной строке или столбце много нулей — тогда часть слагаемых в формуле зануляется и вычисления сильно упрощаются.
Разложение по строке (столбцу)
Пусть дана некоторая матрица , тогда:
-
Для любой -строки верно разложение:
-
Для любого -столбца верно разложение:
Давайте рассмотрим конкретный пример, разложим по второму столбцу:
Однако на практике гораздо удобнее и надёжнее воспользоваться готовыми библиотеками, которые автоматически рассчитывают определитель. Давайте посмотрим, как это можно сделать в Python.
Вычисление в Python
Существует несколько популярных библиотек, с помощью которых можно найти определитель матрицы. Ниже кратко сравним их и приведём примеры использования.
Название |
Применение |
NumPy |
Это наиболее универсальный и часто используемый инструмент для работы с числами на CPU. Функция `numpy.linalg.det()` оптимизирована за счёт использования библиотеки [LAPACK](https://github.com/Reference-LAPACK), что обеспечивает высокую скорость и низкий расход памяти при работе с матрицами, особенно если их размер невелик. Если вы не используете специализированные функции глубокого обучения или символьные вычисления, то `numpy` — оптимальный выбор. |
SciPy |
Модуль `scipy.linalg` предоставляет схожие возможности с `numpy`, но может быть удобен, если вы работаете с более специализированными алгоритмами линейной алгебры или вам требуется поддержка некоторых редких матричных форматов. Скорость и расход памяти будут примерно на том же уровне, что и в `numpy`. |
PyTorch и TensorFlow |
Эти библиотеки разработаны в первую очередь для задач глубокого обучения и автоматического дифференцирования. Они поддерживают вычисления на GPU, что может быть преимуществом при обработке больших матриц или батчей данных. Но для вычисления определителя небольших матриц на CPU они могут накладывать дополнительные издержки по сравнению с `numpy`. Если вы уже работаете с моделями нейронных сетей, то использовать встроенные функции (`torch.det()` или `tf.linalg.det()`) будет удобнее, так как это позволяет избежать лишних преобразований данных. |
Теперь давайте на практике посмотрим, как с помощью этих библиотек можно вычислить определитель. Начнём с самой универсальной — numpy
.
NumPy
Самая часто используемая библиотека для численных вычислений. Функция numpy.linalg.det()
вычисляет определитель массива, используя оптимизированные алгоритмы из LAPACK.
1import numpy as np
2
3A = np.array([[1, 2],
4 [3, 4]])
5det_A = np.linalg.det(A)
6print("Определитель матрицы A (numpy): ", det_A)
7
8# Output:
9# Определитель матрицы A (NumPy): -2.00
SciPy
В библиотеке scipy
есть модуль scipy.linalg
, где функция det()
также позволяет вычислять определитель. Эта функция часто используется, если требуется использовать дополнительные возможности или типы матриц.
1import numpy as np
2from scipy.linalg import det
3
4A = np.array([[1, 2],
5 [3, 4]])
6det_A = det(A)
7print(f"Определитель матрицы A (SciPy): {det_A:.2f}")
8
9# Output:
10# Определитель матрицы A (SciPy): -2.00
PyTorch
В контексте машинного обучения при работе с тензорами можно использовать pytorch
. Функция torch.det()
вычисляет определитель для тензоров.
1import torch
2
3A = torch.tensor([[1.0, 2.0],
4 [3.0, 4.0]])
5det_A = torch.det(A)
6print(f"Определитель матрицы A (PyTorch): {det_A.item():.2f}")
7
8# Output:
9# Определитель матрицы A (PyTorch): -2.00
TensorFlow
Для тех кто использует tensorflow
, также доступна функция tf.linalg.det()
, которая вычисляет определитель тензоров.
1import tensorflow as tf
2
3A = tf.constant([[1.0, 2.0],
4 [3.0, 4.0]])
5det_A = tf.linalg.det(A)
6print(f"Определитель матрицы A (TensorFlow): {det_A.numpy():.2f}")
7
8# Output:
9# Определитель матрицы A (TensorFlow): -2.00
Если вы занимаетесь стандартными численными вычислениями или анализом данных на CPU, то numpy
(или scipy
) будет лучшим выбором благодаря своей скорости и низким затратам памяти. Если же вы работаете в контексте глубокого обучения и уже используете pytorch
или tensorflow
, имеет смысл применять их функции для согласованности вычислительного графа и возможного ускорения на GPU.
Применение определителя в задачах анализа данных
Обычно определитель используется как некоторый вспомогательный инструмент, который позволяет узнать полезную информацию про матрицу. В машинном обучении, когда требуется оценить вероятность наблюдения в многомерном пространстве, используется формула:
где:
- — функция плотности вероятности для случайного вектора с математическим ожиданием и ковариационной матрицей ;
- — определитель ковариационной матрицы, который играет роль нормализующей константы.
Роль определителя:
-
Нормализация распределения.
Определитель , входя в знаменатель нормирующего множителя , обеспечивает, что интеграл плотности по всему пространству равен единице. Математически это гарантирует корректное масштабирование распределения.
-
Связь с объёмом.
Геометрически определитель ковариационной матрицы отражает объём эллипсоида, описывающего область, в которой находится большая часть вероятности (так называемый контур доверительного интервала). Чем меньше , тем более «сжатое» распределение, что означает, что данные сконцентрированы в меньшем объёме пространства.
-
Чувствительность к вырожденности.
Если , это указывает на то, что ковариационная матрица близка к вырожденной — например, когда признаки почти линейно зависимы. В таких случаях модель может испытывать проблемы с числовой стабильностью: обратная матрица становится нестабильной, а оценка правдоподобия — некорректной.
-
Применение в алгоритмах.
В моделях типа Gaussian Mixture Models (GMM) для каждой компоненты рассчитывается своя ковариационная матрица, и её определитель влияет на вклад компоненты в общую вероятность наблюдения.
В заключении отметим, что определитель — это очень полезный инвариант, который выступает как лаконичный индикатор важных свойств и характеристик линейного отображения или матрицы. Так с помощью него можно проверить вырожденность матрицы или дать геометрическую интерпретацию линейным отображениям, о которых мы как раз и поговорим в следующем параграфе.