2.4 Matematinė analizė
Ilgą laiką apskritimo ploto apskaičiavimas išliko paslaptimi. Tada senovės Graikijoje matematikas Archimedas sugalvojo gudrią idėją – į apskritimo vidų įbrėžti daugiakampių seką su vis didesniu viršūnių skaičiumi (2.4.1 pav.). Daugiakampiui su viršūnių gauname trikampių. Kiekvieno trikampio aukštis artėja prie spindulio , kai apskritimą skaidome vis smulkiau. Tuo pat metu jo pagrindas artėja prie , nes lanko ir sekantės santykis artėja prie 1, kai viršūnių skaičius didelis. Taigi daugiakampio plotas artėja prie .
2.4.1 pav. Apskritimo ploto radimas kaip ribinė procedūra.
Ši ribinė procedūra yra tiek diferencialinio, tiek integralinio skaičiavimo šaknis. Pirmasis gali pasakyti, kaip padidinti arba sumažinti funkcijos reikšmę keičiant jos argumentus. Tai praverčia sprendžiant optimizavimo uždavinius, su kuriais susiduriame giliajame mokyme, kai pakartotinai atnaujiname savo parametrus, kad sumažintume nuostolių funkciją. Optimizavimas nagrinėja, kaip pritaikyti modelius apmokymo duomenims, o matematinė analizė yra svarbiausia jo būtina sąlyga. Tačiau nepamirškite, kad mūsų galutinis tikslas yra gerai veikti su anksčiau nematytais duomenimis. Ši problema vadinama generalizacija ir bus pagrindinis kitų skyrių dėmesio objektas.
%matplotlib inline
from d2l import mxnet as d2l
from matplotlib_inline import backend_inline
from mxnet import np, npx
npx.set_np()
%matplotlib inline
from d2l import torch as d2l
from matplotlib_inline import backend_inline
import numpy as np
%matplotlib inline
from d2l import tensorflow as d2l
from matplotlib_inline import backend_inline
import numpy as np
%matplotlib inline
from d2l import jax as d2l
from matplotlib_inline import backend_inline
import numpy as np
2.4.1 Išvestinės ir diferencijavimas
Paprasčiau tariant, išvestinė yra funkcijos kitimo greitis atsižvelgiant į jos argumentų pokyčius. Išvestinės gali pasakyti, kaip sparčiai nuostolių funkcija didėtų ar mažėtų, jei kiekvieną parametrą padidintume arba sumažintume be galo mažu dydžiu. Formaliai funkcijoms , atvaizduojančioms skaliarus į skaliarus, išvestinė taške apibrėžiama kaip
(**
**)
Šis narys dešinėje pusėje vadinamas riba ir parodo, kas nutinka išraiškos reikšmei, kai nurodytas kintamasis artėja prie tam tikros reikšmės. Ši riba parodo, prie ko konverguoja pokyčio ir funkcijos reikšmės pokyčio santykis, kai jo dydį mažiname iki nulio.
Kai egzistuoja, sakoma, kad yra diferencijuojama taške ; ir kai egzistuoja visiems tam tikroje aibėje, pvz., intervale , sakome, kad yra diferencijuojama šioje aibėje. Ne visos funkcijos yra diferencijuojamos, įskaitant daugelį tų, kurias norime optimizuoti, pvz., tikslumą ir plotą po imtuvo darbo charakteristikos kreive (angl. area under the receiving operating characteristic, AUC). Tačiau kadangi nuostolių išvestinės skaičiavimas yra lemiamas žingsnis beveik visuose giliųjų neuroninių tinklų apmokymo algoritmuose, dažnai vietoj to optimizuojame diferencijuojamą pakaitinę funkciją.
Išvestinę galime interpretuoti kaip momentinį kitimo greitį atžvilgiu. Sudarykime šiek tiek intuicijos pavyzdžiu. (Apibrėžkime .)
def f(x):
return 3 * x ** 2 - 4 * x
def f(x):
return 3 * x ** 2 - 4 * x
def f(x):
return 3 * x ** 2 - 4 * x
def f(x):
return 3 * x ** 2 - 4 * x
Nustatę , matome, kad (artėja prie , kai artėja prie .) Nors šiam eksperimentui trūksta matematinio įrodymo griežtumo, greitai matome, kad iš tiesų .
for h in 10.0**np.arange(-1, -6, -1):
print(f'h={h:.5f}, numerical limit={(f(1+h)-f(1))/h:.5f}')
Yra keletas ekvivalenčių išvestinių žymėjimo sutarčių. Kai duota , šios išraiškos yra ekvivalenčios:
kur simboliai ir yra diferencijavimo operatoriai. Toliau pateikiame kai kurių dažnų funkcijų išvestines:
Funkcijos, sudarytos iš diferencijuojamų funkcijų, dažnai pačios yra diferencijuojamos. Šios taisyklės praverčia dirbant su bet kurių diferencijuojamų funkcijų ir bei konstantos kompozicijomis.
Pasinaudoję tuo, galime pritaikyti taisykles ir rasti išvestinę:
Įrašę , matome, kad iš tiesų išvestinė šioje vietoje lygi . Atkreipkite dėmesį, kad išvestinės mums pasako funkcijos nuolydį tam tikroje vietoje.
2.4.2 Vizualizavimo priemonės
Funkcijų nuolydžius galime vizualizuoti naudodami matplotlib biblioteką.
Turime apibrėžti keletą funkcijų.
Kaip rodo pavadinimas, use_svg_display
nurodo matplotlib išvesti grafiką
SVG formatu, kad vaizdai būtų ryškesni.
Komentaras #@save yra speciali modifikacija,
leidžianti išsaugoti bet kurią funkciją,
klasę ar kitą kodo bloką d2l pakete,
kad galėtume jį iškviesti vėliau
nekartodami kodo,
pvz., per d2l.use_svg_display().
def use_svg_display(): #@save
"""Use the svg format to display a plot in Jupyter."""
backend_inline.set_matplotlib_formats('svg')
Patogiai galime nustatyti paveikslų dydžius funkcija set_figsize.
Kadangi importo sakinys from matplotlib import pyplot as plt
d2l pakete buvo pažymėtas #@save, galime kviesti d2l.plt.
def set_figsize(figsize=(3.5, 2.5)): #@save
"""Set the figure size for matplotlib."""
use_svg_display()
d2l.plt.rcParams['figure.figsize'] = figsize
Funkcija set_axes gali susieti ašis
su savybėmis, įskaitant užrašus, intervalus
ir mastelius.
#@save
def set_axes(axes, xlabel, ylabel, xlim, ylim, xscale, yscale, legend):
"""Set the axes for matplotlib."""
axes.set_xlabel(xlabel), axes.set_ylabel(ylabel)
axes.set_xscale(xscale), axes.set_yscale(yscale)
axes.set_xlim(xlim), axes.set_ylim(ylim)
if legend:
axes.legend(legend)
axes.grid()
Naudodami šias tris funkcijas, galime apibrėžti funkciją plot,
kuri uždeda kelias kreives viena ant kitos.
Didelė kodo dalis čia tik užtikrina,
kad įvesčių dydžiai ir formos sutaptų.
#@save
def plot(X, Y=None, xlabel=None, ylabel=None, legend=[], xlim=None,
ylim=None, xscale='linear', yscale='linear',
fmts=('-', 'm--', 'g-.', 'r:'), figsize=(3.5, 2.5), axes=None):
"""Plot data points."""
def has_one_axis(X): # True if X (tensor or list) has 1 axis
return (hasattr(X, "ndim") and X.ndim == 1 or isinstance(X, list)
and not hasattr(X[0], "__len__"))
if has_one_axis(X): X = [X]
if Y is None:
X, Y = [[]] * len(X), X
elif has_one_axis(Y):
Y = [Y]
if len(X) != len(Y):
X = X * len(Y)
set_figsize(figsize)
if axes is None:
axes = d2l.plt.gca()
axes.cla()
for x, y, fmt in zip(X, Y, fmts):
axes.plot(x,y,fmt) if len(x) else axes.plot(y,fmt)
set_axes(axes, xlabel, ylabel, xlim, ylim, xscale, yscale, legend)
Dabar galime nubraižyti funkciją ir jos liestinę taške , kur koeficientas yra liestinės nuolydis.
x = np.arange(0, 3, 0.1)
plot(x, [f(x), 2 * x - 3], 'x', 'f(x)', legend=['f(x)', 'Tangent line (x=1)'])
2.4.3 Dalinės išvestinės ir gradientai
Iki šiol diferencijavome tik vieno kintamojo funkcijas. Giliajame mokyme taip pat reikia dirbti su daugelio kintamųjų funkcijomis. Trumpai pristatome išvestinės sąvokas, taikomas tokioms daugelio kintamųjų funkcijoms.
Tegul yra funkcija su kintamųjų. dalinė išvestinė -ojo jos parametro atžvilgiu yra
Kad apskaičiuotume , galime laikyti konstantomis ir apskaičiuoti išvestinę atžvilgiu. Šios dalinių išvestinių žymėjimo sutartys visos yra dažnos ir reiškia tą patį:
Daugelio kintamųjų funkcijos dalines išvestines visų jos kintamųjų atžvilgiu galime sujungti, kad gautume vektorių, vadinamą funkcijos gradientu. Tarkime, kad funkcijos įvestis yra -matis vektorius , o išvestis – skaliaras. Funkcijos gradientas atžvilgiu yra dalinių išvestinių vektorius:
Kai nėra dviprasmybės, paprastai pakeičiamas . Šios taisyklės praverčia diferencijuojant daugelio kintamųjų funkcijas:
- Visoms turime ir .
- Kvadratinėms matricoms turime ir visų pirma .
Panašiai bet kuriai matricai turime .
2.4.4 Grandinės taisyklė
Giliajame mokyme dominantys gradientai dažnai sunkiai apskaičiuojami, nes dirbame su giliai įdėtomis funkcijomis (funkcijų (funkcijų...)). Laimei, grandinės taisyklė tuo pasirūpina. Grįždami prie vieno kintamojo funkcijų, tarkime, kad ir kad pagrindinės funkcijos ir abi yra diferencijuojamos. Grandinės taisyklė teigia, kad
Grįždami prie daugelio kintamųjų funkcijų, tarkime, kad turi kintamuosius , kur kiekvienas turi kintamuosius , t. y. . Tada grandinės taisyklė teigia, kad
kur yra matrica, kurioje yra vektoriaus išvestinė vektoriaus atžvilgiu. Taigi gradiento apskaičiavimui reikia apskaičiuoti vektoriaus ir matricos sandaugą. Tai viena pagrindinių priežasčių, kodėl tiesinė algebra yra tokia neatsiejama dalis kuriant giliojo mokymosi sistemas.
2.4.5 Diskusija
Nors vos paliečiame gilią temą, jau išryškėja keletas sąvokų: pirma, diferencijavimo kompozicijos taisykles galima taikyti įprastai, todėl galime automatiškai skaičiuoti gradientus. Ši užduotis nereikalauja kūrybiškumo, todėl savo pažintines galias galime nukreipti kitur. Antra, skaičiuojant vektorines reikšmes turinčių funkcijų išvestines, reikia dauginti matricas, sekant kintamųjų priklausomybės grafą nuo išvesties iki įvesties. Visų pirma šis grafas einamas tiesiogine kryptimi, kai vertiname funkciją, ir atgaline kryptimi, kai skaičiuojame gradientus. Vėlesniuose skyriuose formaliai pristatysime atgalinį sklidimą – skaičiavimo procedūrą grandinės taisyklei taikyti.
Optimizavimo požiūriu gradientai leidžia mums nustatyti, kaip perkelti modelio parametrus, kad sumažintume nuostolius, o kiekvienam visoje knygoje naudojamų optimizavimo algoritmų žingsniui reikės apskaičiuoti gradientą.
2.4.6 Pratimai
- Iki šiol išvestinių taisykles priėmėme kaip savaime suprantamas. Naudodami apibrėžtį ir ribas, įrodykite savybes (i) , (ii) , (iii) ir (iv) .
- Panašiai įrodykite sandaugos, sumos ir dalmens taisykles iš pirmųjų principų.
- Įrodykite, kad daugiklio konstantos taisyklė išplaukia kaip atskiras sandaugos taisyklės atvejis.
- Apskaičiuokite išvestinę.
- Ką reiškia, kad kuriam nors ? Pateikite funkcijos ir vietos pavyzdį, kuriam tai galėtų galioti.
- Nubraižykite funkciją ir jos liestinę taške .
- Raskite funkcijos gradientą.
- Koks yra funkcijos gradientas? Kas nutinka, kai ?
- Ar galite užrašyti grandinės taisyklę atvejui, kai ir , bei ?
- Kai duota apgręžiama funkcija , apskaičiuokite jos atvirkštinės funkcijos išvestinę. Čia turime, kad ir atvirkščiai . Užuomina: savo išvedime naudokite šias savybes.
