Wejdź do matrixa, czyli wprowadzenie do macierzy

Chcesz zostać data scientist? Nie jest to łatwa sprawa, a i nauki przed Tobą wiele. Oprócz doskonalenia programowania, projektowania algorytmów i postępowania z danymi musisz zrobić jeszcze jedną rzecz – poznać matematykę. Przygodę z matematyką dla zainteresowanych uczeniem maszynowym warto rozpocząć od algebry liniowej – i tak właśnie zrobimy.

Układ równań z życia wzięty

Jeśli czytasz regularnie mojego bloga, to pewnie zgodzisz się z tezą, że z matematyką mamy do czynienia praktycznie wszędzie. W tej czy innej formie. Oprócz wielu ciekawych zastosowań w życiu codziennym, sporcie, grach i technice, matematykę wykorzystuje się również w przemyśle. Przykład? Proszę bardzo. Wyobraźmy sobie przez chwilę, że zajmujemy się logistyką w pewnej fabryce. Oczywiście nie jest ważne co produkujemy czy sprzedajemy – możesz tutaj pomyśleć o dowolnym artykule. Załóżmy, że na końcu naszej linii produkcyjnej chcemy uzyskać trzy produkty – Produkt Nr 1, Produkt Nr 2 i Produkt nr 3 (chociaż możesz oczywiście nazwać je jak tylko chcesz).

Do wyprodukowania każdego z wymienionych artykułów potrzebujemy użyć trzech składników – w różnych proporcjach. Poniżej krótki opis składowych:

ProduktySkładnik 1Składnik 2Składnik 3
Produkt 1321
Produkt 2145
Produkt 3118

Jak czytać tą tabelkę? Do wyprodukowania Produktu nr 1 potrzeba nam 3 jednostek Składnika 1, ponadto 2 jednostki Składnika 2 oraz 1 jednostkę Składnika 3. Podobnie możemy odczytać dane z tabeli dla Produktów 2 i 3.

Oczywistym jest, że Twój magazyn ma pewne ograniczenia. Jednym z wielu, ale przy tym bardzo znaczącym jest dostępność zasobów. Sprawdzasz więc stany magazynowe i wiesz, że “na stanie” jest dokładnie 20 jednostek Składnika 1, także 25 jednostek Składnika 2 oraz 40 jednostek Składnika 3. Naszym zadaniem jest wyznaczenie optymalnego planu produkcji tzn. określenie ile jednostek finalnych produktów jesteśmy w stanie wyprodukować, żeby na stanie zostało jak najmniej towaru – najlepiej w ogóle. Na pierwszy rzut oka widać, że produkty i składniki są połączone pewną siecią współzależności. Przykładowo z obecnymi stanami magazynowymi nie wyprodukujemy więcej niż 5 jednostek Produktu Nr 3 (na każdą jednostkę Produktu nr 3 potrzeba nam 8 jednostek Składnika 3, a na stanie mamy jedynie 40 sztuk.) itd.

Opisane powyżej zależności możemy “ubrać” w układ równań. Jeżeli przez x_{1}, x_{2}, x_{3} oznaczymy szukane ilości produktów, które możemy wyprodukować, to możemy zapisać, że:

\begin{cases} 3x_{1} + x_{2} + x_{3} = 20 \\ 2x_{1} + 4x_{2} + x_{3} = 25\\ x_{1} + 5x_{2} + 8x_{3} = 40 \end{cases}

W każdym wierszu/równaniu współczynniki stojące przy poszczególnych zmiennych x oznaczają ilość każdego ze składników potrzebną do produkcji, a liczba po prawej stronie to stan magazynowy. Na przykład w pierwszym wierszu widzimy, że do produkcji Produktu 1 potrzeba 3 jednostki Składnika 1, do produkcji Produktu 2 wystarczy 1 jednostka Składnika 1 i dla Produktu 3 również 1 jednostka Składnika 1 będzie wystarczająca.

