2.3 Tiesinė algebra

Dabar jau galime įkelti duomenų rinkinius į tenzorius ir apdoroti šiuos tenzorius pagrindinėmis matematinėmis operacijomis. Norint pradėti kurti sudėtingus modelius, mums prireiks ir keleto tiesinės algebros įrankių. Šiame skyrelyje švelniai supažindiname su svarbiausiomis sąvokomis, pradedant skaliarine aritmetika ir pereinant prie matricų daugybos.

from mxnet import np, npx
npx.set_np()
import torch
import tensorflow as tf
from jax import numpy as jnp

2.3.1 Skaliarai

Dauguma kasdienės matematikos susideda iš skaičių apdorojimo po vieną. Formaliai šias reikšmes vadiname skaliarais. Pavyzdžiui, temperatūra Palo Alto yra malonūs 7272 Farenheito laipsniai. Jei norėtumėte konvertuoti temperatūrą į Celsijaus laipsnius, įvertintumėte išraišką c=59(f−32)c = \frac{5}{9}(f - 32), kai ff lygus 7272. Šioje lygtyje reikšmės 55, 99 ir 3232 yra pastovūs skaliarai. Kintamieji cc ir ff paprastai žymi nežinomus skaliarus.

Skaliarus žymime paprastomis mažosiomis raidėmis (pvz., xx, yy ir zz), o visų (tolydžiųjų) realiąsias reikšmes įgyjančių skaliarų erdvę – R\mathbb{R}. Patogumo dėlei praleisime griežtas erdvių apibrėžtis: tiesiog prisiminkite, kad išraiška x∈Rx \in \mathbb{R} yra formalus būdas pasakyti, kad xx yra realiąją reikšmę įgyjantis skaliaras. Simbolis ∈\in (tariamas „priklauso") žymi priklausymą aibei. Pavyzdžiui, x,y∈{0,1}x, y \in \{0, 1\} rodo, kad xx ir yy yra kintamieji, galintys įgyti tik reikšmes 00 arba 11.

(Skaliarai įgyvendinami kaip tenzoriai, turintys tik vieną elementą.) Toliau priskiriame du skaliarus ir atliekame gerai žinomas sudėties, daugybos, dalybos ir kėlimo laipsniu operacijas.

x = np.array(3.0)
y = np.array(2.0)

x + y, x * y, x / y, x ** y
x = torch.tensor(3.0)
y = torch.tensor(2.0)

x + y, x * y, x / y, x**y
x = tf.constant(3.0)
y = tf.constant(2.0)

x + y, x * y, x / y, x**y
x = jnp.array(3.0)
y = jnp.array(2.0)

x + y, x * y, x / y, x**y

2.3.2 Vektoriai

Šiuo metu vektorių galite įsivaizduoti kaip fiksuoto ilgio skaliarų masyvą. Kaip ir jų atitikmenis kode, šiuos skaliarus vadiname vektoriaus elementais (sinonimai: įrašai ir komponentės). Kai vektoriai vaizduoja realių duomenų rinkinių pavyzdžius, jų reikšmės turi tam tikrą realią reikšmę. Pavyzdžiui, jei apmokytume modelį prognozuoti paskolos neišmokėjimo riziką, galėtume kiekvieną pareiškėją susieti su vektoriumi, kurio komponentės atitinka dydžius, tokius kaip jų pajamos, darbo stažas ar ankstesnių neįvykdymų skaičius. Jei tirtume infarkto riziką, kiekvienas vektorius galėtų vaizduoti pacientą, o jo komponentės galėtų atitikti naujausius gyvybinius požymius, cholesterolio lygį, kasdienio fizinio krūvio minutes ir kt. Vektorius žymime pastorintomis mažosiomis raidėmis (pvz., x\mathbf{x}, y\mathbf{y} ir z\mathbf{z}).

Vektoriai įgyvendinami kaip 11-osios eilės tenzoriai. Paprastai tokie tenzoriai gali būti savavališko ilgio, priklausomai nuo atminties apribojimų. Dėmesio: Python, kaip ir daugumoje programavimo kalbų, vektorių indeksai prasideda nuo 00 (angl. zero-based indexing, indeksavimas nuo nulio), o tiesinėje algebroje apatiniai indeksai prasideda nuo 11 (indeksavimas nuo vieneto).

x = np.arange(3)
x
x = torch.arange(3)
x
x = tf.range(3)
x
x = jnp.arange(3)
x

Vektoriaus elementą galime nurodyti naudodami apatinį indeksą. Pavyzdžiui, x2x_2 žymi antrąjį x\mathbf{x} elementą. Kadangi x2x_2 yra skaliaras, jo nepastoriname. Pagal numatytuosius nustatymus vektorius vizualizuojame sudėdami jo elementus vertikaliai:

x=[x1⋮xn].(2.3.1)\mathbf{x} =\begin{bmatrix}x_{1} \\ \vdots \\x_{n}\end{bmatrix}. \tag{2.3.1}

Čia x1,…,xnx_1, \ldots, x_n yra vektoriaus elementai. Vėliau atskirsime tokius stulpelio vektorius ir eilutės vektorius, kurių elementai sudėti horizontaliai. Prisiminkite, kad tenzoriaus elementus pasiekiame indeksavimu.

x[2]

Norėdami nurodyti, kad vektorių sudaro nn elementų, rašome x∈Rn\mathbf{x} \in \mathbb{R}^n. Formaliai nn vadiname vektoriaus dimensija. Kode tai atitinka tenzoriaus ilgį, pasiekiamą Python integruota funkcija len.

len(x)

Ilgį taip pat galime pasiekti per atributą shape. Forma yra kortežas, nurodantis tenzoriaus ilgį kiekviena ašimi. (Tenzorių, turinčių tik vieną ašį, formos turi tik vieną elementą.)

x.shape

Dažnai žodis „dimensija" vartojamas dviprasmiškai: tiek ašių skaičiui, tiek ilgiui tam tikra ašimi žymėti. Kad išvengtume šios painiavos, ašių skaičiui žymėti vartojame terminą eilė, o dimensija – tik komponenčių skaičiui žymėti.

2.3.3 Matricos

Kaip skaliarai yra 00-osios eilės tenzoriai, o vektoriai – 11-osios eilės tenzoriai, taip matricos yra 22-osios eilės tenzoriai. Matricas žymime pastorintomis didžiosiomis raidėmis (pvz., X\mathbf{X}, Y\mathbf{Y} ir Z\mathbf{Z}) ir kode vaizduojame tenzoriais su dviem ašimis. Išraiška A∈Rm×n\mathbf{A} \in \mathbb{R}^{m \times n} rodo, kad matricą A\mathbf{A} sudaro m×nm \times n realiąsias reikšmes įgyjančių skaliarų, išdėstytų mm eilučių ir nn stulpelių. Kai m=nm = n, sakome, kad matrica yra kvadratinė. Vizualiai bet kurią matricą galime pavaizduoti kaip lentelę. Kad nurodytume atskirą elementą, pridedame apatinius eilutės ir stulpelio indeksus, pvz., aija_{ij} yra reikšmė, priklausanti A\mathbf{A} ii-ajai eilutei ir jj-ajam stulpeliui:

A=[a11a12⋯a1na21a22⋯a2n⋮⋮⋱⋮am1am2⋯amn].(2.3.2)\mathbf{A}=\begin{bmatrix} a_{11} & a_{12} & \cdots & a_{1n} \\ a_{21} & a_{22} & \cdots & a_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m1} & a_{m2} & \cdots & a_{mn} \\ \end{bmatrix}. \tag{2.3.2}

