forked from filipg/aitech-eks-pub
Merge branch 'master' of git.wmi.amu.edu.pl:filipg/aitech-eks
This commit is contained in:
commit
d76157a5a5
File diff suppressed because one or more lines are too long
@ -1,5 +1,29 @@
|
||||
|
||||
* Neurozoo
|
||||
** Kilka uwag dotyczących wektorów
|
||||
|
||||
Wektor wierszowy $\left[x_1,\dots,x_n\right]$ czy kolumnowy $\left[\begin{array}{c}
|
||||
x_1 \\ \vdots \\ x_n\end{array}\right]$?
|
||||
|
||||
Często zakłada się wektor kolumny, będziemy używać *transpozycji*, by otrzymać wektor
|
||||
wierszowy $\vec{x}^T = \left[x_1,\dots,x_n\right]$.
|
||||
|
||||
W praktyce, np. w PyTorchu, może to nie mieć wielkiego znaczenia:
|
||||
|
||||
#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer
|
||||
import torch
|
||||
x = torch.tensor([1.0, -0.5, 2.0])
|
||||
x
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:results:
|
||||
# Out[2]:
|
||||
: tensor([ 1.0000, -0.5000, 2.0000])
|
||||
:end:
|
||||
|
||||
Musimy tylko uważać, jeśli przemnażamy wektor przez macierz!
|
||||
|
||||
** Funkcja sigmoidalna
|
||||
|
||||
Funkcja sigmoidalna zamienia dowolną wartość („sygnał”) w wartość z przedziału $(0,1)$, czyli wartość, która może być interperetowana jako prawdopodobieństwo.
|
||||
@ -101,6 +125,210 @@ Funkcja sigmoidalna nie ma żadnych wyuczalnych wag.
|
||||
**** *Pytanie*: Czy można rozszerzyć funkcję sigmoidalną o jakieś wyuczalne wagi?
|
||||
|
||||
** Regresja liniowa
|
||||
*** Iloczyn skalarny — przypomnienie
|
||||
|
||||
$$\left[1.0, -0.5, 2.0\right]
|
||||
\left[\begin{array}{c}
|
||||
3.0 \\
|
||||
1.5 \\
|
||||
0.0\end{array}\right]
|
||||
=
|
||||
1.0 \cdot 3.0 + -0.5 \cdot 1.5 + 2.0 \cdot 0.0 = 2.25$$
|
||||
**** Intuicje
|
||||
|
||||
- $\vec{a}^T \vec{b}$ mierzy jak bardzo $\vec{a}$ „pasuje” do
|
||||
$\vec{b}$,
|
||||
- … zwłaszcza gdy znormalizujemy wektory dzieląc przez $|\vec{a}|$ i $|\vec{b}|$:
|
||||
$\frac{\vec{a}^T \vec{b}}{|\vec{a}||\vec{b}|} = \cos \theta$,
|
||||
gdzie $\theta$ to kąt pomiędzy $\vec{a}$ and $\vec{b}$ (podobieństwo kosinusowe!)
|
||||
- co, jeśli if $\vec{a}^T \vec{b} = 0$? — $\vec{a}$ i $\vec{b}$ są prostopadłe, np.
|
||||
$\left[1, 2\right] \cdot \left[-2, -1\right]^T = 0$
|
||||
- a co, jeśli $\vec{a}^T \vec{b} = -1$ — wektor są skierowane w przeciwnym kierunku, jeśli dodatkowo $|\vec{a}|=|\vec{b}|=1$, np.
|
||||
$\left[\frac{\sqrt{2}}{2},\frac{\sqrt{2}}{2}\right] \cdot \left[-\frac{\sqrt{2}}{2},-\frac{\sqrt{2}}{2}\right]^T = -1$
|
||||
|
||||
**** W PyTorchu
|
||||
|
||||
#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer
|
||||
import torch
|
||||
x = torch.tensor([1.0, -0.5, 2.0])
|
||||
y = torch.tensor([3.0, 1.5, 0.0])
|
||||
x @ y
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:results:
|
||||
# Out[3]:
|
||||
: tensor(2.2500)
|
||||
:end:
|
||||
|
||||
*** Regresja liniowa jako element sieci neuronowej
|
||||
|
||||
Przypomnijmy sobie wzór na regresję liniową:
|
||||
|
||||
$$y = w_0 + w_1x_1 + w_2x_2 + \dots + w_{|V|}x_{|v|}$$
|
||||
|
||||
Jeśli wprowadzimy sztuczny element wektora $\vec{x}$ ustawiony zawsze na 1 ($x_0 = 1$), wówczas
|
||||
wzór może przyjąc bardziej zwartą postać:
|
||||
|
||||
$$y = \sum_{i=0}^{|V|} w_ix_i = \vec{w}\vec{x}$$
|
||||
|
||||
*** PyTorch
|
||||
|
||||
**** Implementacja w PyTorchu
|
||||
|
||||
Zakładamy, że wektor wejściowy *nie* obejmuje dodatkowego elementu $x_0 = 1$.
|
||||
|
||||
#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
|
||||
class MyLinearRegressor(nn.Module):
|
||||
def __init__(self, vlen):
|
||||
super(MyLinearRegressor, self).__init__()
|
||||
self.register_parameter(name='w', param=torch.nn.Parameter(
|
||||
torch.zeros(vlen, dtype=torch.double, requires_grad=True)))
|
||||
self.register_parameter(name='b', param=torch.nn.Parameter(
|
||||
torch.tensor(0., dtype=torch.double, requires_grad=True)))
|
||||
|
||||
def forward(self, x):
|
||||
return self.b + x @ self.w
|
||||
|
||||
regressor = MyLinearRegressor(3)
|
||||
regressor(torch.tensor([0.3, 0.4, 1.0], dtype=torch.double))
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:results:
|
||||
# Out[11]:
|
||||
: tensor(0., dtype=torch.float64, grad_fn=<AddBackward0>)
|
||||
:end:
|
||||
|
||||
**** Gotowy moduł w PyTorchu
|
||||
|
||||
Możemy skorzystać z ogólniejszej konstrukcji — warstwy liniowej (ale,
|
||||
uwaga!, na wyjściu będzie wektor jednoelementowy).
|
||||
|
||||
#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
|
||||
regressor = torch.nn.Linear(in_features=3, out_features=1, bias=True)
|
||||
regressor(torch.tensor([0.3, 0.4, 1.0]))
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:results:
|
||||
# Out[18]:
|
||||
: tensor([0.1882], grad_fn=<AddBackward0>)
|
||||
:end:
|
||||
|
||||
*** Zastosowania
|
||||
|
||||
Bezpośrednio możemy zastosować do zadania regresji dla tekstu (np.
|
||||
przewidywanie roku publikacji tekstu).
|
||||
|
||||
[[./img-linear-regression.png]]
|
||||
|
||||
W połączeniu z sigmoidą otrzymamy regresją logistyczną, np. dla zadania klasyfikacji tekstu:
|
||||
|
||||
$$p(c|\vec{x}) = \sigma(w_0 + w_1x_1 + w_2x_2 + \dots + w_{|V|}x_{|v})
|
||||
= \sigma(\Sigma_{i=0}^{|V|} w_ix_i) = \sigma(\vec{w}\vec{x})$$
|
||||
|
||||
[[./img-logistic-regression.png]]
|
||||
|
||||
Tak sieć będzie aktywowana dla tekstu _aardvark in Aachen_:
|
||||
|
||||
[[./img-logistic-regression-aardvark.png]]
|
||||
|
||||
Regresje logistyczną (liniową zresztą też) dla tekstu możemy połączyć z trikiem z haszowaniem:
|
||||
|
||||
\[p(c|\vec{x}) = \sigma(w_0 + w_1x_1 + w_2x_2 + \dots + w_{2^b}x_{2^b})
|
||||
= \sigma(\Sigma_{i=0}^{2^b} w_ix_i) = \sigma(\vec{w}\vec{x})\] \\
|
||||
{\small hashing function $H : V \rightarrow \{1,\dots,2^b\}$,
|
||||
e.g. MurmurHash3}
|
||||
|
||||
[[./img-logistic-regression-hashing.png]]
|
||||
|
||||
**Pytanie:** Jaki tekst otrzyma na pewno taką samą klasę jak _aardvark in Aachen_?
|
||||
|
||||
*** Wagi
|
||||
|
||||
Liczba wag jest równa rozmiarowi wektora wejściowego (oraz opcjonalnie
|
||||
obciążenie).
|
||||
|
||||
Każda waga odpowiada wyrazowi ze słownika, możemy więc interpretować
|
||||
wagi jako jednowymiarowy parametr opisujący słowa.
|
||||
|
||||
** Warstwa liniowa
|
||||
*** Mnożenie macierzy przez wektor — przypomnienie
|
||||
|
||||
Mnożenie macierzy przez wektor można interpretować jako zrównolegloną operację mnożenie wektora przez wektor.
|
||||
|
||||
$$\left[\begin{array}{ccc}
|
||||
\alert<2>{1.0} & \alert<2>{-2.0} & \alert<2>{3.0} \\
|
||||
\alert<3>{-2.0} & \alert<3>{0.0} & \alert<3>{10.0}\end{array}\right]
|
||||
\left[\begin{array}{c}
|
||||
\alert<2-3>{1.0} \\
|
||||
\alert<2-3>{-0.5} \\
|
||||
\alert<2-3>{2.0}\end{array}\right]
|
||||
=
|
||||
\left[\begin{array}{c}
|
||||
\uncover<2->{\alert<2>{8.0}} \\
|
||||
\uncover<3->{\alert<3>{18.0}}\end{array}\right]$$
|
||||
|
||||
Jeśli przemnożymy macierz $n \times m$ przez wektor kolumnowy o długości
|
||||
$m$, otrzymamy wektor o rozmiarze $n$.
|
||||
|
||||
W PyTorchu:
|
||||
|
||||
#+BEGIN_SRC ipython :session mysession :results file
|
||||
import torch
|
||||
m = torch.tensor([[1.0, -2.0, 3.0],
|
||||
[-2.0, 0.0, 10.0]])
|
||||
x = torch.tensor([1.0, -0.5, 2.0])
|
||||
m @ x
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
[[file:# Out[19]:
|
||||
: tensor([ 8., 18.])]]
|
||||
|
||||
*** Definicja warstwy liniowej
|
||||
|
||||
Warstwa liniowa polega na przemnożeniu wejścia przez macierz. Można
|
||||
to intepretować jako zrównolegloną operację regresji liniowej (równolegle
|
||||
uczymy czy wykonujemy $n$ regresji liniowych).
|
||||
|
||||
*** PyTorch
|
||||
|
||||
Warstwa liniowa, która przyjmuje wektor o rozmiarze 3 i zwraca wektor o rozmiarze 2.
|
||||
|
||||
#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
|
||||
regressor = torch.nn.Linear(in_features=3, out_features=2, bias=True)
|
||||
regressor(torch.tensor([0.3, 0.4, 1.0]))
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:results:
|
||||
# Out[23]:
|
||||
: tensor([-1.1909, -0.5831], grad_fn=<AddBackward0>)
|
||||
:end:
|
||||
|
||||
*Pytanie*: Ile wag (parametrów) ma powyżej użyta warstwa?
|
||||
|
||||
*** Zastosowania
|
||||
|
||||
Warstwa liniowa jest podstawowym elementem sieci neuronowych —
|
||||
począwszy od prostych sieci neuronowych feed-forward, gdzie warstwy
|
||||
liniowe łączymy używając funkcji aktywacji (np. sigmoidy).
|
||||
|
||||
Oto przykład prostej dwuwarstwowej sieci neuronowej do klasyfikacji binarnej.
|
||||
|
||||
[[./img-feed-forward.png]]
|
||||
|
||||
|
||||
** Softmax
|
||||
|
||||
@ -576,7 +804,6 @@ Przykłady zastosowań:
|
||||
- oznaczanie etykiet nazw w zadaniu NER (nazwisko, kwoty, adresy — najwięcej tokenów będzie miało etykietę pustą, zazwyczaj oznaczaną przez ~O~)
|
||||
|
||||
*** *Pytanie*: czy zadanie tłumaczenia maszynowego można potraktować jako problem etykietowania sekwencji?
|
||||
|
||||
*** Przykładowe wyzwanie NER CoNLL-2003
|
||||
|
||||
Zob. <https://gonito.net/challenge/en-ner-conll-2003>.
|
||||
@ -590,7 +817,6 @@ W pierwszym polu oczekiwany wynik zapisany za pomocą notacji *BIO*.
|
||||
Jako metrykę używamy F1 (z pominięciem tagu ~O~)
|
||||
|
||||
*** Metryka F1
|
||||
|
||||
*** Etykietowanie za pomocą klasyfikacji wieloklasowej
|
||||
|
||||
Można potraktować problem etykietowania dokładnie tak jak problem
|
||||
@ -598,7 +824,7 @@ klasyfikacji wieloklasowej (jak w przykładzie klasyfikacji dyscyplin
|
||||
sportowych powyżej), tzn. rozkład prawdopodobieństwa możliwych etykiet
|
||||
uzyskujemy poprzez zastosowanie prostej warstwy liniowej i funkcji softmax:
|
||||
|
||||
$$p(l^k=i) = s(\vec{w}\vec{v}(t^k))_i = \frac{e^{\vec{w}\vec{v}(t^k)}}{Z},$$
|
||||
$$p(l^k=j) = s(W\vec{v}(t^k))_j = \frac{e^{(W\vec{v}(t^k))_j}}{Z},$$
|
||||
|
||||
gdzie $\vec{v}(t^k)$ to reprezentacja wektorowa tokenu $t^k$.
|
||||
Zauważmy, że tutaj (w przeciwieństwie do klasyfikacji całego tekstu)
|
||||
@ -626,7 +852,7 @@ Za pomocą wektora można przedstawić nie pojedynczy token $t^k$, lecz
|
||||
cały kontekst, dla /okna/ o długości $c$ będzie to kontekst $t^{k-c},\dots,t^k,\dots,t^{k+c}$.
|
||||
Innymi słowy klasyfikujemy token na podstawie jego samego oraz jego kontekstu:
|
||||
|
||||
$$p(l^k=i) = \frac{e^{\vec{w}\vec{v}(t^{k-c},\dots,t^k,\dots,t^{k+c})}}{Z_k}.$$
|
||||
$$p(l^k=j) = \frac{e^{(W\vec{v}(t^{k-c},\dots,t^k,\dots,t^{k+c}))_j}}{Z_k}.$$
|
||||
|
||||
Zauważmy, że w tej metodzie w ogóle nie rozpatrujemy sensowności
|
||||
sekwencji wyjściowej (etykiet), np. może być bardzo mało
|
||||
@ -635,7 +861,12 @@ prawdopodobne, że bezpośrednio po nazwisku występuje data.
|
||||
Napiszmy wzór określający prawdopodobieństwo całej sekwencji, nie
|
||||
tylko pojedynczego tokenu. Na razie będzie to po prostu iloczyn poszczególnych wartości.
|
||||
|
||||
$$p(l) = \prod_{k=1}^K \frac{e^{\vec{w}\vec{v}(t^{k-c},\dots,t^k,\dots,t^{k+c})}}{Z_k} = \frac{e^{\sum_{k=1}^K\vec{w}\vec{v}(t^{k-c},\dots,t^k,\dots,t^{k+c})}}{\prod_{k=1}^K Z_k}$$
|
||||
$$p(l) = \prod_{k=1}^K \frac{e^{(W\vec{v}(t^{k-c},\dots,t^k,\dots,t^{k+c}))_{l^k}}}{Z_k} = \frac{e^{\sum_{k=1}^K (W\vec{v}(t^{k-c},\dots,t^k,\dots,t^{k+c}))_{l^k}}}{\prod_{k=1}^K Z_k}$$
|
||||
|
||||
Reprezentacja kontekstu może być funkcją embeddingów wyrazów
|
||||
(zakładamy, że embedding nie zależy od pozycji słowa).
|
||||
|
||||
$$\vec{v}(t^{k-c},\dots,t^k,\dots,t^{k+c}) = f(\vec{E}(t^{k-c}),\dots,\vec{E}(t^k),\dots,\vec{E}({t^{k+c}})$$
|
||||
|
||||
** Warunkowe pola losowe
|
||||
|
||||
@ -646,13 +877,178 @@ graf wyrażający „następowanie po” (czyli sekwencje). Do poprzedniego
|
||||
wzoru dodamy składnik $V_{i,j}$ (który można interpretować jako
|
||||
macierz) określający prawdopodobieństwo, że po etykiecie o numerze $i$ wystąpi etykieta o numerze $j$.
|
||||
|
||||
*** *Pytanie*: Czy macierz $V$ musi być symetryczna? Czy $V_{i,j} = V_{j,i}$? Czy jakieś specjalne wartości występują na przekątnej?
|
||||
*Pytanie*: Czy macierz $V$ musi być symetryczna? Czy $V_{i,j} = V_{j,i}$? Czy jakieś specjalne wartości występują na przekątnej?
|
||||
|
||||
Macierz $V$ wraz z wektorem $\vec{w}$ będzie stanowiła wyuczalne wagi w naszym modelu.
|
||||
Macierz $V$ wraz z macierzą $W$ będzie stanowiła wyuczalne wagi w naszym modelu.
|
||||
|
||||
Wartości $V_{i,j}$ nie stanowią bezpośrednio prawdopodobieństwa, mogą
|
||||
przyjmować dowolne wartości, które będę normalizowane podobnie jak to się dzieje w funkcji Softmax.
|
||||
przyjmować dowolne wartości, które będę normalizowane podobnie, tak jak to się dzieje w funkcji Softmax.
|
||||
|
||||
W takiej wersji warunkowych pól losowych otrzymamy następujący wzór na prawdopodobieństwo całej sekwencji.
|
||||
|
||||
$$p(l) = \frac{e^{\sum_{k=1}^K\vec{w}\vec{v}(t^{k-c},\dots,t^k,\dots,t^{k+c}) + \sum_{k=1}^{K-1} V_{l_k,l_{k+1}}}}{\prod_{k=1}^K Z_k}$$
|
||||
$$p(l) = \frac{e^{\sum_{k=1}^K (W\vec{v}(t^{k-c},\dots,t^k,\dots,t^{k+c}))_{l^k} + \sum_{k=1}^{K-1} V_{l^k,l^{k+1}}}}{\prod_{k=1}^K Z_k}$$
|
||||
|
||||
** Algorytm Viterbiego
|
||||
|
||||
W czasie inferencji mamy ustalone wagi funkcji $\vec{v}(\dots)$ oraz
|
||||
macierz $V$. Szukamy sekwencji $y$ która maksymalizuje prawdopodobieństwo estymowane przez model:
|
||||
|
||||
$$y = \underset{l}{\operatorname{argmax}} \hat{p}(l|t^1,\dots,t^K)$$
|
||||
|
||||
Naiwne podejście polegające na obliczeniu prawdopodobieństw wszystkich możliwych sekwencji miałoby
|
||||
nieakceptowalną złożoność czasową $O(|L|^K)$.
|
||||
|
||||
Na szczęście, możemy użyć *algorytmu Viterbiego* o lepszej złożoności
|
||||
obliczeniowej, algorytmu opartego na idei programowania dynamicznego.
|
||||
|
||||
W algorytmie będziemy wypełniać dwuwymiarowe tabele $s[i, j]$ i $b[i, j]$:
|
||||
|
||||
- $s[i, j]$ — będzie zawierać maksymalne prawdopodobieństwo (właściwie: nieznormalizowaną wartość,
|
||||
która jest monotoniczna względem prawdopodobieństwa)
|
||||
dla ciągów o długości $i$ zakończonych etykietą $l_j$,
|
||||
- $b[i, j]$ — będzie zawierać „wskaźnik” wsteczny (/backpointer/) do podciągu o długości $i-1$, dla którego
|
||||
razem z $l_j$ jest osiągana maksymalna wartość $s[i, j]$.
|
||||
|
||||
Inicjalizacja:
|
||||
|
||||
- $s[1, j] = (W\vec{v}(t^k,\dots,t^{k+c}))_j$,
|
||||
- $b[1, j]$ — nie musimy wypełniać tej wartości.
|
||||
|
||||
Dla $i > 1$ i dla każdego $j$ będziemy teraz szukać:
|
||||
|
||||
$$\underset{q \in \{1,\dots,|V|\}}{\operatorname{max}} s[i-1, q] + (W\vec{v}(t^{k-c},\dots,t^k,\dots,t^{k+c}))_j + V_{q, j}$$
|
||||
|
||||
Tę wartość przypiszemy do $s[i, j]$, z kolei do $b[i, j]$ — indeks
|
||||
$q$, dla którego ta największa wartość jest osiągnięta.
|
||||
|
||||
Najpierw obliczenia wykonujemy wprzód wypełniając tabelę dla coraz większych wartości $j$.
|
||||
W ten sposób otrzymamy największą wartość (nieznormalizowanego) prawdopodobieństwa:
|
||||
|
||||
$$\underset{q \in \{1,\dots,|V|\}}{\operatorname{max}} s[K, q]$$
|
||||
|
||||
oraz ostatnią etykietę:
|
||||
|
||||
$$y^K = \underset{q \in \{1,\dots,|V|\}}{\operatorname{argmax}} s[K, q]$$
|
||||
|
||||
Aby uzyskać cały ciąg, kierujemy się /wstecz/ używając wskaźników:
|
||||
|
||||
$$y^i = b[i, y^{i+1}]$$
|
||||
|
||||
*** Złożoność obliczeniowa
|
||||
|
||||
Zauważmy, że rozmiar tabel $s$ i $b$ wynosi $K \times |L|$, a koszt
|
||||
wypełnienia każdej komórki to $|L|$, a zatem złożoność algorytmu jest wielomianowa:
|
||||
$O(K|L|^2)$.
|
||||
|
||||
*Pytanie:* Czy gdyby uzależnić etykietę nie tylko od poprzedniej
|
||||
etykiety, lecz również od jeszcze wcześniejszej, to złożoność
|
||||
obliczeniowa byłaby taka sama?
|
||||
|
||||
*** Przykład
|
||||
|
||||
Rozpatrzmy uproszczony przykład tagowania częściami mowy:
|
||||
|
||||
- słownik $V=\{\mathit{Ala}, \mathit{powieść}, \mathit{ma}\}$,
|
||||
- zbiór etykiet $L=\{\mathit{C}, \mathit{P}, \mathit{R}\}$,
|
||||
- kontekst nie jest uwzględniany ($c = 0$).
|
||||
|
||||
(To, że liczba słów i etykiet jest taka sama, jest przypadkowe, nie ma znaczenia)
|
||||
|
||||
Zakładamy, że słowa reprezentujemy wektorowo za pomocą prostej reprezentacji one-hot.
|
||||
|
||||
#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer
|
||||
import torch
|
||||
|
||||
vocab = ['Ala', 'ma', 'powieść']
|
||||
labels = ['C', 'P', 'R']
|
||||
|
||||
onehot = {
|
||||
'Ala': torch.tensor([1., 0., 0.]),
|
||||
'ma': torch.tensor([0., 1., 0.]),
|
||||
'powieść': torch.tensor([0., 0., 1.])
|
||||
}
|
||||
|
||||
onehot['ma']
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:results:
|
||||
# Out[2]:
|
||||
: tensor([0., 1., 0.])
|
||||
:end:
|
||||
|
||||
Przyjmijmy, że w czasie uczenia zostały ustalone następujące wartości
|
||||
macierzy $W$ i $V$ (samego procesu uczenia nie pokazujemy tutaj):
|
||||
|
||||
#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
|
||||
matrixW = torch.tensor(
|
||||
[[-1., 3.0, 3.0],
|
||||
[0., 2.0, -2.0],
|
||||
[4., -2.0, 3.0]])
|
||||
|
||||
# rozkład prawdopodobieństwa, gdyby patrzeć tylko na słowo
|
||||
nn.functional.softmax(matrixW @ onehot['powieść'], dim=0)
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:results:
|
||||
# Out[9]:
|
||||
: tensor([0.4983, 0.0034, 0.4983])
|
||||
:end:
|
||||
|
||||
|
||||
#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
|
||||
matrixV = torch.tensor(
|
||||
[[-0.5, 1.5, 2.0],
|
||||
[0.5, 0.8, 2.5],
|
||||
[2.0, 0.8, 0.2]])
|
||||
|
||||
# co występuje po przymiotniku? - rozkład prawdopodobieństwa
|
||||
nn.functional.softmax(matrixV[1], dim=0)
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:results:
|
||||
# Out[10]:
|
||||
: tensor([0.1027, 0.1386, 0.7587])
|
||||
:end:
|
||||
|
||||
Algorytm Viterbiego:
|
||||
|
||||
#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer
|
||||
d = ['Ala', 'ma', 'powieść']
|
||||
|
||||
s = []
|
||||
b = []
|
||||
|
||||
# inicjalizacja
|
||||
s.append(matrixW @ onehot[d[0]])
|
||||
b.append(None)
|
||||
|
||||
# wprzód
|
||||
i = 1
|
||||
os = []
|
||||
ob = []
|
||||
for j in range(0, len(labels)):
|
||||
z = s[i-1] + matrixV[:,j] + matrixW @ onehot[d[i]]
|
||||
|
||||
ns = torch.max(z).item()
|
||||
nb = torch.argmax(z).item()
|
||||
|
||||
os.append(ns)
|
||||
ob.append(nb)
|
||||
|
||||
os
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:results:
|
||||
# Out[16]:
|
||||
: [4.0, 3.5, 4.5]
|
||||
:end:
|
||||
|
BIN
wyk/img-feed-forward.png
Normal file
BIN
wyk/img-feed-forward.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
BIN
wyk/img-linear-regression.png
Normal file
BIN
wyk/img-linear-regression.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
BIN
wyk/img-logistic-regression-aardvark.png
Normal file
BIN
wyk/img-logistic-regression-aardvark.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
BIN
wyk/img-logistic-regression-hashing.png
Normal file
BIN
wyk/img-logistic-regression-hashing.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
BIN
wyk/img-logistic-regression.png
Normal file
BIN
wyk/img-logistic-regression.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
Loading…
Reference in New Issue
Block a user