Pewnie co bardziej niecierpliwi z Was przystąpią zaraz do poszukiwania rozwiązań. Nie będziemy jednak zajmować się tym teraz (a dla dociekliwych powiem tylko, że optymalny plan produkcji opisanej układem zakłada wytworzenie \frac{115}{24}j. Produktu 1, \frac{235}{72}j. Produktu 2 oraz \frac{85}{36}j. Produktu 3). To, co dzisiaj będzie nas interesować, to współczynniki stojące przy zmiennych x_{1}, x_{2}, x_{3} w każdym z równań układu. Przyznacie pewnie sami, że w przypadku większej liczby równań zapis “klamrowy” może być nieco nieczytelny. Dlatego dla uproszczenia przyjmujemy następującą konwencję notacji: współczynniki stojące przy każdej ze zmiennych oraz wyraz wolne zapisujemy w postaci wektorów. Nasze równania możemy zatem przedstawić w taki sposób:

x_{1} \begin{bmatrix} 3 \\ 2 \\ 1 \end{bmatrix} + x_{2} \begin{bmatrix} 1 \\ 4 \\ 5 \end{bmatrix} + x_{3}  \begin{bmatrix} 1 \\ 1 \\ 8 \end{bmatrix}  =  \begin{bmatrix} 20 \\ 25 \\ 40 \end{bmatrix}

Aby jeszcze uprościć zapis możemy przejść całkowicie na notację wspomnianą wcześniej:

\begin{bmatrix} 3 & 1 & 1 \\ 2 & 4 & 1 \\1 & 5 & 8  \end{bmatrix} \begin{bmatrix} x_{1} \\ x_{2} \\ x_{3}  \end{bmatrix} = \begin{bmatrix} 20 \\ 25 \\ 40 \end{bmatrix}

Taki zapis sprowadza nas na nowe matematyczne tory – wchodzimy na ścieżkę … macierzy.

Zadanie logistyczne opisane w tym podrozdziale można oczywiście uogólnić – wtedy zakładamy, że mamy n towarów, z których każdy jest wytwarzany z m różnych składników. Przy tym nic nie stoi na przeszkodzie, żeby n \ne m. Jedynym co nas ogranicza jest to, że wypadałoby, żeby n oraz m były liczbami naturalnymi.


Czym jest macierz?

Macierze zajmują centralną pozycję w dziedzinie matematyki zwanej algebrą liniową. Ale czym właściwie są? Wyjaśni to poniższa definicja.

Załóżmy, że m oraz n są liczbami naturalnymi. Macierzą A nazywamy układ m \cdot n liczb zapisanych w postaci prostokątnej tablicy. Elementami macierzy nazywamy liczby a_{ij} gdzie i \in 1,2, \dots m oraz j = 1,2, \dots n. Macierz A możemy zaprezentować w poniższej postaci:

A = \begin{bmatrix} a_{11} & a_{12} & \cdots & a_{1n} \\ a_{21} & a_{22} & \cdots & a_{2n} \\ \cdots  & \cdots & \cdots & \cdots \\ a_{m1} & a_{m2} & \cdots & a_{mn} \end{bmatrix}, a_{ij} \in \ \mathbb{R}

Poszczególne macierze składające się z elementów o tym samym pierwszym indeksie i nazywamy wierszami, a te składające się z elementów o tym samym drugim indeksie jkolumnami. Symbolem m \times n oznaczamy rozmiar macierzy. Zatem macierz o 3 wierszach i 4 kolumnach jest rozmiaru 3 \times 4. Zbiór wszystkich macierzy o elementach będących liczbami rzeczywistymi rozmiaru m \times n oznaczamy symbolem \mathbb{R}^{m \times n}. W naszym przypadku A \in  \mathbb{R}^{m \times n}.