Kode matricą A∈Rm×n\mathbf{A} \in \mathbb{R}^{m \times n} vaizduojame 22-osios eilės tenzoriumi, kurio forma (mm, nn). Bet kurį tinkamo dydžio m×nm \times n tenzorių galime paversti m×nm \times n matrica, nurodę norimą formą funkcijai reshape:

A = np.arange(6).reshape(3, 2)
A
A = torch.arange(6).reshape(3, 2)
A
A = tf.reshape(tf.range(6), (3, 2))
A
A = jnp.arange(6).reshape(3, 2)
A

Kartais norime apversti ašis. Kai sukeičiame matricos eilutes ir stulpelius, rezultatas vadinamas jos transponuota matrica. Formaliai matricos A\mathbf{A} transponuotą matricą žymime A⊤\mathbf{A}^\top, ir jei B=A⊤\mathbf{B} = \mathbf{A}^\top, tai bij=ajib_{ij} = a_{ji} visiems ii ir jj. Taigi m×nm \times n matricos transponuota matrica yra n×mn \times m matrica:

A⊤=[a11a21…am1a12a22…am2⋮⋮⋱⋮a1na2n…amn].\mathbf{A}^\top = \begin{bmatrix} a_{11} & a_{21} & \dots & a_{m1} \\ a_{12} & a_{22} & \dots & a_{m2} \\ \vdots & \vdots & \ddots & \vdots \\ a_{1n} & a_{2n} & \dots & a_{mn} \end{bmatrix}.

Kode bet kurios (matricos transponuotą matricą) galime gauti taip:

A.T
tf.transpose(A)

Simetrinės matricos yra kvadratinių matricų poaibis, lygių savo pačių transponuotoms matricoms: A=A⊤\mathbf{A} = \mathbf{A}^\top. Ši matrica yra simetrinė:

A = np.array([[1, 2, 3], [2, 0, 4], [3, 4, 5]])
A == A.T
A = torch.tensor([[1, 2, 3], [2, 0, 4], [3, 4, 5]])
A == A.T
A = tf.constant([[1, 2, 3], [2, 0, 4], [3, 4, 5]])
A == tf.transpose(A)
A = jnp.array([[1, 2, 3], [2, 0, 4], [3, 4, 5]])
A == A.T

Matricos naudingos duomenų rinkiniams vaizduoti. Paprastai eilutės atitinka atskirus įrašus, o stulpeliai – skirtingus atributus.

2.3.4 Tenzoriai

