C Inwendig product, matrix-vermenigvuldiging, vectoren en tensoren

De perceptron is een leeralgoritme dat de ‘gewichten’ \(\theta\) probeert te vinden die na vermenigvuldiging met de invoer \(x\) de uitkomst \(y\) tracht te benaderen met \(\hat{y}\).

\[\begin{equation} f(x, \theta)=\sum_{i=0}^{n}{\theta_ix_i} \tag{C.1} \end{equation}\]

Deze bewerking komt overeen met het inwendig product van de matrix \(\mathbf{x}\) met de vector \(\mathbf{\theta}\):

\[\begin{equation} \mathbf{x}\cdot\mathbf{\theta} \tag{C.2} \end{equation}\]

Nemen we iris dataset uit een vorige casestudy, dan ziet de invoer van een neuraal netwerk \(\mathbf{x}\) er als volgt uit:

x <- iris[, 1:2] %>% cbind("Bias" = c(1, 1), .) %>% as.matrix

\[\mathbf{x}=\begin{bmatrix} 1.0&5.1&3.5 \\ 1.0&4.9&3.0 \\ 1.0&4.7&3.2 \\ 1.0&4.6&3.1 \\ 1.0&5.0&3.6 \\ 1.0&5.4&3.9 \\ \vdots&\vdots&\vdots \\ \end{bmatrix}\]

De eerste kolom is de nep-variabele waarvan sprake zal zijn tijdens het bespreken van Feed-forward ANNs. Nemen we hier nu de eerste rij uit, dan krijgen we een geannoteerde [vector](https://nl.wikipedia.org/wiki/Vector_(wiskunde). In R doen we dit:

x[1,]
##         Bias Sepal.Length  Sepal.Width 
##          1.0          5.1          3.5

Wiskundigen gaan een vector echter meestal voorstellen als een kolomvector. Datawetenschappers houden er dan weer van om een vector als rijvector voor te stellen. Dat heeft te maken met het feit dat het aantal variabelen vaak veel kleiner is dan het aantal instanties en, zoals hierboven voor \(\mathbf{x}\) gedaan werd, de matrix gemakkelijker weer te geven is. Hier gaan we de wiskundige weergave volgen, maar het resultaat moet hetzelfde zijn. We bekomen een kolomvector door deze eerste rij te transponeren, i.e. we maken van de rijen kolommen:

\[\mathbf{x^T_1}=\begin{bmatrix} 1.0 \\ 5.1 \\ 3.5 \\ \end{bmatrix}\]

We kunnen deze vector interpreteren als een pijl in een 3-dimensionaal assenstelsel vertrekkende van de oorsprong en met de punt ter hoogte van 1 op de as Bias, 5.1 richting as Sepal.Length en 3.5 richting Sepal.Width:

Maar opgelet:

Stelling C.1 Het typeert een vector dat het uit waarden bestaat die elke op hun eigen dimensie in een \(p\)-dimensionale ruimte geprojecteerd kunnen worden en dat het niet afhangt van de set van eenheidsvectoren of van coördinatenstelsel.

Nu gaan we over naar de parameters. Uit het resultaat van het eenvoudigste artificieel neuraal netwerk uit de § Inleiding tot ANN’s halen we de parameters die nodig zijn voor het berekenen van de uitvoer-node voor de uitkomst setosa:

\[\mathbf{\theta_{setosa}^T}=\begin{bmatrix} 0.773&-0.374&0.571 \\ \end{bmatrix}\]

Dit noemen we een covector of lineaire functionaal.

Stelling C.2 Het typeert een covector om niet uitgedrukt te kunnen worden in bepaalde eenheden. Covectoren zijn dus eenheidsloos en dienen als lineaire afbeelding (eng: linear map) om een vector te transformeren naar een andere vector. Het is de veralgemening van deze in elkaar transformeerbare vectoren die met tensoren noemt en de term “tensorflow” komt voort uit het het herhaaldelijk moeten uitvoeren van deze transformaties.

Er rest ons nu alleen maar de matrix-vermenigvuldiging uit te voeren. Dit doen volgens het schema in Figuur C.1. Deze figuur laat meteen de veralgemeende situatie zien waarbij meerdere parameter vectoren en meerdere instanties betrokken zijn. Inderdaad, alle waarden voor \(z\) binnen eenzelfde laag kunnen doormiddel van één bewerking tegelijk berekend worden.

Matrix-vermenigvuldiging van. De vermenigvuldiging van twee matrices kan kan dus enkel indien het aantal kolommen van de eerste matrix overeenkomt met het aantal rijen van de tweede. (gebaseerd op deze afbeeldingr)

Figuur C.1: Matrix-vermenigvuldiging van. De vermenigvuldiging van twee matrices kan kan dus enkel indien het aantal kolommen van de eerste matrix overeenkomt met het aantal rijen van de tweede. (gebaseerd op deze afbeeldingr)

Nu kunnen we terug de wiskundige wereld verlaten en de datawetenschapper wereld betreden, en kunnen de dat kantelen (transponeren) van de matrices vergeten. In R voer je een matrix-vermenigvuldiging uit door middel van de %*% operator:

set.seed(42)
x <- rnorm(15, 10, 3) %>% matrix(5, 3)
theta <- runif(6) %>% matrix(3, 2)
z <- x %*% theta

\[z=\mathbf{x}\cdot\mathbf{\theta}=\begin{bmatrix} 14.1&9.7&13.9 \\ 8.3&14.5&16.9 \\ 11.1&9.7&5.8 \\ 11.9&16.1&9.2 \\ 11.2&9.8&9.6 \\ \end{bmatrix}\cdot\begin{bmatrix} 0.7&0.7 \\ 0.8&0.0 \\ 0.4&0.8 \\ \end{bmatrix}=\begin{bmatrix} 1.4&2.0 \\ 1.7&1.5 \\ -0.3&-0.9 \\ 2.0&0.2 \\ 0.2&0.2 \\ \end{bmatrix}\]

Oefening C.1 Probeer nu zelf voor het eerste neuraal netwerk uit § Inleiding tot ANN’s de resultaten in nn$net.result te bekomen door de invoergegevens te vermenigvuldigen met de parameters in nn$weights.