Macierze podobnie jak większość innych obiektów matematycznych można ze sobą “łączyć” na dwa sposoby: przez dodawanie i mnożenie. W tym wpisie pokażę obydwa działania. W pierwszej kolejności oczywiście zdefiniuję najogólniej czym jest dodawanie macierzy.

Dodawanie macierzy

Zakładamy, że mamy dwie macierze o tym samym rozmiarze m \times n i oznaczone są jako A i B. Zgrabny matematyczny zapis powie nam, że A \in  \mathbb{R}^{m \times n} oraz B \in  \mathbb{R}^{m \times n}.

Suma dwóch macierzy to również macierz o tym samym rozmiarze co A oraz B. Oznaczamy ją A + B oraz definiujemy w następujący sposób:

A + B :=  \begin{bmatrix} a_{11} & a_{12} & \cdots & a_{1n} \\ a_{21} & a_{22} & \cdots & a_{2n} \\ \cdots  & \cdots & \cdots & \cdots \\ a_{m1} & a_{m2} & \cdots & a_{mn} \end{bmatrix} +  \begin{bmatrix} b_{11} & b_{12} & \cdots & b_{1n} \\ b_{21} & b_{22} & \cdots & b_{2n} \\ \cdots  & \cdots & \cdots & \cdots \\ b_{m1} & b_{m2} & \cdots & b_{mn} \end{bmatrix} =  \begin{bmatrix} a_{11} + b_{11}  & a_{12} +  b_{12}  & \cdots & a_{1n} +  b_{1n}  \\ a_{21} +  b_{21}  & a_{22} + b_{22} & \cdots & a_{2n}+ b_{2n}  \\ \cdots  & \cdots & \cdots & \cdots \\ a_{m1} +  b_{m1}  & a_{m2} +  b_{m2}  & \cdots & a_{mn} +  b_{mn}  \end{bmatrix}

Najogólniej rzecz biorąc bierzemy dwie macierze o tym samym rozmiarze, patrzymy na ich elementy i dodajemy każdy element macierzy pierwszej do jego odpowiednika w macierzy drugiej.

Sprawdźmy czy dobrze rozumiesz jak działa dodawanie macierzy.

Weźmy dwie macierze o rozmiarze 3 \times 4 zatem mamy trzy wiersze i cztery kolumny.

A =   \begin{bmatrix} 1 & 2 & 3 & 4 \\ 5 & 6 & 7 & 8 \\ 0  & 1 & 2 & 3 \end{bmatrix}, B =  \begin{bmatrix} 0 & 1 & 0 & 2 \\ 3 & 0 & 4 & 0 \\ 0  & 5 & 0 & 6 \end{bmatrix} .

Wówczas A + B =   \begin{bmatrix} 1 + 0 & 2 + 1 & 3 + 0 & 4 + 2 \\ 5+3 & 6+0 & 7+4 & 8+0 \\ 0 + 0  & 1+5 & 2+0 & 3+6 \end{bmatrix} =   \begin{bmatrix} 1 & 3 & 3 & 6 \\ 8 & 6 & 11 & 8 \\ 0  & 6 & 2 & 9 \end{bmatrix}

Proste prawda?

Mnożenie macierzy

Jeśli przeczytałeś poprzedni akapit dotyczący dodawania macierzy, to pewne wydaje Ci się, że mnożenie dwóch macierzy będzie przebiegać podobnie. No cóż… tym razem zaskoczysz się. Mnożenie macierzy nie polega na mnożeniu przez siebie ich odpowiednich elementów. Jest to działanie troszkę bardziej skomplikowane.

Zacznijmy od tego, że nie każde dwie macierze da się przez siebie pomnożyć. Kolejne zaskoczenie… Przypomnę, że mimo wszystko macierze to abstrakcyjne byty, które nie zachowują wszystkich własności charakterystycznych na przykład dla liczb. Pewne prawa działają i tu i tu, inne są typowe dla liczb, a przecież są też kwestie, w których macierze są wyjątkowe. Po drugie, tak jak napisałem mnożenie macierzy nie polega na prostym mnożeniu przez siebie elementów. Na marginesie, nawet takie działanie zostało zdefiniowane i nazwane. Zainteresowanych zachęcam do poczytania na przykład na Wikipedii o iloczynie Hadamarda. Link na końcu artykułu.