Nors su vien skaliarais, vektoriais ir matricomis galite nueiti toli savo mašininio mokymosi kelyje, galiausiai gali prireikti dirbti su aukštesnės eilės tenzoriais. Tenzoriai (suteikia mums bendrą būdą aprašyti nn-osios eilės masyvų plėtinius.) Programinius tenzoriaus klasės objektus vadiname „tenzoriais" būtent todėl, kad jie taip pat gali turėti savavališką ašių skaičių. Nors gali būti painu vartoti žodį tenzorius ir matematiniam objektui, ir jo įgyvendinimui kode, mūsų reikšmė paprastai turėtų būti aiški iš konteksto. Bendruosius tenzorius žymime didžiosiomis raidėmis specialiu šriftu (pvz., X\mathsf{X}, Y\mathsf{Y} ir Z\mathsf{Z}), o jų indeksavimo mechanizmas (pvz., xijkx_{ijk} ir [X]1,2i−1,3[\mathsf{X}]_{1, 2i-1, 3}) natūraliai išplaukia iš matricų indeksavimo.

Tenzoriai taps svarbesni, kai pradėsime dirbti su vaizdais. Kiekvienas vaizdas pateikiamas kaip 33-iosios eilės tenzorius, kurio ašys atitinka aukštį, plotį ir kanalą. Kiekvienoje erdvinėje vietoje kiekvienos spalvos (raudonos, žalios ir mėlynos) intensyvumai sudedami kanalo ašimi. Be to, vaizdų rinkinys kode vaizduojamas 44-osios eilės tenzoriumi, kurio skirtingi vaizdai indeksuojami pirmąja ašimi. Aukštesnės eilės tenzoriai konstruojami, kaip ir vektoriai bei matricos, didinant formos komponenčių skaičių.

np.arange(24).reshape(2, 3, 4)
torch.arange(24).reshape(2, 3, 4)
tf.reshape(tf.range(24), (2, 3, 4))
jnp.arange(24).reshape(2, 3, 4)

2.3.5 Pagrindinės tenzorių aritmetikos savybės

Skaliarai, vektoriai, matricos ir aukštesnės eilės tenzoriai turi keletą patogių savybių. Pavyzdžiui, poelementės operacijos sukuria išvestis, kurių forma tokia pati kaip operandų.

A = np.arange(6).reshape(2, 3)
B = A.copy()  # Assign a copy of A to B by allocating new memory
A, A + B
A = torch.arange(6, dtype=torch.float32).reshape(2, 3)
B = A.clone()  # Assign a copy of A to B by allocating new memory
A, A + B
A = tf.reshape(tf.range(6, dtype=tf.float32), (2, 3))
B = A  # No cloning of A to B by allocating new memory
A, A + B
A = jnp.arange(6, dtype=jnp.float32).reshape(2, 3)
B = A
A, A + B

Dviejų matricų poelementė sandauga vadinama jų Adamaro sandauga (žymima ⊙\odot). Dviejų matricų A,B∈Rm×n\mathbf{A}, \mathbf{B} \in \mathbb{R}^{m \times n} Adamaro sandaugos įrašus galime išrašyti:

A⊙B=[a11b11a12b12…a1nb1na21b21a22b22…a2nb2n⋮⋮⋱⋮am1bm1am2bm2…amnbmn].\mathbf{A} \odot \mathbf{B} = \begin{bmatrix} a_{11} b_{11} & a_{12} b_{12} & \dots & a_{1n} b_{1n} \\ a_{21} b_{21} & a_{22} b_{22} & \dots & a_{2n} b_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m1} b_{m1} & a_{m2} b_{m2} & \dots & a_{mn} b_{mn} \end{bmatrix}.
A * B

Pridėjus skaliarą prie tenzoriaus arba padauginus skaliarą ir tenzorių, gaunamas rezultatas, kurio forma tokia pati kaip pradinio tenzoriaus. Čia prie kiekvieno tenzoriaus elemento pridedamas skaliaras (arba jis dauginamas iš skaliaro).

a = 2
X = np.arange(24).reshape(2, 3, 4)
a + X, (a * X).shape
a = 2
X = torch.arange(24).reshape(2, 3, 4)
a + X, (a * X).shape
a = 2
X = tf.reshape(tf.range(24), (2, 3, 4))
a + X, (a * X).shape
a = 2
X = jnp.arange(24).reshape(2, 3, 4)
a + X, (a * X).shape

2.3.6 Redukavimas

Dažnai norime apskaičiuoti tenzoriaus elementų sumą. Vektoriaus x\mathbf{x}, kurio ilgis nn, elementų sumai išreikšti rašome ∑i=1nxi\sum_{i=1}^n x_i. Tam yra paprasta funkcija:

x = np.arange(3)
x, x.sum()
x = torch.arange(3, dtype=torch.float32)
x, x.sum()
x = tf.range(3, dtype=tf.float32)
x, tf.reduce_sum(x)
x = jnp.arange(3, dtype=jnp.float32)
x, x.sum()

Kad išreikštume savavališkos formos tenzorių elementų sumas, tiesiog sumuojame pagal visas jo ašis. Pavyzdžiui, m×nm \times n matricos A\mathbf{A} elementų suma galėtų būti užrašyta ∑i=1m∑j=1naij\sum_{i=1}^{m} \sum_{j=1}^{n} a_{ij}.

A.shape, A.sum()
A.shape, tf.reduce_sum(A)

Pagal numatytuosius nustatymus iškvietus sumos funkciją tenzorius redukuojamas visomis ašimis, galiausiai gaunamas skaliaras. Mūsų bibliotekos taip pat leidžia nurodyti ašis, kuriomis tenzorius turi būti redukuojamas. Norėdami susumuoti visus elementus eilutėmis (0 ašis), funkcijoje sum nurodome axis=0. Kadangi įvesties matrica redukuojama 0 ašimi, kad gautume išvesties vektorių, šios ašies išvesties formoje nėra.

