Як визначити обчислювач матриці або ndArray, використовуючи numpy в Python?
У цій статті ми навчимося обчислювати визначник матриці за допомогою бібліотеки numpy у Python. Визначник матриці – це скалярна величина, яка може представляти матрицю у компактній формі. Це корисна величина в лінійній алгебрі, і вона має кілька застосувань у різних галузях, таких як фізика, інженерія та інформатика.
У цій статті ми спочатку розглянемо визначення та властивості визначника. Потім ми навчимося обчислювати визначник матриці за допомогою numpy та розглянемо кілька прикладів, щоб побачити, як це працює на практиці.
Визначення та властивості визначника.
Визначник матриці - це скалярна величина, яку можна використовувати для опису властивостей матриці компактної форми. Його часто позначають | A | або det(A), де A - матриця. Визначник є фундаментальним поняттям лінійної алгебри і має кілька важливих властивостей, які роблять його потужним інструментом математичних обчислень.
- Однією з найбільш примітних властивостей визначника і те, що він дорівнює добутку власних значень матриці. Власні значення - це набір спеціальних скалярних значень, які показують, як матриця діє певні вектори, і грають вирішальну роль багатьох додатках лінійної алгебри.
- Ще однією важливою властивістю визначника є те, що він дорівнює добутку діагоналей верхньої або нижньої трикутної матриці. Трикутна матриця - це матриця, що має нулі нижче або вище діагоналі, і ця властивість корисна при обчисленні визначників великих матриць.
Обчислення визначника матриці з використанням numpy
Щоб визначити обчислювач матриці за допомогою numpy, ми можемо використовувати функцію linalg.det(). Ця функція приймає на вхід матрицю та повертає визначник матриці.Давайте подивимося на приклад –
import numpy as np # create a 2x2 matrix matrix = np.array([[5, 6], [7, 8]]) # calculate determinant of matrix determinant = np.linalg.det(matrix)
Вихід
Пояснення коду
Як бачите, функція linalg.det() обчислює визначник матриці та повертає його у вигляді скалярного значення. У разі визначник матриці дорівнює -2,0.
Обчислення визначника багатовимірної матриці
Щоб визначити обчислювач багатовимірної матриці, ми можемо використовувати ту ж функцію linalg.det(). Давайте подивимося на приклад –
import numpy as np # create a 3x3 singular matrix matrix = np.array([[20, 21, 22], [23, 24, 25], [26, 27, 28]]) # calculate the determinant of the matrix determinant = np.linalg.det(matrix) print(determinant)
Вихід
2.131628207280298e-14
Пояснення коду
Як бачите, функцію linalg.det() можна також використовувати для обчислення визначника багатовимірної матриці. І тут визначник матриці дорівнює 0,0.
Обчислення визначника сингулярної матриці
сингулярна матриця - це матриця, яка не має зворотної. Визначник сингулярної матриці дорівнює 0, що означає, що вона необоротна. Давайте подивимося на приклад –
Приклад 1
У наступному прикладі функція linalg.det() повертає 0 для сингулярної матриці, що вказує на те, що вона необоротна.
import numpy as np # create a 3x3 matrix matrix = np.array([[10, 11, 12], [13, 14, 15], [16, 17, 18]]) # calculate the determinant of the matrix determinant = np.linalg.det(matrix) print(determinant)
Вихід
Приклад 2
Функція linalg.slogdet() повертає знак та логарифм визначника матриці. Визначник розраховується з використанням методу LU-розкладання, який є більш стабільним і точним, ніж метод, що використовується функцією linalg.det().
Однією з переваг використання функції linalg.slogdet() є те, що вона стабільніша і точніша, ніж функція linalg.det(), особливо для великих матриць.Однак майте на увазі, що він повертає логарифм визначника, тому вам потрібно буде взяти показник ступеня результату, щоб отримати фактичний визначник.
import numpy as np # create a 3x3 matrix matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) # calculate the determinant of the matrix using the linalg.slogdet() function sign, determinant = np.linalg.slogdet(matrix) print(determinant)
Вихід
Висновок
Ця стаття навчила нас, як обчислити визначник матриці за допомогою Python numpy. на практиці. Ми також дізналися, як обчислити визначник матриці за допомогою numpy у Python.
Визначник - це скалярна величина, яку можна використовувати для представлення матриці в компактній формі, і вона має ряд додатків у різних галузях. і повертає визначник. Як альтернативу ми можемо використовувати функцію linalg.slogdet(), яка повертає знак і логарифм визначника, використовуючи метод LU-розкладання.
Статті з цієї тематики:
- Як порахувати проміжну суму в Google Sheets
- Як порахувати відсоток у Google Таблицях
- Обчислити число Пі, порахувавши пікселі
- Як обчислити факторіал числа
- Як розрахувати IP-адресу підмережі за допомогою Ipcalc
- Програма Python для розрахунку суми лівої діагоналі матриці
- Програма Python для розрахунку суми правої діагоналі матриці
- Програма Python для розрахунку симетричної різниці між двома списками
- Як розрахувати точність прогнозу логістичної регресії?
- Як визначити трасування матриці, використовуючи numpy в Python?
- Програма для розрахунку Судного дня за рік
- Як обчислити та побудувати графік похідної функції за допомогою Python – Matplotlib?
- Як розрахувати різницю між часом у різних стовпцях MySQL?
- Отримати різницю між датами та розрахувати зарплату за допомогою MySQL?
- Як розрахувати час у секундах у MySQL?
NumPy: матриці та операції над ними
У цьому ноутбуці зі сторонніх бібліотек нам знадобиться лише NumPy. Для зручності імпортуємо її під коротшим ім'ям:
import
numpy
as
np
1. Створення матриць
Наведемо кілька способів створення матриць NumPy.
Найпростіший спосіб – за допомогою функції numpy.array(list, dtype=None, . ).
Як перший аргумент їй треба передати об'єкт, що ітерується, елементами якого є інші об'єкти, що ітеруються, однакової довжини і містять дані однакового типу.
Другий аргумент є опціональним та визначає тип даних матриці. Його можна не ставити, тоді тип даних буде визначений із типу елементів першого аргументу. При заданні цього параметра буде зроблено спробу наведення типів.
Наприклад, матрицю зі списку списків цілих чисел можна створити так:
a
=
np.array([1,
2,
3])
# Створюємо одновимірний масив
print(type(a))
# Prints ""
print(a.shape)
# Prints "(3,)" - кортеж з розмірами
print(a[0],
a[1],
a[2])
# Prints "1 2 3"
a[0]
=
5
# Змінюємо значення елемента масиву
print(a)
# Prints "[5, 2, 3]"
b
=
np.array([[1,2,3],[4,5,6]])
# Створюємо двомірний масив
print(b.shape)
# Prints "(2, 3)"
print(b[0,
0],
b[0,
1],
b[1,
0])
# Prints "1 2 4"
print(np.arange(1,
5))
#Створює вектор з елементами від 1 до 4
(3,) 1 2 3 [5 2 3] (2, 3) 1 2 4 [1 2 3 4]
matrix
=
np.array([[1,
2,
3],
[2,
5,
6],
[6,
7,
4]])
print
("Матриця:\n",
matrix)
Матриця: [[1 2 3] [2 5 6] [6 7 4]]
Другий спосіб створення – за допомогою вбудованих функцій numpy.eye(N, M=None, . ), numpy.zeros(shape, . ), numpy.ones(shape, . ).
Перша функція створює одиничну матрицю розміру N×M ; якщо M не заданий, то M = N .
Друга і третя функції створюють матриці, що складаються з нулів або одиниць відповідно. Як перший аргумент необхідно задати розмірність масиву - кортеж цілих чисел. У двовимірному випадку це набір двох чисел: кількість рядків і стовпців матриці.
Приклади:
b
=
np.eye(5)
print
("Поодинока матриця:\n",
b)
Поодинока матриця: [[1. 0. 0. 0. 0.] [0. 1. 0. 0. 0.] [0. 0. 1. 0. 0.] [0. 0. 0. 1. 0.] [0. 0. 0. 0. 1.]]
c
=
np.ones((7,
5))
print
("Матриця, що складається з одних одиниць:\n",
c)
Матриця, що з одних одиниць: [[1. 1. 1. 1. 1.] [1. 1. 1. 1. 1.] [1. 1. 1. 1. 1.] [1. 1. 1. 1. 1.] [1. 1. 1. 1. 1.] [1. 1. 1. 1. 1.] [1. 1. 1. 1. 1.]]
d
=
np.full((2,2),
7)
# Створює матрицю (1, 2) заповнену заданим значенням
print(d)
# Prints "[[ 7. 7.]
# [ 7. 7.]]"
e
=
np.random.random((2,2))
# Створює одиничну матрицю (2, 2) заповнену випадковими числами (0, 1)
print(e)
# Might print "[[ 0.91940167 0.08143941]
# [ 0.68744134 0.87236687]]"
[[7 7] [7 7]] [[0.25744383 0.48056466] [0.13767881 0.40578168]]
Зверніть увагу: розмірність масиву задається не двома аргументами функції, а одним кортежем!
Ось так - np.ones(7, 5) — створити масив не вдасться, оскільки функції як параметр shape передається 7, а не кортеж (7, 5).
І, нарешті, третій спосіб – за допомогою функції numpy.arange([start, ]stop, [step, ], . )яка створює одновимірний масив послідовних чисел з проміжку [Start, stop) із заданим кроком step, і методу
array.reshape(shape).
Параметр shape, Як і в попередньому прикладі, задає розмірність матриці (кортеж чисел). Логіка роботи методу зрозуміла з наступного прикладу:
v
=
np.arange(0,
24,
2)
print
("Вектор-стовпець:\n",
v)
Вектор-стовпець: [ 0 2 4 6 8 10 12 14 16 18 20 22]
d
=
v.reshape((3,
4))
print
("Матриця:\n",
d)
Матриця: [[ 0 2 4 6] [ 8 10 12 14] [16 18 20 22]]
Докладніше про те, як створювати масиви в NumPyдив. документацію.
2. Індексування
Для отримання елементів матриці можна використати кілька способів. Розглянемо найпростіші їх.
Для зручності нагадаємо, як виглядає матриця d:
Матриця: [[ 0 2 4 6] [ 8 10 12 14] [16 18 20 22]]
Елемент на перетині рядка i та стовпця j можна отримати за допомогою виразу array[i, j].
Зверніть увагу: рядки та стовпці нумеруються з нуля!
print
("Другий елемент третього рядка матриці:",
d[2,
1])
Другий елемент третього рядка матриці: 18
З матриці можна отримувати цілі рядки або стовпці за допомогою виразів array[i, :] або array[:, j] відповідно:
print
("Другий рядок матриці d:\n",
d[1,
:])
print
("Четвертий стовпець матриці d:\n",
d[:,
3])
Другий рядок матриці d: [8 10 12 14] Четвертий стовпець матриці d: [6 14 22]
Ще один спосіб отримання елементів – за допомогою виразу array[list1, list2], де list1, list2 - Деякі списки цілих чисел. При такій адресації одночасно проглядаються обидва списки та повертаються елементи матриці з відповідними координатами. Наступний приклад зрозуміліше пояснює механізм роботи такого індексування:
print
("Елементи матриці d з координатами (1, 2) та (0, 3):\n",
d[[1,
0],
[2,
3]])
Елементи матриці d з координатами (1, 2) та (0, 3): [12 6]
# Slicing
# Створимо матрицю (3, 4)
# [[ 1 2 3 4]
# [ 5 6 7 8]
# [ 9 10 11 12]]
a
=
np.array([[1,2,3,4],
[5,6,7,8],
[9,10,11,12]])
# Використовуючи слайсинг, ззаду матрицю b з елементів матриці а
# будемо використовувати 0 і 1 рядок, а так само 1 і 2 стовпці
# [[2 3]
# [6 7]]
b
=
a[:2,
1:3]
print(b)
# ЗВЕРНІТЬ УВАГУ НА ЗМІНУ ВИХОДУ МАТРИЦІ
print(a[0,
1])
# Prints "2"
b[0,
0]
=
77
# b[0, 0] is the same piece of data as a[0, 1]
print(a[0,
1])
# Prints "77"
# Integer array indexing
a
=
np.array([[1,2],
[3,
4],
[5,
6]])
print(a)
print()
# Приклад Integer array indexing
# В результаті вийде масив розмірності (3,)
# Зверніть увагу, що до коми йдуть індекси рядків, після - стовпців
print(a[[0,
1,
2],
[0,
1,
0]])
# Prints "[1 4 5]"
print()
# Інакше приклад можна записати так
print(np.array([a[0,
0],
a[1,
1],
a[2,
0]]))
# Prints "[1 4 5]"
[[1 2] [3 4] [5 6]] [1 4 5] [1 4 5]
Приклади використання слайсингу:
# Створимо новий маасив, з якого вибиратимемо елементи
a
=
np.array([[1,2,3],
[4,5,6],
[7,8,9],
[10,
11,
12]])
print(a)
# prints "array([[ 1, 2, 3],
# [ 4, 5, 6],
# [ 7, 8, 9],
# [10, 11, 12]])"
# Створимо масив індексів
b
=
np.array([0,
2,
0,
1])
# Виберемо з кожного рядка елемент із індексом з b (індекс стовпця береться з b)
print(a[np.arange(4),
b])
# Prints "[ 1 6 7 11]"
print()
# Додамо до цих елементів 10
a[np.arange(4),
b]
+=
10
print(a)
# prints "array([[11, 2, 3],
# [ 4, 5, 16],
# [17, 8, 9],
# [10, 21, 12]])
[[ 1 2 3] [ 4 5 6] [ 7 8 9] [10 11 12]] [ 1 6 7 11] [[11 2 3] [ 4 5 16] [17 8 9] [10 21 12]]
a
=
np.array([[1,2],
[3,
4],
[5,
6]])
bool_idx
=
(a
>
2)
# Знайдемо елементи матриці a, які більше 2
# В результаті отримаємо матрицю b такої ж розмірності, як і a
print(bool_idx)
# Prints "[[False False]
print()
# [ True True]
# [ True True]]"
# Скористаємося отриманим масивом для створення нового масиву, рангу 1
print(a[bool_idx])
# Prints "[3 4 5 6]"
# Аналогічно
print(a[a
>
2])
# Prints "[3 4 5 6]"
[[False False] [ True True] [ True True]] [3 4 5 6] [3 4 5 6]
#Пам'ятайте, що ви можете користуватися відразу кількома типами індексування
a
=
np.array([[1,2,3,4],
[5,6,7,8],
[9,10,11,12]])
row_r1
=
a[1,
:]
row_r2
=
a[1:2,
:]
print(row_r1,
row_r1.shape)
# Prints "[5 6 7 8] (4,)"
print(row_r2,
row_r2.shape)
# Prints "[[5 6 7 8]] (1, 4)"
[5 6 7 8] (4,) [[5 6 7 8]] (1, 4)
Докладніше про різні способи індексування в масивах див.
3. Вектори, векторні рядки та векторні стовпці
Наступні два способи завдання масиву здаються однаковими:
a
=
np.array([1,
2,
3])
b
=
np.array([[1],
[2],
[3]])
Однак, насправді це завдання одномірного масиву (тобто вектора) та двовимірного масиву:
print
("Вектор:\n",
a)
print
("Його розмірність:\n",
a.shape)
print
("Двовимірний масив:\n",
b)
print
("Його розмірність:\n",
b.shape)
Вектор: [1 2 3] Його розмірність: (3,) Двовимірний масив: [[1] [2] [3]] Його розмірність: (3, 1)
Зверніть увагу:
вектор (одномірний масив) та вектор-стовпець або вектор-рядок (двовимірні масиви) є різними об'єктами в NumPy, хоча математично задають той самий об'єкт. У разі одновимірного масиву кортеж shape складається з одного числа і має вигляд (n,), де n - Довжина вектора. У випадку двовимірних векторів shape є ще одна розмірність, рівна одиниці.
Найчастіше неважливо, яке уявлення використовувати, оскільки часто спрацьовує приведення типів. Але деякі операції не працюють для одновимірних масивів. Наприклад, транспонування (про нього йтиметься нижче):
print
("Вектор не змінився:\n",
a)
print
("Його розмірність також не змінилася:\n",
a.shape)
print
("Транспонований двовимірний масив:\n",
b)
print
("Його розмірність змінилася:\n",
b.shape)
Вектор не змінився: [1 2 3] Його розмірність також не змінилася: (3,) Транспонований двовимірний масив: [[1 2 3]] Його розмірність змінилася: (1, 3)
4. Datatypes
Всі елементи масиву numpy належать одному типу. У цьому плані масиви ближче до C, ніж до звичних листів пітону. Numpy має безліч гострих типів, придатних на вирішення більшості завдань.
x
=
np.array([1,
2])
# Автоматичний вибір типу
print(x.dtype)
# Prints "int64"
x
=
np.array([1.0,
2.0])
# Автоматичний вибір типу
print(x.dtype)
# Prints "float64"
x
=
np.array([1,
2],
dtype=np.int64)
# Примусове виставлення типу
print(x.dtype)
# Prints "int64"
int32 float64 int64
5. Математичні операції
До масивів (матриць) можна застосовувати відомі вам математичні операції. Слід розуміти, що при цьому елементи повинні мати схожі розмірності. Поведінка у разі не збігу розмірностей добре описана в документації numpy.
x
=
np.array([[1,2],[3,4]],
dtype=np.float64)
y
=
np.array([[5,6],[7,8]],
dtype=np.float64)
arr
=
np.array([1,
2])
# Додавання відбувається поелеметно
# [[ 6.0 8.0]
# [10.0 12.0]]
print(x
+
y)
print()
print(np.add(x,
y))
print('З числом')
print(x
+
1)
print('З масивом іншої розмірності')
print(x
+
arr)
[[6. 8.] [10. 12.]] [[ 6. 8.] [10. 12.]] З числом [[2. 3.] [4. 5.]] C масивом іншої розмірності [[2. 4.] [4. 6.]]
# Віднімання
print(x
-
y)
print(np.subtract(x,
y))
# Поділ
# [[ 0.2 0.33333333]
# [ 0.42857143 0.5 ]]
print(x
/
y)
print(np.divide(x,
y))
[[0.2 0.33333333] [0.42857143 0.5 ]] [[0.2 0.33333333] [0.42857143 0.5 ]]
# Інші функції
# [[ 1. 1.41421356]
# [ 1.73205081 2. ]]
print(np.sqrt(x))
[[1. 1.41421356] [1.73205081 2. ]]
6. Множення матриць та стовпців
Нагадування теорії. Операція множення визначено для двох матриць, таких що число стовпців першої дорівнює числу рядків другої.
Нехай матриці A і B такі, що A ∈ ℝ n×k і B ∈ ℝ k×m . Твором матриць A і B називається матриця C , така що cij = ∑ k
r = 1
airbrj , де cij - Елемент матриці C , що стоїть на перетині рядка з номером i та стовпця з номером j .
У NumPy добуток матриць обчислюється за допомогою функції numpy.dot(a, b, . ) або за допомогою методу
array1.dot(array2), де array1 і array2 - матриці, що перемножуються.
a
=
np.array([[1,
0],
[0,
1]])
b
=
np.array([[4,
1],
[2,
2]])
r1
=
np.dot(a,
b)
r2
=
a.dot(b)
print
("Матриця A:\n",
a)
print
("Матриця B:\n",
b)
print
("Результат множення функцією:\n",
r1)
print
("Результат множення методом:\n",
r2)
Матриця A: [[1 0] [0 1]] Матриця B: [[4 1] [2 2]] Результат множення функцією: [[4 1] [2 2]] Результат множення методом: [[4 1] [ 2 2]]
Матриці в NumPy можна множити і на вектори:
c
=
np.array([1,
2])
r3
=
b.dot(c)
print
("Матриця:\n",
b)
print
("Вектор:\n",
c)
print
("Результат множення:\n",
r3)
Матриця: [[4 1] [2 2]] Вектор: [1 2] Результат множення: [6 6]
Зверніть увагу: операція * робить над матрицями покоординатне множення, а не матричне!
print
("Матриця A:\n",
a)
print
("Матриця B:\n",
b)
print
("Результат покоординатного множення через операцію множення:\n",
r)
Матриця A: [[1 0] [0 1]] Матриця B: [[4 1] [2 2]] Результат покоординатного множення через операцію множення: [[4 0] [0 2]]
Докладніше про матричне множення в NumPy див. документацію.
7. Об'єднання масивів
Масиви можна об'єднувати. Є горизонтальне та вертикальне об'єднання.
a
=
np.floor(10*np.random.random((2,2)))
b
=
np.floor(10*np.random.random((2,2)))
print(a)
print(b)
print()
print(np.vstack((a,b)))
print()
print(np.hstack((a,b)))
[[4. 0.] [1. 4.]] [[9. 7.] [2. 6.]] [[4. 0.] [1. 4.] [9. 7.] [2. 6.]] [[4. 0. 9. 7.] [1. 4. 2. 6.]]
Масиви можна переформувати за допомогою методу, який задає новий багатовимірний масив. Наслідуючи такий приклад, ми переформатуємо одновимірний масив з десяти елементів у двовимірний масив, що складається з п'яти рядків і двох стовпців:
a
=
np.array(range(10),
float)
print(a)
print()
# Перетворимо на матрицю
a
=
a.reshape((5,
2))
print(a)
print()
# Повернемо назад
print(a.flatten())
# Інший варіант
print(a.reshape((-1)))
# Перетворимо на марицю (9, 1)
print(a.reshape((-1,
1)))
# Перетворимо на марицю (1, 9)
print(a.reshape((1,
-1)))
[0. 1. 2. 3. 4. 5. 6. 7. 8. 9.] [[0. 1.] [2. 3.] [4. 5.] [6. 7.] [8. 9.]] [0. 1. 2. 3. 4. 5. 6. 7. 8. 9.] [0. 1. 2. 3. 4. 5. 6. 7. 8. 9.] [[0.] [1.] [2.] [3.] [4.] [5.] [6.] [7.] [8.] [9.]] [[0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]]
Завдання: (Блок 1)
Завдання 1:
Вирішіть без використання циклів засобами NumPy (кожен пункт вирішується в 1-2 рядки)
- Створіть вектор з елементами від 12 до 42
- Створіть вектор з нулів довжини 12, але його п'ятий елемент повинен дорівнювати 1
- Створіть матрицю (3, 3), заповнену від 0 до 8
- Знайдіть усі позитивні числа в np.array([1,2,0,0,4,0])
- Помножте матрицю розмірності (5, 3) на (3, 2)
- Створіть матрицю (10, 10) так, щоб на кордоні були 0, а внтури 1
- Створіть рандомний вектор та відсортуйте його
- Який еквівалент функції enumerate для numpy масивів?
- *Створіть рандомний вектор і виконайте нормалізацію стовпців (з кожного стовпця відняти середнє цього стовпця, від кожного стовпця відняти sd цього стовпця)
- *Для заданого числа знайдіть найближчий до нього елемент у векторі
- *Знайдіть N найбільших значень у векторі
Завдання 2:
Даний тривимірний масив, що містить зображення, розміру (height, width, numChannels), а також вектор довжини numChannels. Скласти канали зображення із зазначеними вагами, і повернути результат у вигляді матриці розміру (height, width). Вважати реальне зображення можна за допомогою функції scipy.misc.imread (якщо зображення не у форматі png, установіть пакет pillow: conda install pillow).Перетворіть кольорове зображення на відтінки сірого, використовуючи коефіцієнти np.array([0.299, 0.587, 0.114]).
8. Транспонування матриць
Нагадування теорії.
Транспонованою матрицею
A
T називається матриця, отримана з вихідної матриці A заміною рядків на стовпці. Формально: елементи матриці A
T визначаються як a
T
ij = aji , де a
T
ij - Елемент матриці A
T , що стоїть на перетині рядка з номером i та стовпця з номером j .
У NumPy транспонована матриця обчислюється за допомогою функції numpy.transpose() або за допомогою методу
array.T, де array - Необхідний двовимірний масив.
a
=
np.array([[1,
2],
[3,
4]])
b
=
np.transpose(a)
c
=
a.T
print
("Матриця:\n",
a)
print
("Транспонування функцією:\n",
b)
print
("Транспонування методом:\n",
c)
Матриця: [[1 2] [3 4]] Транспонування функцією: [[1 3] [2 4]] Транспонування методом: [[1 3] [2 4]]
У наступних розділах активно використовується модуль numpy.linalgреалізує деякі додатки лінійної алгебри. Докладніше про функції, описані нижче, та різні інші функції цього модуля можна переглянути в його документації.
9. Визначник матриці
Нагадування теорії. Для квадратних матриць існує поняття визначника.
Нехай A - Квадратна матриця. Визначником (або детермінантом) матриці A ∈ ℝ n×n назвемо число
detA = ∑ α1, α2, …, αn ( − 1) N(α1, α2, …, αn) ⋅aα11⋅⋅⋅aαnn,
де α1, α2, …, αn - Перестановка чисел від 1 до n , N(α1, α2, …, αn) - Число інверсій в перестановці, підсумовування ведеться по всіх можливих перестановках довжини n .
Не варто засмучуватись, якщо це визначення зрозуміле не до кінця — надалі в такому вигляді воно не знадобиться.
Наприклад, для матриці розміру 2×2 виходить:
det ⎛ ⎜ ⎝ a11
a12
a21
a22 ⎞ ⎟ ⎠ = a11a22 − a12a21
Обчислення визначника матриці за визначенням вимагає порядку n! операцій, тому розроблено методи, які дозволяють обчислювати його швидко та ефективно.
У NumPy визначник матриці обчислюється за допомогою функції numpy.linalg.det(a), де a - Вихідна матриця.
a
=
np.array([[1,
2,
1],
[1,
1,
4],
[2,
3,
6]],
dtype=np.float32)
det
=
np.linalg.det(a)
print
("Матриця:\n",
a)
print
("Визначник:\n",
det)
Матриця: [[1. 2. 1.] [1. 1. 4.] [2. 3. 6.]] Визначник: -1.0
Розглянемо одну цікаву властивість визначника. Нехай у нас є паралелограм з кутами в точках (0, 0), (c, d), (a + c, b + d), (a, b) (кути дано в порядку обходу за годинниковою стрілкою). Тоді площу цього паралелограма можна обчислити як модуль визначника матриці ⎛ ⎜ ⎝ a
c
b
d ⎞ ⎟ ⎠ . Подібним чином можна виразити об'єм паралелепіпеда через визначник матриці розміру 3×3 .
10. Ранг матриці
Нагадування теорії.
Рангом матриці
A називається максимальне число лінійно незалежних рядків (стовпців) цієї матриці.
У NumPy ранг матриці обчислюється за допомогою функції numpy.linalg.matrix_rank(M, tol=None), де M - матриця, tol - Параметр, який відповідає за деяку точність обчислення. У найпростішому випадку можна його не ставити, і функція сама визначить потрібне значення цього параметра.
a
=
np.array([[1,
2,
3],
[1,
1,
1],
[2,
2,
2]])
r
=
np.linalg.matrix_rank(a)
print
("Матриця:\n",
a)
print
("Ранг матриці:",
r)
Матриця: [[1 2 3] [1 1 1] [2 2 2]] Ранг матриці: 2
За допомогою обчислення рангу матриці можна перевіряти лінійну незалежність векторної системи.
Допустимо, у нас є кілька векторів. Складемо з них матрицю, де наші вектори будуть рядками. Зрозуміло, що вектори лінійно незалежні і тоді, коли ранг отриманої матриці збігається з числом векторів. Наведемо приклад:
a
=
np.array([1,
2,
3])
b
=
np.array([1,
1,
1])
c
=
np.array([2,
3,
5])
m
=
np.array([a,
b,
c])
print
(np.linalg.matrix_rank(m)
==
m.shape[0])
11. Системи лінійних рівнянь
Нагадування теорії.
Системою лінійних рівнянь алгебри називається система виду Ax = b , де A ∈ ℝ n×m , x ∈ ℝ m×1 , b ∈ ℝ n×1. У разі квадратної невиродженої матриці A рішення системи єдине.
У NumPy вирішення такої системи можна знайти за допомогою функції numpy.linalg.solve(a, b), де перший аргумент - матриця A , другий - стовпець b .
a
=
np.array([[3,
1],
[1,
2]])
b
=
np.array([9,
8])
x
=
np.linalg.solve(a,
b)
print
("Матриця A:\n",
a)
print
("Вектор b:\n",
b)
print
("Рішення системи:\n",
x)
Матриця A: [[3 1] [1 2]] Вектор b: [9 8] Рішення системи: [2. 3.]
Переконаємося, що вектор x дійсно є рішенням системи:
Трапляються випадки, коли рішення системи не існує. Але хотілося б все одно "вирішити" таку систему. Логічним здається шукати такий вектор x , який мінімізує вираз ‖ Ax − b ‖ 2 — так ми наблизимо вираз Ax до b .
У NumPy таке псевдорішення можна шукати за допомогою функції numpy.linalg.lstsq(a, b, . ), де перші два аргументи такі ж, як і для функції numpy.linalg.solve(). Крім рішення, функція повертає ще три значення, які нам зараз не знадобляться.
a
=
np.array([[0,
1],
[1,
1],
[2,
1],
[3,
1]])
b
=
np.array([-1,
0.2,
0.9,
2.1])
x,
res,
r,
s
=
np.linalg.lstsq(a,
b,
rcond=None)
print
("Матриця A:\n",
a)
print
("Вектор b:\n",
b)
print
("Пседорішення системи:\n",
x)
Матриця A: [[0 1] [1 1] [2 1] [3 1]] Вектор b: [-1. 0.2 0.9 2.1] Псевдорішення системи: [1. -0.95]
12. Звернення матриць
Нагадування теорії. Для квадратних невироджених матриць визначено поняття зворотній матриці.
Нехай A - Квадратна невироджена матриця. Матриця A − 1 називається зворотною матрицею до A , якщо
де I - Поодинока матриця.
У NumPy обернені матриці обчислюються за допомогою функції numpy.linalg.inv(a), де a - Вихідна матриця.
a
=
np.array([[1,
2,
1],
[1,
1,
4],
[2,
3,
6]],
dtype=np.float32)
b
=
np.linalg.inv(a)
print
("Матриця A:\n",
a)
print
("Зворотна матриця до A:\n",
b)
print
("Твор A на зворотний має бути одиничною:\n",
a.dot(b))
Матриця A: [[1. 2. 1.] [1. 1. 4.] [2. 3. 6.]] Зворотна матриця до A: [[ 6. 9. -7.] [-2. -4. 3.] [-1. -1. 1.]] Твір A на зворотний має бути одиничною: [[1. 0. 0.] [0. 1. 0.] [0. 0. 1.]]
13. Власні числа та власні вектори матриці
Нагадування теорії. Для квадратних матриць визначено поняття власного вектора і власного числа.
Нехай A — квадратна матриця та A ∈ ℝ n×n . Власним вектором матриці A називається такий ненульовий вектор x ∈ ℝ n , що для деякого λ ∈ ℝ виконується рівність Ax = λx . При цьому λ називається власним числом матриці A . Власні числа та власні вектори матриці відіграють важливу роль у теорії лінійної алгебри та її практичних додатках.
У NumPy власні числа та власні вектори матриці обчислюються за допомогою функції numpy.linalg.eig(a), де a - Вихідна матриця. Як результат ця функція видає одновимірний масив w власних чисел та двовимірний масив v, в якому по стовпцях записані власні вектори, так що вектор v[:, i] відповідає власному числу w[i].
a
=
np.array([[-1,
-6],
[2,
6]])
w,
v
=
np.linalg.eig(a)
print
("Матриця A:\n",
a)
print
("Власні числа:\n",
w)
print
("Власні вектори:\n",
v)
Матриця A: [[-1 -6] [2 6]] Власні числа: [2. 3.] Власні вектори: [[-0.89442719 0.83205029] [ 0.4472136 -0.5547002 ]]
Зверніть увагу: у речової матриці власні значення або власні вектори можуть бути комплексними.
14. Відстань між векторами
Згадаймо деякі норми, які можна запровадити у просторі ℝ n , і розглянемо, за допомогою яких бібліотек та функцій їх можна обчислювати в NumPy.
p-норма
p-норма (норма Гельдера) для вектора x = (x1, …, xn) ∈ ℝ n обчислюється за такою формулою:
‖ x ‖ p = ( n ∑ i = 1 | xi | p ) 1 ⁄ p , p ≥ 1.
У окремих випадках при: * p = 1 отримуємо ℓ1 норму * p = 2 отримуємо ℓ2 норму
Далі нам знадобиться модуль numpy.linalgреалізує деякі додатки лінійної алгебри. Для обчислення різних норм ми використовуємо функцію numpy.linalg.norm(x, ord=None, . ), де x - Вихідний вектор, ord - Параметр, що визначає норму (ми розглянемо два варіанти його значень - 1 і 2). Імпортуємо цю функцію:
from
numpy.linalg
import
norm
ℓ1 норма
ℓ1 норма (також відома як манхеттенська відстань) для вектора x = (x1, …, xn) ∈ ℝ n обчислюється за такою формулою:
Їй у функції numpy.linalg.norm(x, ord=None, . ) відповідає параметр ord=1.
a
=
np.array([1,
2,
-3])
print('Вектор a:',
a)
print('L1 норма вектора a:\n',
norm(a,
ord=1))
L1 норма вектора a: 6.0
ℓ2 норма
ℓ2 норма (також відома як евклідова норма) для вектора x = (x1, …, xn) ∈ ℝ n обчислюється за такою формулою:
Їй у функції numpy.linalg.norm(x, ord=None, . ) відповідає параметр ord=2.
print
('L2 норма вектора a:\n',
norm(a,
ord=2))
L2 норма вектора a: 3.7416573867739413
Докладніше про те, які ще норми (у тому числі матричні) можна обчислити, див.
15. Відстань між векторами
Для двох векторів x = (x1, …, xn) ∈ ℝ n і y = (y1, …, yn) ∈ ℝ n
ℓ1 і ℓ2 відстані обчислюються за такими формулами відповідно:
ρ1 ( x, y ) = ‖ x − y ‖ 1 = n ∑ i = 1 | xi − yi |
ρ2 ( x, y ) = ‖ x − y ‖ 2 = √ ( n ∑ i = 1 ( xi − yi ) 2 ) .
a
=
np.array([1,
2,
-3])
b
=
np.array([-4,
3,
8])
print
('Вектор a:',
a)
print
('Вектор b:',
b)
Вектор a: [ 1 2 -3] Вектор b: [-4 3 8]
print
('L1 відстань між векторами a та b:\n',
norm(a
-
b,
ord=1))
print
('L2 відстань між векторами a та b:\n',
norm(a
-
b,
ord=2))
L1 відстань між векторами a та b: 17.0 L2 відстань між векторами a та b: 12.12435565298214
16. Скалярний твір та кут між векторами
a
=
np.array([0,
5,
-1])
b
=
np.array([-4,
9,
3])
print
('Вектор a:',
a)
print
('Вектор b:',
b)
Вектор a: [ 0 5 -1] Вектор b: [-4 9 3]
Скалярний твір у просторі ℝ n для двох векторів x = (x1, …, xn) та y = (y1, …, yn) визначається як:
Довжина вектора x = (x1, …, xn) ∈ ℝ n називається квадратний корінь із скалярного твору, тобто довжина дорівнює евклідовій нормі вектора:
| x | = √ ( ⟨x, x⟩ ) = √ ( n ∑ i = 1
x 2 i ) = ‖ x ‖ 2.
Тепер, коли ми знаємо відстань між двома ненульовими векторами та їх довжини, ми можемо обчислити кут між ними через скалярний твір:
⟨x, y⟩ = | x | |y| cos (α) ⟹ cos(α) = ( ⟨x, y⟩ )/( | x | |y| ) ,
де α ∈ [0, π] - кут між векторами x і y .
cos_angle
=
np.dot(a,
b)
/
norm(a)
/
norm(b)
print
('Косинус кута між a та b:',
cos_angle)
print
('Сам кут:',
np.arccos(cos_angle))
Косинус кута між a і b: 0.8000362836474323 Сам кут: 0.6434406336093618
17. Комплексні числа у пітоні
Нагадування теорії.
Комплексними числами називаються числа виду x + iy , де x і y - Речові числа, а i - уявна одиниця (величина, для якої виконується рівність i 2 = − 1). Безліч всіх комплексних чисел позначається буквою ℂ (докладніше для комплексних чисел див. вікіпедію).
У пітоні комплескні числа можна задати так (j позначає уявну одиницю):
print
("Комплексне число a:\n",
a)
print
("Комплексне число b:\n",
b)
Комплексне число a: (3+2j) Комплексне число b: 1j
З комплексними числами в пітоні можна проводити базові арифметичні операції так само, як і з речовими числами:
c
=
a
*
a
d
=
a
/
(4
-
5j)
print
("Комплексне число з:\n",
c)
print
("Комплексне число d:\n",
d)
Комплексне число c: (5+12j) Комплексне число d: (0.0487804878048781+0.5609756097560976j)
Завдання: (Блок 2)
Завдання 3:
Розглянемо складну математичну функцію на відрізку [1, 15]:
f(x) = sin(x/5) * exp(x / 10) + 5 * exp(-x / 2)
Вона може описувати, наприклад, залежність оцінок, які виставляють певному ґатунку вина експерти, залежно від віку цього вина. Ми хочемо наблизити складну залежність за допомогою функції певного сімейства. У цьому завданні ми наближатимемо вказану функцію за допомогою багаточленів.
Як відомо, багаточлен ступеня n (тобто w0 + w1x + w2x 2 + … + wnx
n ) однозначно визначається будь-якими n + 1 різними точками, якими він проходить. Це означає, що його коефіцієнти w0 , … wn можна визначити з наступної системи лінійних рівнянь:
де через x1, . xn, xn + 1 позначені точки, через які проходить багаточлен, а через f(x1), . f(xn), f(xn + 1) - значення, які він повинен набувати в цих точках.
Скористаємося описаним властивістю, і знаходитимемо наближення функції многочленом, вирішуючи систему лінійних рівнянь.
- Сформуйте систему лінійних рівнянь (тобто задайте матрицю коефіцієнтів A та вільний вектор b) для багаточлена першого ступеня, який має збігатися з функцією f у точках 1 та 15. Розв'яжіть цю систему за допомогою функції scipy.linalg.solve. Намалюйте функцію f та отриманий багаточлен. Чи добре він наближає вихідну функцію?
- Повторіть ті самі кроки для багаточлена другого ступеня, який збігається з функцією f у точках 1, 8 та 15. Чи покращилася якість апроксимації?
- Повторіть ті самі кроки для багаточлена третього ступеня, який збігається з функцією f у точках 1, 4, 10 та 15. Чи добре він апроксимує функцію? Коефіцієнти даного многочлена (чотири числа у такому порядку: w_0, w_1, w_2, w_3) є відповіддю завдання.Округлювати коефіцієнти не обов'язково, але за бажання можете зробити округлення до другого знака (тобто до числа виду 0.42)
Сайт збудований з використанням Pelican. За основу оформлення взято тему від Smashing Magazine. Вихідні тексти програм, наведені на цьому сайті, поширюються під ліцензією GPLv3, решта матеріалів сайту поширюється під ліцензією CC-BY.