Załóżmy, że A \in  \mathbb{R}^{m \times n} oraz B \in  \mathbb{R}^{n \times k}. Oczywiście nie zakładamy, że m \ne n \ne k. Nic nie stoi na przeszkodzie, aby któreś z rozmiarów były równe innym. Standardowo wyrazy macierzy A będziemy oznaczać jako a_{ij} i macierzy B jako b_{ij}. Przy takich oznaczeniach:

Ogólna zasada dotycząca mnożenia macierzy mówi, że pomnożyć można takie macierze, w których liczba kolumn pierwszej z nich (stojącej z lewej strony mnożenia) odpowiada liczbie wierszy drugiej z nich (stojącej z prawej strony mnożenia). W szczególności zawsze możemy mnożyć przez siebie dwie macierze kwadratowe (czyli takie, które mają taką samą liczbę kolumn i wierszy) takich samych rozmiarów. OK – wiemy już jaki warunek koniecznie muszą spełniać nasze macierze – zdefiniujmy wreszcie to magiczne działanie mnożenia.

A \cdot B = C, gdzie C \in  \mathbb{R}^{m \times k}

oraz poszczególne wyrazy macierzy C są równe:

    \[c_{ij} = \sum_{l = 1}^{n} a_{il}\cdot b_{lj}\]

dla i =1, 2, ..., m oraz j = 1, 2, ..., k

Może wygląda to jak hieroglify dla osób mniej wprawionych w meandry matematyki. Zdecydowanie łatwiej pokazać to na konkretnym przykładzie.

Dwie proste macierze: A =  \begin{bmatrix} 1 & 2 & 3 \\ 3 & 2 & 1 \end{bmatrix} \in  \mathbb{R}^{2 \times 3} oraz B =  \begin{bmatrix} 0 & 2 \\ 1 & -1 \\ 0 & 1 \end{bmatrix} \in  \mathbb{R}^{3 \times 2}. Po pierwsze zauważamy, że możliwe są obydwa mnożenia – zarówno AB (liczba kolumn A jest taka sama jak liczba wierszy B), jak i BA (liczba kolumn B jest równa liczbie wierszy A). Macierz, która powstanie jako wynik mnożenia AB będzie miała rozmiar równy 2 \times 2 – liczba wierszy macierzy A oraz liczba kolumn macierzy B.

AB =  \begin{bmatrix} 1 & 2 & 3 \\ 3 & 2 & 1 \end{bmatrix} \cdot  \begin{bmatrix} 0 & 2 \\ 1 & -1 \\ 0 & 1 \end{bmatrix} =  \begin{bmatrix} 1\cdot 0 + 2 \cdot 1 + 3 \cdot 0 & 1 \cdot 2 + 2 \cdot (-1) + 3 \cdot 1\\ 3 \cdot 0 + 2\cdot 1 + 1\cdot  0 &3\cdot 2 + 2 \cdot (-1) +  1 \cdot 1 \end{bmatrix}

Ostetecznie:

AB = C = \begin{bmatrix} 2 & 3 \\ 2 & 5 \end{bmatrix} \in    \mathbb{R}^{2 \times 2}

Praca domowa dla Ciebie – sprawdź jaki otrzymamy wynik mnożenia B\cdot A. Jaki rozmiar będzie miała nowopowstała macierz? Pisz w komentarzu.

Własności dodawania i mnożenia macierzy