A.shape, A.sum(axis=0).shape
A.shape, tf.reduce_sum(A, axis=0).shape

Nurodžius axis=1, bus redukuojamas stulpelių matmuo (1 ašis), susumuojant visų stulpelių elementus.

A.shape, A.sum(axis=1).shape
A.shape, tf.reduce_sum(A, axis=1).shape

Matricos redukavimas sumuojant ir eilutėmis, ir stulpeliais yra ekvivalentus visų matricos elementų susumavimui.

A.sum(axis=[0, 1]) == A.sum()  # Same as A.sum()
tf.reduce_sum(A, axis=[0, 1]), tf.reduce_sum(A)  # Same as tf.reduce_sum(A)

Susijęs dydis yra vidurkis, dar vadinamas aritmetiniu vidurkiu. Vidurkį skaičiuojame dalydami sumą iš bendro elementų skaičiaus. Kadangi vidurkio skaičiavimas toks dažnas, jam skirta atskira bibliotekos funkcija, veikianti analogiškai kaip sum.

A.mean(), A.sum() / A.size
A.mean(), A.sum() / A.numel()
tf.reduce_mean(A), tf.reduce_sum(A) / tf.size(A).numpy()

Panašiai vidurkio skaičiavimo funkcija taip pat gali redukuoti tenzorių konkrečiomis ašimis.

A.mean(axis=0), A.sum(axis=0) / A.shape[0]
tf.reduce_mean(A, axis=0), tf.reduce_sum(A, axis=0) / A.shape[0]

2.3.7 Suma be redukavimo

Kartais gali būti naudinga išlaikyti nepakeistą ašių skaičių, kviečiant sumos ar vidurkio skaičiavimo funkciją. Tai svarbu, kai norime naudoti transliavimo mechanizmą.

sum_A = A.sum(axis=1, keepdims=True)
sum_A, sum_A.shape
sum_A = tf.reduce_sum(A, axis=1, keepdims=True)
sum_A, sum_A.shape

Pavyzdžiui, kadangi sum_A po kiekvienos eilutės susumavimo išlaiko abi ašis, galime (padalyti A iš sum_A naudodami transliavimą), kad sukurtume matricą, kurios kiekvienos eilutės suma lygi 11.

A / sum_A

Jei norime apskaičiuoti A elementų kaupiamąją sumą tam tikra ašimi, tarkime, axis=0 (eilutė po eilutės), galime iškviesti funkciją cumsum. Pagal paskirtį ši funkcija neredukuoja įvesties tenzoriaus jokia ašimi.

A.cumsum(axis=0)
tf.cumsum(A, axis=0)

2.3.8 Skaliarinės sandaugos

Iki šiol atlikome tik poelementes operacijas, sumas ir vidurkius. Ir jei tai būtų viskas, ką galime daryti, tiesinė algebra nenusipelnytų atskiro skyrelio. Laimei, čia viskas tampa įdomiau. Viena pagrindinių operacijų yra skaliarinė sandauga. Kai duoti du vektoriai x,y∈Rd\mathbf{x}, \mathbf{y} \in \mathbb{R}^d, jų skaliarinė sandauga x⊤y\mathbf{x}^\top \mathbf{y} (dar žinoma kaip vidinė sandauga, ⟨x,y⟩\langle \mathbf{x}, \mathbf{y} \rangle) yra tos pačios padėties elementų sandaugų suma: x⊤y=∑i=1dxiyi\mathbf{x}^\top \mathbf{y} = \sum_{i=1}^{d} x_i y_i.

Dviejų vektorių skaliarinė sandauga yra tos pačios padėties elementų sandaugų suma

y = np.ones(3)
x, y, np.dot(x, y)
y = torch.ones(3, dtype = torch.float32)
x, y, torch.dot(x, y)
y = tf.ones(3, dtype=tf.float32)
x, y, tf.tensordot(x, y, axes=1)
y = jnp.ones(3, dtype = jnp.float32)
x, y, jnp.dot(x, y)

Ekvivalenčiai, (dviejų vektorių skaliarinę sandaugą galime apskaičiuoti atlikdami poelementę daugybą, o po jos – sumavimą:)

np.sum(x * y)
torch.sum(x * y)
tf.reduce_sum(x * y)
jnp.sum(x * y)

Skaliarinės sandaugos naudingos įvairiuose kontekstuose. Pavyzdžiui, kai duotas reikšmių rinkinys, žymimas vektoriumi x∈Rn\mathbf{x} \in \mathbb{R}^n, ir svorių (angl. weights) rinkinys, žymimas w∈Rn\mathbf{w} \in \mathbb{R}^n, reikšmių x\mathbf{x} svertinė suma pagal svorius w\mathbf{w} gali būti išreikšta skaliarine sandauga x⊤w\mathbf{x}^\top \mathbf{w}. Kai svoriai neneigiami ir sudaro sumą 11, t. y. (∑i=1nwi=1)\left(\sum_{i=1}^{n} {w_i} = 1\right), skaliarinė sandauga išreiškia svertinį vidurkį. Normalizavus du vektorius iki vienetinio ilgio, skaliarinės sandaugos išreiškia kampo tarp jų kosinusą. Vėliau šiame skyrelyje formaliai pristatysime šią ilgio sąvoką.

