forked from pms/uczenie-maszynowe
536 lines
13 KiB
Plaintext
536 lines
13 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"### Uczenie maszynowe\n",
|
|
"# 7. Metody optymalizacji"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"## 7.1. Warianty metody gradientu prostego\n",
|
|
"\n",
|
|
"* Batch gradient descent\n",
|
|
"* Stochastic gradient descent\n",
|
|
"* Mini-batch gradient descent"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "subslide"
|
|
}
|
|
},
|
|
"source": [
|
|
"### _Batch gradient descent_\n",
|
|
"\n",
|
|
"* Klasyczna wersja metody gradientu prostego\n",
|
|
"* Obliczamy gradient funkcji kosztu względem całego zbioru treningowego:\n",
|
|
" $$ \\theta := \\theta - \\alpha \\cdot \\nabla_\\theta J(\\theta) $$\n",
|
|
"* Dlatego może działać bardzo powoli\n",
|
|
"* Nie można dodawać nowych przykładów na bieżąco w trakcie trenowania modelu (*online learning*)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "subslide"
|
|
}
|
|
},
|
|
"source": [
|
|
"### *Stochastic gradient descent* (SGD)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"source": [
|
|
"#### Algorytm\n",
|
|
"\n",
|
|
"Powtórz określoną liczbę razy (liczba epok):\n",
|
|
" 1. Randomizuj dane treningowe\n",
|
|
" 1. Powtórz dla każdego przykładu $i = 1, 2, \\ldots, m$:\n",
|
|
" $$ \\theta := \\theta - \\alpha \\cdot \\nabla_\\theta \\, J \\! \\left( \\theta, x^{(i)}, y^{(i)} \\right) $$"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "notes"
|
|
}
|
|
},
|
|
"source": [
|
|
"**Randomizacja danych** to losowe potasowanie przykładów uczących (wraz z odpowiedziami)."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "subslide"
|
|
}
|
|
},
|
|
"source": [
|
|
"#### SGD - zalety\n",
|
|
"\n",
|
|
"* Dużo szybszy niż _batch gradient descent_\n",
|
|
"* Można dodawać nowe przykłady na bieżąco w trakcie trenowania (*online learning*)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "subslide"
|
|
}
|
|
},
|
|
"source": [
|
|
"#### SGD\n",
|
|
"\n",
|
|
"* Częsta aktualizacja parametrów z dużą wariancją:\n",
|
|
"\n",
|
|
"<img src=\"http://ruder.io/content/images/2016/09/sgd_fluctuation.png\" style=\"margin: auto;\" width=\"50%\" />\n",
|
|
"\n",
|
|
"* Z jednej strony dzięki temu nie utyka w złych minimach lokalnych, ale z drugiej strony może „wyskoczyć” z dobrego minimum"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "subslide"
|
|
}
|
|
},
|
|
"source": [
|
|
"### _Mini-batch gradient descent_"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"source": [
|
|
"#### Algorytm\n",
|
|
"\n",
|
|
"1. Ustal rozmiar \"paczki/wsadu\" (*batch*) $b \\leq m$.\n",
|
|
"2. Powtórz określoną liczbę razy (liczba epok):\n",
|
|
" 1. Powtórz dla każdego batcha (czyli dla $i = 1, 1 + b, 1 + 2 b, \\ldots$):\n",
|
|
" $$ \\theta := \\theta - \\alpha \\cdot \\nabla_\\theta \\, J \\left( \\theta, x^{(i : i+b)}, y^{(i : i+b)} \\right) $$"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "subslide"
|
|
}
|
|
},
|
|
"source": [
|
|
"#### _Mini-batch gradient descent_\n",
|
|
"\n",
|
|
"* Kompromis między _batch gradient descent_ i SGD\n",
|
|
"* Stabilniejsza zbieżność dzięki redukcji wariancji aktualizacji parametrów\n",
|
|
"* Szybszy niż klasyczny _batch gradient descent_\n",
|
|
"* Typowa wielkość batcha: między kilka a kilkaset przykładów\n",
|
|
" * Im większy batch, tym bliżej do BGD; im mniejszy batch, tym bliżej do SGD\n",
|
|
" * BGD i SGD można traktować jako odmiany MBGD dla $b = m$ i $b = 1$"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "skip"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Mini-batch gradient descent - przykładowa implementacja\n",
|
|
"\n",
|
|
"def MiniBatchSGD(h, fJ, fdJ, theta, X, y, \n",
|
|
" alpha=0.001, maxEpochs=1.0, batchSize=100, \n",
|
|
" logError=True):\n",
|
|
" errorsX, errorsY = [], []\n",
|
|
" \n",
|
|
" m, n = X.shape\n",
|
|
" start, end = 0, batchSize\n",
|
|
" \n",
|
|
" maxSteps = (m * float(maxEpochs)) / batchSize\n",
|
|
" for i in range(int(maxSteps)):\n",
|
|
" XBatch, yBatch = X[start:end,:], y[start:end,:]\n",
|
|
"\n",
|
|
" theta = theta - alpha * fdJ(h, theta, XBatch, yBatch)\n",
|
|
" \n",
|
|
" if logError:\n",
|
|
" errorsX.append(float(i*batchSize)/m)\n",
|
|
" errorsY.append(fJ(h, theta, XBatch, yBatch).item())\n",
|
|
" \n",
|
|
" if start + batchSize < m:\n",
|
|
" start += batchSize\n",
|
|
" else:\n",
|
|
" start = 0\n",
|
|
" end = min(start + batchSize, m)\n",
|
|
" \n",
|
|
" return theta, (errorsX, errorsY)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "subslide"
|
|
}
|
|
},
|
|
"source": [
|
|
"### Wady klasycznej metody gradientu prostego, czyli dlaczego potrzebujemy optymalizacji\n",
|
|
"\n",
|
|
"* Trudno dobrać właściwą szybkość uczenia (*learning rate*)\n",
|
|
"* Jedna ustalona wartość stałej uczenia się dla wszystkich parametrów\n",
|
|
"* Funkcja kosztu dla sieci neuronowych nie jest wypukła, więc uczenie może utknąć w złym minimum lokalnym lub punkcie siodłowym"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"## 7.2. Algorytmy optymalizacji metody gradientu\n",
|
|
"\n",
|
|
"* Momentum\n",
|
|
"* Nesterov Accelerated Gradient\n",
|
|
"* Adagrad\n",
|
|
"* Adadelta\n",
|
|
"* RMSprop\n",
|
|
"* Adam\n",
|
|
"* Nadam\n",
|
|
"* AMSGrad"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "subslide"
|
|
}
|
|
},
|
|
"source": [
|
|
"### Momentum\n",
|
|
"\n",
|
|
"* SGD źle radzi sobie w „wąwozach” funkcji kosztu\n",
|
|
"* Momentum rozwiązuje ten problem przez dodanie współczynnika $\\gamma$, który można trakować jako „pęd” spadającej piłki:\n",
|
|
" $$ v_t := \\gamma \\, v_{t-1} + \\alpha \\, \\nabla_\\theta J(\\theta) $$\n",
|
|
" $$ \\theta := \\theta - v_t $$"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "subslide"
|
|
}
|
|
},
|
|
"source": [
|
|
"### Przyspieszony gradient Nesterova (*Nesterov Accelerated Gradient*, NAG)\n",
|
|
"\n",
|
|
"* Momentum czasami powoduje niekontrolowane rozpędzanie się piłki, przez co staje się „mniej sterowna”\n",
|
|
"* Nesterov do piłki posiadającej pęd dodaje „hamulec”, który spowalnia piłkę przed wzniesieniem:\n",
|
|
" $$ v_t := \\gamma \\, v_{t-1} + \\alpha \\, \\nabla_\\theta J(\\theta - \\gamma \\, v_{t-1}) $$\n",
|
|
" $$ \\theta := \\theta - v_t $$"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "subslide"
|
|
}
|
|
},
|
|
"source": [
|
|
"### Adagrad\n",
|
|
"\n",
|
|
"* “<b>Ada</b>ptive <b>grad</b>ient”\n",
|
|
"* Adagrad dostosowuje współczynnik uczenia (*learning rate*) do parametrów: zmniejsza go dla cech występujących częściej, a zwiększa dla występujących rzadziej:\n",
|
|
"* Świetny do trenowania na rzadkich (*sparse*) zbiorach danych\n",
|
|
"* Wada: współczynnik uczenia może czasami gwałtownie maleć\n",
|
|
"* Wyniki badań pokazują, że często **starannie** dobrane $\\alpha$ daje lepsze wyniki na zbiorze testowym"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "subslide"
|
|
}
|
|
},
|
|
"source": [
|
|
"### Adadelta i RMSprop\n",
|
|
"* Warianty algorytmu Adagrad, które radzą sobie z problemem gwałtownych zmian współczynnika uczenia"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "subslide"
|
|
}
|
|
},
|
|
"source": [
|
|
"### Adam\n",
|
|
"\n",
|
|
"* “<b>Ada</b>ptive <b>m</b>oment estimation”\n",
|
|
"* Łączy zalety algorytmów RMSprop i Momentum\n",
|
|
"* Można go porównać do piłki mającej ciężar i opór\n",
|
|
"* Obecnie jeden z najpopularniejszych algorytmów optymalizacji"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "subslide"
|
|
}
|
|
},
|
|
"source": [
|
|
"### Nadam\n",
|
|
"* “<b>N</b>esterov-accelerated <b>ada</b>ptive <b>m</b>oment estimation”\n",
|
|
"* Łączy zalety algorytmów Adam i Nesterov Accelerated Gradient"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "subslide"
|
|
}
|
|
},
|
|
"source": [
|
|
"### AMSGrad\n",
|
|
"* Wariant algorytmu Adam lepiej dostosowany do zadań takich jak rozpoznawanie obiektów czy tłumaczenie maszynowe"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "subslide"
|
|
}
|
|
},
|
|
"source": [
|
|
"<img src=\"contours_evaluation_optimizers.gif\" style=\"margin: auto;\" width=\"60%\" />"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "subslide"
|
|
}
|
|
},
|
|
"source": [
|
|
"<img src=\"saddle_point_evaluation_optimizers.gif\" style=\"margin: auto;\" width=\"60%\" />"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"## 7.3. Metody zbiorcze"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "subslide"
|
|
}
|
|
},
|
|
"source": [
|
|
" * **Metody zbiorcze** (*ensemble methods*) używają połączonych sił wielu modeli uczenia maszynowego w celu uzyskania lepszej skuteczności niż mogłaby być osiągnięta przez każdy z tych modeli z osobna."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"source": [
|
|
" * Na metodę zbiorczą składa się:\n",
|
|
" * dobór modeli\n",
|
|
" * sposób agregacji wyników"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"source": [
|
|
" * Warto zastosować randomizację, czyli przetasować zbiór uczący przed trenowaniem każdego modelu."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"### Uśrednianie prawdopodobieństw"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"source": [
|
|
"#### Przykład\n",
|
|
"\n",
|
|
"Mamy 3 modele, które dla klas $c=1, 2, 3, 4, 5$ zwróciły prawdopodobieństwa:\n",
|
|
"\n",
|
|
"* $M_1$: [0.10, 0.40, **0.50**, 0.00, 0.00]\n",
|
|
"* $M_2$: [0.10, **0.60**, 0.20, 0.00, 0.10]\n",
|
|
"* $M_3$: [0.10, 0.30, **0.40**, 0.00, 0.20]\n",
|
|
"\n",
|
|
"Która klasa zostanie wybrana według średnich prawdopodobieństw dla każdej klasy?"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "subslide"
|
|
}
|
|
},
|
|
"source": [
|
|
"Średnie prawdopodobieństwo: [0.10, **0.43**, 0.36, 0.00, 0.10]\n",
|
|
"\n",
|
|
"Została wybrana klasa $c = 2$"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"### Głosowanie klas"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"source": [
|
|
"#### Przykład\n",
|
|
"\n",
|
|
"Mamy 3 modele, które dla klas $c=1, 2, 3, 4, 5$ zwróciły prawdopodobieństwa:\n",
|
|
"\n",
|
|
"* $M_1$: [0.10, 0.40, **0.50**, 0.00, 0.00]\n",
|
|
"* $M_2$: [0.10, **0.60**, 0.20, 0.00, 0.10]\n",
|
|
"* $M_3$: [0.10, 0.30, **0.40**, 0.00, 0.20]\n",
|
|
"\n",
|
|
"Która klasa zostanie wybrana według głosowania?"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "subslide"
|
|
}
|
|
},
|
|
"source": [
|
|
"Liczba głosów: [0, 1, **2**, 0, 0]\n",
|
|
"\n",
|
|
"Została wybrana klasa $c = 3$"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"### Inne metody zbiorcze\n",
|
|
"\n",
|
|
" * Bagging\n",
|
|
" * Boostng\n",
|
|
" * Stacking\n",
|
|
" \n",
|
|
"https://towardsdatascience.com/ensemble-methods-bagging-boosting-and-stacking-c9214a10a205"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"celltoolbar": "Slideshow",
|
|
"kernelspec": {
|
|
"display_name": "Python 3 (ipykernel)",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.10.6"
|
|
},
|
|
"livereveal": {
|
|
"start_slideshow_at": "selected",
|
|
"theme": "white"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 4
|
|
}
|