Zaprezentowane przed chwilą działania na macierzach mają swoje własności podobne do działań na liczbach. Ogólnie rzecz biorąc tam gdzie takie działania są możliwe (tutaj w grę wchodzi oczywiście rozmiar macierzy) dodawanie i mnożenie macierzy są łączne i mnożenie jest rozdzielne względem dodawania.

  • Łączność
    Załóżmy, że mamy macierze A, B, C o rozmiarach A  \in    \mathbb{R}^{m \times n}, B  \in    \mathbb{R}^{n \times p} oraz C  \in  \mathbb{R}^{p \times q}. Wtedy zachodzi zależność:

        \[\left(AB\right) C = A\left( BC \right)\]

  • Rozdzielność mnożenia względem dodawania
    Zakładamy, że mamy macierze A, B, C, D o rozmiarach A,B  \in    \mathbb{R}^{m \times n} oraz C, D  \in    \mathbb{R}^{n \times p} Wtedy prawdziwe są zależności:

        \[\left(A+B\right) C = AC + BC\]


        \[A\left(C + D\right)= AC + AD\]

  • Mnożenie przez macierz identycznościową
    Dla dowolnej macierzy A  \in  \mathbb{R}^{m \times n} zachodzi:

        \[I_{m}A = AI_{n} =A\]

Wracając do ostatniej własności warto powiedzieć czym jest macierz identycznościowa. Najprościej mówiąc jest to macierz kwadratowa o dowolnej liczbie wierszy (i tylu kolumnach), która ma na przekątnej same jedynki, a na pozostałych elementach zera. Zerknij na zapis matematyczny (dla dowolnej liczby naturalnej n):

I_{n} =  \begin{bmatrix} 1 & 0 & \cdots & 0 \\ 0 & 1 & \cdots & 0 \\ \cdots  & \cdots & \cdots & \cdots \\ 0 & 0 & \cdots & 1 \end{bmatrix}

Widzieliśmy, że macierze to struktury w pewniej sposób rozszerzające pojęcie liczb rzeczywistych. Macierz jednostkowa jest również próbą rozszerzenia liczby 1 na świat macierzy. Ostatnia własność mówi o tym, że mnożenie dowolnej macierzy przez zgodną z jej wymiarem macierz identycznościową nie zmienia macierzy wyjściowej. Podobna sytuacja ma oczywiście miejsce z liczbą 1 – przemnożenie dowolonej liczby rzeczywistej przez 1 nie zmienia jej.

Kolejne ciekawe własności opiszę przy okazji pojęć odwracania i transponowania macierzy, ale to już w kolejnym wpisie, żeby nie przeładować Was wiedzą.

Dodawanie i mnożenie macierzy w Pythonie

Pokazane dzisiaj pojęcia możemy łatwo zaimplementować w Pythonie. Do obliczeń m.in. na macierzach służy biblioteka numpy.

Po wczytaniu biblioteki poleceniem import definiujemy i wyświetlamy macierz A:

import numpy as np                          

A = np.array([[1,2,3],
              [4,5,6]])

print (A)

Dodajemy definicję macierzy B oraz wykonujemy proste sumowanie (A+B):

import numpy as np                          

A = np.array([[1,2,3],
              [4,5,6]])

B= np.array([[0,1,2],
              [7,8.9]])

print (A+B)

Podobnie możemy wykonać mnożenie macierzy – oczywiście wcześniej sprawdzamy, czy wymiary macierzy się zgadzają:

import numpy as np                          

A = np.array([[1,2,3],
              [4,5,6]])

B= np.array([[0,1]
              [2,3],
              [4,5]])

print (A @ B)

Zakończenie

Dzisiejszy wpis pełen był dość elementarnej wiedzy na temat macierzy. Dopiero zaczynam na blogu ten temat, więc nie chodziło mi o to, żeby nie zasypać Was wzorami. Macierze to całkiem fajne zagadnienie bo po pierwsze jest proste a po drugiej mimo swojej prostoty pozwala na wykorzystanie pewnych elementów matematycznego myślenia na poziomie abstrakcji. W kolejnych wpisach z tej serii będę dalej pokazywać świat macierzy stopniowo wprowadzając trudniejsze i ciekawsze ich własności. Tym samym – do następnego razu!