2.3.9 Matricos ir vektoriaus sandaugos

Dabar, kai žinome, kaip skaičiuoti skaliarines sandaugas, galime pradėti suprasti sandaugą tarp m×nm \times n matricos A\mathbf{A} ir nn-mačio vektoriaus x\mathbf{x}. Pradžioje savo matricą pavaizduojame jos eilučių vektoriais

A=[a1⊤a2⊤⋮am⊤],\mathbf{A}= \begin{bmatrix} \mathbf{a}^\top_{1} \\ \mathbf{a}^\top_{2} \\ \vdots \\ \mathbf{a}^\top_m \\ \end{bmatrix},

kur kiekvienas ai⊤∈Rn\mathbf{a}^\top_{i} \in \mathbb{R}^n yra eilutės vektorius, vaizduojantis matricos A\mathbf{A} ii-ąją eilutę.

Matricos ir vektoriaus sandauga Ax\mathbf{A}\mathbf{x} yra tiesiog mm ilgio stulpelio vektorius, kurio ii-asis elementas yra skaliarinė sandauga ai⊤x\mathbf{a}^\top_i \mathbf{x}:

Ax=[a1⊤a2⊤⋮am⊤]x=[a1⊤xa2⊤x⋮am⊤x].\mathbf{A}\mathbf{x} = \begin{bmatrix} \mathbf{a}^\top_{1} \\ \mathbf{a}^\top_{2} \\ \vdots \\ \mathbf{a}^\top_m \\ \end{bmatrix}\mathbf{x} = \begin{bmatrix} \mathbf{a}^\top_{1} \mathbf{x} \\ \mathbf{a}^\top_{2} \mathbf{x} \\ \vdots\\ \mathbf{a}^\top_{m} \mathbf{x}\\ \end{bmatrix}.

Daugybą iš matricos A∈Rm×n\mathbf{A}\in \mathbb{R}^{m \times n} galime laikyti transformacija, projektuojančia vektorius iš Rn\mathbb{R}^{n} į Rm\mathbb{R}^{m}. Šios transformacijos nepaprastai naudingos. Pavyzdžiui, posūkius galime pavaizduoti kaip daugybą iš tam tikrų kvadratinių matricų. Matricos ir vektoriaus sandaugos taip pat aprašo pagrindinį skaičiavimą, naudojamą apskaičiuojant kiekvieno neuroninio tinklo sluoksnio išvestis, kai duotos ankstesnio sluoksnio išvestys.

Matricos ir vektoriaus sandaugai kode išreikšti naudojame tą pačią funkciją dot. Operacija nustatoma pagal argumentų tipą. Atkreipkite dėmesį, kad A stulpelių dimensija (jos ilgis 1 ašimi) turi sutapti su x dimensija (jo ilgiu).

Matricos ir vektoriaus sandaugai kode išreikšti naudojame funkciją mv. Atkreipkite dėmesį, kad A stulpelių dimensija (jos ilgis 1 ašimi) turi sutapti su x dimensija (jo ilgiu). Python turi patogų operatorių @, galintį vykdyti ir matricos–vektoriaus, ir matricos–matricos sandaugas (priklausomai nuo argumentų). Taigi galime rašyti A@x.

Matricos ir vektoriaus sandaugai kode išreikšti naudojame funkciją matvec. Atkreipkite dėmesį, kad A stulpelių dimensija (jos ilgis 1 ašimi) turi sutapti su x dimensija (jo ilgiu).

A.shape, x.shape, np.dot(A, x)
A.shape, x.shape, torch.mv(A, x), A@x
A.shape, x.shape, tf.linalg.matvec(A, x)
A.shape, x.shape, jnp.matmul(A, x)

2.3.10 Matricų daugyba

Kai perprasite skaliarines sandaugas ir matricos ir vektoriaus sandaugas, matricų daugyba turėtų būti paprasta.

Tarkime, turime dvi matricas A∈Rn×k\mathbf{A} \in \mathbb{R}^{n \times k} ir B∈Rk×m\mathbf{B} \in \mathbb{R}^{k \times m}:

A=[a11a12⋯a1ka21a22⋯a2k⋮⋮⋱⋮an1an2⋯ank],B=[b11b12⋯b1mb21b22⋯b2m⋮⋮⋱⋮bk1bk2⋯bkm].\mathbf{A}=\begin{bmatrix} a_{11} & a_{12} & \cdots & a_{1k} \\ a_{21} & a_{22} & \cdots & a_{2k} \\ \vdots & \vdots & \ddots & \vdots \\ a_{n1} & a_{n2} & \cdots & a_{nk} \\ \end{bmatrix},\quad \mathbf{B}=\begin{bmatrix} b_{11} & b_{12} & \cdots & b_{1m} \\ b_{21} & b_{22} & \cdots & b_{2m} \\ \vdots & \vdots & \ddots & \vdots \\ b_{k1} & b_{k2} & \cdots & b_{km} \\ \end{bmatrix}.

Tegul ai⊤∈Rk\mathbf{a}^\top_{i} \in \mathbb{R}^k žymi eilutės vektorių, vaizduojantį matricos A\mathbf{A} ii-ąją eilutę, o bj∈Rk\mathbf{b}_{j} \in \mathbb{R}^k – stulpelio vektorių iš matricos B\mathbf{B} jj-ojo stulpelio:

A=[a1⊤a2⊤⋮an⊤],B=[b1b2⋯bm].\mathbf{A}= \begin{bmatrix} \mathbf{a}^\top_{1} \\ \mathbf{a}^\top_{2} \\ \vdots \\ \mathbf{a}^\top_n \\ \end{bmatrix}, \quad \mathbf{B}=\begin{bmatrix} \mathbf{b}_{1} & \mathbf{b}_{2} & \cdots & \mathbf{b}_{m} \\ \end{bmatrix}.

Kad sudarytume matricų sandaugą C∈Rn×m\mathbf{C} \in \mathbb{R}^{n \times m}, tiesiog apskaičiuojame kiekvieną elementą cijc_{ij} kaip skaliarinę sandaugą tarp A\mathbf{A} ii-osios eilutės ir B\mathbf{B} jj-ojo stulpelio, t. y. ai⊤bj\mathbf{a}^\top_i \mathbf{b}_j:

C=AB=[a1⊤a2⊤⋮an⊤][b1b2⋯bm]=[a1⊤b1a1⊤b2⋯a1⊤bma2⊤b1a2⊤b2⋯a2⊤bm⋮⋮⋱⋮an⊤b1an⊤b2⋯an⊤bm].\mathbf{C} = \mathbf{AB} = \begin{bmatrix} \mathbf{a}^\top_{1} \\ \mathbf{a}^\top_{2} \\ \vdots \\ \mathbf{a}^\top_n \\ \end{bmatrix} \begin{bmatrix} \mathbf{b}_{1} & \mathbf{b}_{2} & \cdots & \mathbf{b}_{m} \\ \end{bmatrix} = \begin{bmatrix} \mathbf{a}^\top_{1} \mathbf{b}_1 & \mathbf{a}^\top_{1}\mathbf{b}_2& \cdots & \mathbf{a}^\top_{1} \mathbf{b}_m \\ \mathbf{a}^\top_{2}\mathbf{b}_1 & \mathbf{a}^\top_{2} \mathbf{b}_2 & \cdots & \mathbf{a}^\top_{2} \mathbf{b}_m \\ \vdots & \vdots & \ddots &\vdots\\ \mathbf{a}^\top_{n} \mathbf{b}_1 & \mathbf{a}^\top_{n}\mathbf{b}_2& \cdots& \mathbf{a}^\top_{n} \mathbf{b}_m \end{bmatrix}.

Matricų daugybą AB\mathbf{AB} galime laikyti mm matricos ir vektoriaus sandaugų arba m×nm \times n skaliarinių sandaugų atlikimu ir rezultatų sujungimu į n×mn \times m matricą. Šiame fragmente atliekame matricų A ir B daugybą. Čia A yra matrica su dviem eilutėmis ir trimis stulpeliais, o B – matrica su trimis eilutėmis ir keturiais stulpeliais. Po daugybos gauname matricą su dviem eilutėmis ir keturiais stulpeliais.

B = np.ones(shape=(3, 4))
np.dot(A, B)
B = torch.ones(3, 4)
torch.mm(A, B), A@B
B = tf.ones((3, 4), tf.float32)
tf.matmul(A, B)
B = jnp.ones((3, 4))
jnp.matmul(A, B)

Terminas matricų daugyba (angl. matrix–matrix multiplication) dažnai supaprastinamas iki matricų daugybos ir neturėtų būti painiojamas su Adamaro sandauga.

2.3.11 Normos

Vieni naudingiausių tiesinės algebros operatorių yra normos. Neformaliai vektoriaus norma parodo, kiek jis yra didelis. Pavyzdžiui, ℓ2\ell_2 norma matuoja vektoriaus (Euklido) ilgį. Čia vartojame dydžio sąvoką, susijusią su vektoriaus komponenčių didumu (o ne jo dimensija).

Norma yra funkcija ∥⋅∥\| \cdot \|, kuri atvaizduoja vektorių į skaliarą ir tenkina šias tris savybes:

  1. Kai duotas bet kuris vektorius x\mathbf{x}, jei vektorių (visus jo elementus) padauginame iš skaliaro α∈R\alpha \in \mathbb{R}, jo norma atitinkamai keičiasi:
∥αx∥=∣α∣∥x∥.\|\alpha \mathbf{x}\| = |\alpha| \|\mathbf{x}\|.
  1. Bet kuriems vektoriams x\mathbf{x} ir y\mathbf{y} normos tenkina trikampio nelygybę:
∥x+y∥≤∥x∥+∥y∥.\|\mathbf{x} + \mathbf{y}\| \leq \|\mathbf{x}\| + \|\mathbf{y}\|.
  1. Vektoriaus norma yra neneigiama ir lygi nuliui tik tada, kai vektorius nulinis:
∥x∥>0 for all x≠0.\|\mathbf{x}\| > 0 \textrm{ for all } \mathbf{x} \neq 0.

Daug funkcijų yra tinkamos normos, ir skirtingos normos koduoja skirtingas dydžio sąvokas. Euklido norma, kurią visi išmokome pradinės mokyklos geometrijoje skaičiuodami statiojo trikampio įžambinę, yra vektoriaus elementų kvadratų sumos kvadratinė šaknis. Formaliai tai vadinama ℓ2\ell_2 norma ir išreiškiama

(**

∥x∥2=∑i=1nxi2.\|\mathbf{x}\|_2 = \sqrt{\sum_{i=1}^n x_i^2}.

**)

Metodas norm apskaičiuoja ℓ2\ell_2 normą.

u = np.array([3, -4])
np.linalg.norm(u)
u = torch.tensor([3.0, -4.0])
torch.norm(u)
u = tf.constant([3.0, -4.0])
tf.norm(u)
u = jnp.array([3.0, -4.0])
jnp.linalg.norm(u)

ℓ1\ell_1 norma taip pat dažna, o susijęs matas vadinamas Manheteno atstumu. Pagal apibrėžtį ℓ1\ell_1 norma susumuoja vektoriaus elementų absoliutines reikšmes:

(**

∥x∥1=∑i=1n∣xi∣.\|\mathbf{x}\|_1 = \sum_{i=1}^n \left|x_i \right|.

**)

Palyginti su ℓ2\ell_2 norma, ji mažiau jautri išskirtims. Kad apskaičiuotume ℓ1\ell_1 normą, absoliutinės reikšmės operaciją sukomponuojame su sumavimo operacija.

np.abs(u).sum()
torch.abs(u).sum()
tf.reduce_sum(tf.abs(u))
jnp.linalg.norm(u, ord=1) # same as jnp.abs(u).sum()

Ir ℓ2\ell_2, ir ℓ1\ell_1 normos yra bendresnių ℓp\ell_p normų atskiri atvejai:

∥x∥p=(∑i=1n∣xi∣p)1/p.\|\mathbf{x}\|_p = \left(\sum_{i=1}^n \left|x_i \right|^p \right)^{1/p}.

Matricų atveju reikalai sudėtingesni. Juk matricas galima vertinti ir kaip atskirų įrašų rinkinius, ir kaip objektus, veikiančius vektorius ir paverčiančius juos kitais vektoriais. Pavyzdžiui, galime klausti, kiek ilgesnė gali būti matricos ir vektoriaus sandauga Xv\mathbf{X} \mathbf{v} palyginti su v\mathbf{v}. Ši mąstymo linija veda prie vadinamosios spektrinės normos. Kol kas pristatome kur kas lengviau apskaičiuojamą Frobenijaus normą, apibrėžiamą kaip matricos elementų kvadratų sumos kvadratinė šaknis:

**

∥X∥F=∑i=1m∑j=1nxij2.\|\mathbf{X}\|_\textrm{F} = \sqrt{\sum_{i=1}^m \sum_{j=1}^n x_{ij}^2}.

**

Frobenijaus norma elgiasi taip, tarsi būtų matricos formos vektoriaus ℓ2\ell_2 norma. Iškvietus šią funkciją, bus apskaičiuota matricos Frobenijaus norma.

np.linalg.norm(np.ones((4, 9)))
torch.norm(torch.ones((4, 9)))
tf.norm(tf.ones((4, 9)))
jnp.linalg.norm(jnp.ones((4, 9)))

Nors nenorime per daug skubėti, jau galime sudaryti intuiciją, kodėl šios sąvokos naudingos. Giliajame mokyme dažnai bandome spręsti optimizavimo uždavinius: maksimizuoti stebimiems duomenims priskirtą tikimybę; maksimizuoti su rekomendacijų modeliu susijusias pajamas; minimizuoti atstumą tarp prognozių ir etaloninių stebėjimų; minimizuoti atstumą tarp to paties asmens nuotraukų reprezentacijų, kartu maksimizuojant atstumą tarp skirtingų asmenų nuotraukų reprezentacijų. Šie atstumai, sudarantys giliojo mokymosi algoritmų tikslus, dažnai išreiškiami normomis.

2.3.12 Diskusija

Šiame skyrelyje apžvelgėme visą tiesinę algebrą, kurios jums prireiks, kad suprastumėte didelę šiuolaikinio giliojo mokymosi dalį. Tiesinė algebra turi daug daugiau, ir didelė jos dalis naudinga mašininiam mokymuisi. Pavyzdžiui, matricas galima skaidyti į daugiklius, o šie skaidiniai gali atskleisti žemos dimensijos struktūrą realiuose duomenų rinkiniuose. Yra ištisų mašininio mokymosi porūšių, kurie sutelkia dėmesį į matricų skaidinių ir jų apibendrinimų aukštesnės eilės tenzoriams naudojimą, kad atskleistų duomenų rinkinių struktūrą ir spręstų prognozavimo uždavinius. Tačiau ši knyga sutelkia dėmesį į gilųjį mokymąsi. Ir manome, kad jums labiau norėsis išmokti daugiau matematikos, kai praktiškai išbandysite mašininį mokymąsi su realiais duomenų rinkiniais. Taigi, nors pasiliekame teisę vėliau pristatyti daugiau matematikos, čia šį skyrelį baigiame.

Jei norite sužinoti daugiau tiesinės algebros, yra daug puikių knygų ir šaltinių internete. Pažangesniam greitajam kursui apsvarstykite (Strang, 1993), (Kolter, 2008) ir (Petersen ir Pedersen, 2008).

Apibendrinant:

  • Skaliarai, vektoriai, matricos ir tenzoriai yra pagrindiniai matematiniai objektai, naudojami tiesinėje algebroje, ir turi atitinkamai nulį, vieną, dvi ir savavališką skaičių ašių.
  • Tenzorius galima atpjauti arba redukuoti nurodytomis ašimis atitinkamai indeksavimu arba operacijomis, tokiomis kaip sum ir mean.
  • Poelementės sandaugos vadinamos Adamaro sandaugomis. Priešingai, skaliarinės sandaugos, matricos ir vektoriaus sandaugos bei matricų sandaugos nėra poelementės operacijos ir paprastai grąžina objektus, kurių formos skiriasi nuo operandų.
  • Palyginti su Adamaro sandaugomis, matricų sandaugos skaičiuojamos gerokai ilgiau (kubiniu, o ne kvadratiniu laiku).
  • Normos atspindi įvairias vektoriaus (ar matricos) didumo sąvokas ir dažnai taikomos dviejų vektorių skirtumui, kad būtų išmatuotas jų atstumas.
  • Įprastos vektorių normos yra ℓ1\ell_1 ir ℓ2\ell_2 normos, o įprastos matricų normos – spektrinė ir Frobenijaus normos.

2.3.13 Pratimai

  1. Įrodykite, kad matricos transponuotos matricos transponuota matrica yra pati matrica: (A⊤)⊤=A(\mathbf{A}^\top)^\top = \mathbf{A}.
  2. Kai duotos dvi matricos A\mathbf{A} ir B\mathbf{B}, parodykite, kad sudėtis ir transponavimas komutuoja: A⊤+B⊤=(A+B)⊤\mathbf{A}^\top + \mathbf{B}^\top = (\mathbf{A} + \mathbf{B})^\top.
  3. Ar bet kurios kvadratinės matricos A\mathbf{A} atveju A+A⊤\mathbf{A} + \mathbf{A}^\top visada yra simetrinė? Ar galite įrodyti rezultatą naudodami tik ankstesnių dviejų pratimų rezultatus?
  4. Šiame skyrelyje apibrėžėme tenzorių X, kurio forma (2, 3, 4). Kokia yra len(X) išvestis? Parašykite savo atsakymą nerašydami jokio kodo, tada patikrinkite atsakymą kodu.
  5. Ar savavališkos formos tenzoriui X len(X) visada atitinka tam tikros X ašies ilgį? Kokia tai ašis?
  6. Paleiskite A / A.sum(axis=1) ir pažiūrėkite, kas nutinka. Ar galite išanalizuoti rezultatus?
  7. Keliaujant tarp dviejų taškų Manheteno centre, kokį atstumą reikia įveikti koordinačių požiūriu, t. y. prospektais ir gatvėmis? Ar galima keliauti įstrižai?
  8. Panagrinėkite tenzorių, kurio forma (2, 3, 4). Kokios yra sumavimo išvesčių formos 0, 1 ir 2 ašimis?
  9. Pateikite tenzorių su trimis ar daugiau ašių funkcijai linalg.norm ir stebėkite jos išvestį. Ką ši funkcija apskaičiuoja savavališkos formos tenzoriams?
  10. Panagrinėkite tris dideles matricas, tarkime, A∈R210×216\mathbf{A} \in \mathbb{R}^{2^{10} \times 2^{16}}, B∈R216×25\mathbf{B} \in \mathbb{R}^{2^{16} \times 2^{5}} ir C∈R25×214\mathbf{C} \in \mathbb{R}^{2^{5} \times 2^{14}}, inicializuotas Gauso atsitiktiniais dydžiais. Norite apskaičiuoti sandaugą ABC\mathbf{A} \mathbf{B} \mathbf{C}. Ar yra skirtumas atminties pėdsake ir greityje, priklausomai nuo to, ar skaičiuojate (AB)C(\mathbf{A} \mathbf{B}) \mathbf{C}, ar A(BC)\mathbf{A} (\mathbf{B} \mathbf{C})? Kodėl?
  11. Panagrinėkite tris dideles matricas, tarkime, A∈R210×216\mathbf{A} \in \mathbb{R}^{2^{10} \times 2^{16}}, B∈R216×25\mathbf{B} \in \mathbb{R}^{2^{16} \times 2^{5}} ir C∈R25×216\mathbf{C} \in \mathbb{R}^{2^{5} \times 2^{16}}. Ar yra skirtumas greityje, priklausomai nuo to, ar skaičiuojate AB\mathbf{A} \mathbf{B}, ar AC⊤\mathbf{A} \mathbf{C}^\top? Kodėl? Kas pasikeičia, jei inicializuojate C=B⊤\mathbf{C} = \mathbf{B}^\top nekopijuodami atminties? Kodėl?
  12. Panagrinėkite tris matricas, tarkime, A,B,C∈R100×200\mathbf{A}, \mathbf{B}, \mathbf{C} \in \mathbb{R}^{100 \times 200}. Sukonstruokite tenzorių su trimis ašimis, sudėję [A,B,C][\mathbf{A}, \mathbf{B}, \mathbf{C}]. Kokia yra dimensija? Atpjaukite antrąją trečiosios ašies koordinatę, kad atkurtumėte B\mathbf{B}. Patikrinkite, ar jūsų atsakymas teisingas.

Diskusijos

Diskusijos

Diskusijos

Diskusijos