Daj znać w komentarzu czy podoba Ci się taki sposób przekazywania wiedzy. A może chcesz więcej teorii i dowodów albo temat macierzy nie zainteresował Cię… Napisz komentarz, skreśl kilka słów do mnie na krzysiek@prostamatematyka.pl. Czekam na Twoją opinię!

Jeśli zainteresował Cię ten temat o chcesz zapisać się na moją listę mailową to użyj poniższego formularza. Za zapis – jest prezent.

Linki

1 == Iloczyn Hadamarda na Wikipedii
2 == Rozwiązywanie układów równań on-line
3 == Mathematics for Machine Learning – darmowy ebook

Polub nas na:
error

6 komentarzy

  1. Bardzo fajny wpis Krzyśku. Taka forma jest bardzo dobra.

    Odpowiedź do twojego zdania to [[6,4,2][-2,0,2][3,2,1]]. Dawno się nie uczyłem macierzy ale jakoś zrozumiałem w jakiej kolejności mnożyć co przez co na podstawie twojego przykładu. Zauważyłem też że AB != BA. Takie przekazywanie elementarnej wiedzy bardzo mi się podoba.

    Więcej takich wpisów :-).

    Pozdrawiam.

    1. Author

      Dzięki Mateusz ! Postaram się umieszczać więcej wpisów w takiej formie. W planach mam przerobienie w ten sposób zagadnień z algebry liniowej: macierzy, wektorów, przestrzeni liniowych. A co dalej to zobaczymy 🙂

      1. Bardzo fajnie. Chetnie poczytam wiecej ciekawych wpisow.

        Od dluzszego czasu nic nie zamieszczales Krzyśku, wiec niecierpliwie czekam na jakies poruszenie na twoim blogu .

        1. Author

          Hej Mateusz – masz rację od jakiegoś czasu cisza w eterze… i potrwa to jeszcze trochę bo w tej chwili nie pracuje jeszcze nad nowym artykułem. Kilka spraw życia codziennego wysunęło się na pierwszy plan – remont i urządzanie mieszkania, wyjazdowy okres wakacyjny i wzmorzony sezon urlopowy w pracy, a… no i spać też kiedyś trzeba – najlepiej min. 7 godzin bo w tym roku zdarzały mi się kilkudniowe serie po 4-5 godzin 🙁
          W tej chwili jestem w trakcie formowania w głowie nowej koncepcji bloga – raczej nie wrócą już czasy częstych wpisów co dwa tygodnie, na pewno zostanie jednak mailing do listy. Myślę też nad nową koncepcją na stronie ProstaMatematyka lub na nowoutworzonej gdzie byłoby więcej tematów praktycznych i użytecznych w pracy ale za to mniej klasycznej matematyki. Idealnie byłoby rozdzielić to na dwa blogi – ten nowy praktyczny i stary gdzie byłoby mniej offtopów a więcej czystej matematyki. Poza tym – chciałbym w jakiś sposób zmonetyzować swoją pracę (spędziłem nad tym blogiem sporo czasu więc chciałbym przynajmniej na serwer zarobić ;)). Ale tak jak napisałem – jest pewna koncepcja – zobaczymy czy starczy czasu na realizację 🙂

          1. Myślę że rozdzielanie bloga na dwa osobne blogi o matematyce to zły pomysł. Stworzyłeś Krzyśku coś fajnego. “ProstaMatematyka.pl” to pierwszy i jedyny blog o matematyce który czytam.

            Jak chcesz zwiększać jego popularność to radził bym wrzucać off-topy również w ten rejon. Inaczej mówiąc dziel i zwyciężaj nie będzie tutaj dobrą strategią ale to tylko moje zdanie. Mogę się mylić.

            Pozdrawiam.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *