22.3 Vieno kintamojo matematinė analizė

2.4 skyrelis matėme pagrindinius diferencialinio skaičiavimo elementus. Šiame skyriuje giliau panagrinėsime matematinės analizės pagrindus ir tai, kaip ją galime suprasti bei taikyti mašininio mokymo kontekste.

22.3.1 Diferencialinis skaičiavimas

Diferencialinis skaičiavimas iš esmės tiria, kaip funkcijos elgiasi esant mažiems pokyčiams. Kad pamatytume, kodėl tai toks svarbus giliajam mokymuisi, panagrinėkime pavyzdį.

Tarkime, turime gilųjį neuroninį tinklą, kurio parametrai patogumo dėlei sujungti į vieną vektorių w=(w1,…,wn)\mathbf{w} = (w_1, \ldots, w_n). Turėdami mokymo duomenų rinkinį, nagrinėjame savo neuroninio tinklo nuostolius šiame rinkinyje, kuriuos žymėsime L(w)\mathcal{L}(\mathbf{w}).

Ši funkcija yra nepaprastai sudėtinga, nes užkoduoja visų galimų duotos architektūros modelių našumą šiame duomenų rinkinyje, todėl beveik neįmanoma pasakyti, kuri parametrų aibė w\mathbf{w} minimizuos nuostolius. Todėl praktikoje dažnai pradedame parametrus inicializuodami atsitiktinai, o tada iteratyviai darome mažus žingsnius kryptimi, kuria nuostoliai mažėja kuo greičiau.

Taigi klausimas tampa toks, kuris iš pažiūros ne lengvesnis: kaip rasti kryptį, kuria parametrai mažėtų kuo greičiau? Norėdami tai išnagrinėti, pirmiausia panagrinėkime atvejį su vienu parametru: L(w)=L(x)L(\mathbf{w}) = L(x) vienai realiajai reikšmei xx.

Paimkime xx ir pabandykime suprasti, kas nutinka, kai ją šiek tiek pakeičiame į x+ϵx + \epsilon. Jei norite konkretumo, pagalvokite apie tokį skaičių kaip ϵ=0,0000001\epsilon = 0{,}0000001. Kad geriau įsivaizduotume, kas vyksta, nubraižykime pavyzdinės funkcijos f(x)=sin⁡(xx)f(x) = \sin(x^x) grafiką intervale [0,3][0, 3].

%matplotlib inline
from d2l import mxnet as d2l
from IPython import display
from mxnet import np, npx
npx.set_np()

# Plot a function in a normal range
x_big = np.arange(0.01, 3.01, 0.01)
ys = np.sin(x_big**x_big)
d2l.plot(x_big, ys, 'x', 'f(x)')
%matplotlib inline
from d2l import torch as d2l
from IPython import display
import torch
torch.pi = torch.acos(torch.zeros(1)).item() * 2  # Define pi in torch

# Plot a function in a normal range
x_big = torch.arange(0.01, 3.01, 0.01)
ys = torch.sin(x_big**x_big)
d2l.plot(x_big, ys, 'x', 'f(x)')
%matplotlib inline
from d2l import tensorflow as d2l
from IPython import display
import tensorflow as tf
tf.pi = tf.acos(tf.zeros(1)).numpy() * 2  # Define pi in TensorFlow

# Plot a function in a normal range
x_big = tf.range(0.01, 3.01, 0.01)
ys = tf.sin(x_big**x_big)
d2l.plot(x_big, ys, 'x', 'f(x)')

Tokiu dideliu mastu funkcijos elgsena nėra paprasta. Tačiau jei susiaurinsime intervalą iki kažko mažesnio, pavyzdžiui, [1,75;2,25][1{,}75; 2{,}25], matome, kad grafikas tampa gerokai paprastesnis.

# Plot a the same function in a tiny range
x_med = np.arange(1.75, 2.25, 0.001)
ys = np.sin(x_med**x_med)
d2l.plot(x_med, ys, 'x', 'f(x)')
# Plot a the same function in a tiny range
x_med = torch.arange(1.75, 2.25, 0.001)
ys = torch.sin(x_med**x_med)
d2l.plot(x_med, ys, 'x', 'f(x)')
# Plot a the same function in a tiny range
x_med = tf.range(1.75, 2.25, 0.001)
ys = tf.sin(x_med**x_med)
d2l.plot(x_med, ys, 'x', 'f(x)')

Šią mintį išplėtę iki kraštutinumo, priartinę mažytį atkarpą matome, kad elgsena tampa daug paprastesnė: tai tiesiog tiesė.

# Plot a the same function in a tiny range
x_small = np.arange(2.0, 2.01, 0.0001)
ys = np.sin(x_small**x_small)
d2l.plot(x_small, ys, 'x', 'f(x)')
# Plot a the same function in a tiny range
x_small = torch.arange(2.0, 2.01, 0.0001)
ys = torch.sin(x_small**x_small)
d2l.plot(x_small, ys, 'x', 'f(x)')
# Plot a the same function in a tiny range
x_small = tf.range(2.0, 2.01, 0.0001)
ys = tf.sin(x_small**x_small)
d2l.plot(x_small, ys, 'x', 'f(x)')

Tai yra pagrindinis vieno kintamojo matematinės analizės pastebėjimas: pažįstamų funkcijų elgseną pakankamai mažame intervale galima modeliuoti tiese. Tai reiškia, kad daugumai funkcijų pagrįstai galima tikėtis, jog šiek tiek pakeitus funkcijos xx reikšmę, išvestis f(x)f(x) taip pat šiek tiek pasikeis. Vienintelis klausimas, į kurį turime atsakyti: „Kiek didelis išvesties pokytis, palyginti su įvesties pokyčiu? Ar perpus mažesnis? Dvigubai didesnis?“

Taigi galime nagrinėti funkcijos išvesties pokyčio ir nedidelio funkcijos įvesties pokyčio santykį. Formaliai tai galime užrašyti kaip

L(x+ϵ)−L(x)(x+ϵ)−x=L(x+ϵ)−L(x)ϵ.\frac{L(x+\epsilon) - L(x)}{(x+\epsilon) - x} = \frac{L(x+\epsilon) - L(x)}{\epsilon}.

Su tuo jau galima pradėti žaisti kode. Pavyzdžiui, tarkime, žinome, kad L(x)=x2+1701(x−4)3L(x) = x^{2} + 1701(x-4)^3, tada galime pamatyti, kokia yra ši reikšmė taške x=4x = 4, taip.

# Define our function
def L(x):
    return x**2 + 1701*(x-4)**3

# Print the difference divided by epsilon for several epsilon
for epsilon in [0.1, 0.001, 0.0001, 0.00001]:
    print(f'epsilon = {epsilon:.5f} -> {(L(4+epsilon) - L(4)) / epsilon:.5f}')

Jei esame pastabūs, pamatysime, kad šio skaičiaus išvestis įtartinai artima 88. Iš tiesų, mažindami ϵ\epsilon, matysime, kad reikšmė vis labiau artėja prie 88. Taigi galime teisingai daryti išvadą, kad ieškoma reikšmė (laipsnis, kuriuo įvesties pokytis keičia išvestį) taške x=4x=4 turėtų būti 88. Matematikas šį faktą užkoduoja taip

lim⁡ϵ→0L(4+ϵ)−L(4)ϵ=8.\lim_{\epsilon \rightarrow 0}\frac{L(4+\epsilon) - L(4)}{\epsilon} = 8.

Trumpa istorinė atkarpa: pirmaisiais neuroninių tinklų tyrimų dešimtmečiais mokslininkai naudojo šį algoritmą (baigtinių skirtumų metodą), kad įvertintų, kaip nuostolių funkcija keičiasi esant mažam trikdžiui: tiesiog pakeisti parametrus ir pažiūrėti, kaip pasikeitė nuostoliai. Tai skaičiavimo požiūriu neefektyvu: norint pamatyti, kaip vieno kintamojo pokytis paveikė nuostolius, reikia dviejų nuostolių funkcijos įvertinimų. Jei taip bandytume daryti net su menku keliu tūkstančių parametrų skaičiumi, reikėtų kelių tūkstančių tinklo įvertinimų visame duomenų rinkinyje! Ši problema buvo išspręsta tik 1986 m., kai (Rumelhart ir kt., 1988) pristatytas atgalinio sklidimo algoritmas suteikė būdą apskaičiuoti, kaip bet koks kartu pakeistų parametrų pokytis pakeistų nuostolius per tiek pat skaičiavimo laiko, kiek reikia vienai tinklo prognozei visame duomenų rinkinyje.

Grįžkime prie mūsų pavyzdžio: ši reikšmė 88 skiriasi esant skirtingoms xx reikšmėms, todėl prasminga ją apibrėžti kaip xx funkciją. Formaliau, šis nuo reikšmės priklausantis kitimo greitis vadinamas išvestine ir žymimas

dfdx(x)=lim⁡ϵ→0f(x+ϵ)−f(x)ϵ.(22.3.1)\frac{df}{dx}(x) = \lim_{\epsilon \rightarrow 0}\frac{f(x+\epsilon) - f(x)}{\epsilon}. \tag{22.3.1}

Skirtinguose tekstuose išvestinei žymėti naudojami skirtingi žymenys. Pavyzdžiui, visi toliau pateikti žymenys reiškia tą patį:

dfdx=ddxf=f′=∇xf=Dxf=fx.\frac{df}{dx} = \frac{d}{dx}f = f' = \nabla_xf = D_xf = f_x.

Dauguma autorių pasirenka vieną žymenį ir jo laikosi, tačiau ir tai negarantuota. Geriausia mokėti visus šiuos žymenis. Šiame tekste naudosime žymenį dfdx\frac{df}{dx}, nebent norėsime imti sudėtingos išraiškos išvestinę – tuomet naudosime ddxf\frac{d}{dx}f ir rašysime tokias išraiškas kaip

ddx[x4+cos⁡(x2+12x−1)].\frac{d}{dx}\left[x^4+\cos\left(\frac{x^2+1}{2x-1}\right)\right].

Dažnai intuityviai naudinga iš naujo išskleisti išvestinės apibrėžimą (22.3.1), kad pamatytume, kaip funkcija keičiasi, kai šiek tiek pakeičiame xx:

dfdx(x)=lim⁡ϵ→0f(x+ϵ)−f(x)ϵ  ⟹  dfdx(x)≈f(x+ϵ)−f(x)ϵ  ⟹  ϵdfdx(x)≈f(x+ϵ)−f(x)  ⟹  f(x+ϵ)≈f(x)+ϵdfdx(x).(22.3.2)\begin{aligned} \frac{df}{dx}(x) = \lim_{\epsilon \rightarrow 0}\frac{f(x+\epsilon) - f(x)}{\epsilon} & \implies \frac{df}{dx}(x) \approx \frac{f(x+\epsilon) - f(x)}{\epsilon} \\ & \implies \epsilon \frac{df}{dx}(x) \approx f(x+\epsilon) - f(x) \\ & \implies f(x+\epsilon) \approx f(x) + \epsilon \frac{df}{dx}(x). \end{aligned} \tag{22.3.2}

Paskutinę lygtį verta paminėti atskirai. Ji sako, kad jei paimsime bet kurią funkciją ir šiek tiek pakeisime įvestį, išvestis pasikeis tuo mažu dydžiu, padaugintu iš išvestinės.

Šitaip išvestinę galime suprasti kaip mastelio koeficientą, parodantį, kokį išvesties pokytį gauname dėl įvesties pokyčio.

22.3.2 Matematinės analizės taisyklės

Dabar pereiname prie užduoties suprasti, kaip apskaičiuoti aiškios funkcijos išvestinę. Pilnas formalus matematinės analizės dėstymas viską išvestų iš pirmųjų principų. Šiam pagundai čia nepasiduosime, o veikiau suteiksime supratimą apie dažniausiai sutinkamas taisykles.

22.3.2.1 Dažniausios išvestinės

Kaip matėme 2.4 skyrelis, skaičiuojant išvestines dažnai galima naudoti taisyklių seką, kad skaičiavimą sumažintume iki kelių pagrindinių funkcijų. Dėl patogumo pakartojame jas čia.

  • Konstantų išvestinė. ddxc=0\frac{d}{dx}c = 0.
  • Tiesinių funkcijų išvestinė. ddx(ax)=a\frac{d}{dx}(ax) = a.
  • Laipsnio taisyklė. ddxxn=nxn−1\frac{d}{dx}x^n = nx^{n-1}.
  • Eksponentinių funkcijų išvestinė. ddxex=ex\frac{d}{dx}e^x = e^x.
  • Logaritmo išvestinė. ddxlog⁡(x)=1x\frac{d}{dx}\log(x) = \frac{1}{x}.

22.3.2.2 Išvestinių taisyklės

Jei kiekvieną išvestinę reikėtų skaičiuoti atskirai ir saugoti lentelėje, diferencialinis skaičiavimas būtų beveik neįmanomas. Matematikos dovana yra tai, kad aukščiau pateiktas išvestines galime apibendrinti ir skaičiuoti sudėtingesnes, pavyzdžiui, rasti funkcijos f(x)=log⁡(1+(x−1)10)f(x) = \log\left(1+(x-1)^{10}\right) išvestinę. Kaip minėta 2.4 skyrelis, raktas į tai – užkoduoti, kas nutinka funkcijas įvairiai derinant, svarbiausia: sumas, sandaugas ir kompozicijas.

  • Sumos taisyklė. ddx(g(x)+h(x))=dgdx(x)+dhdx(x)\frac{d}{dx}\left(g(x) + h(x)\right) = \frac{dg}{dx}(x) + \frac{dh}{dx}(x).
  • Sandaugos taisyklė. ddx(g(x)⋅h(x))=g(x)dhdx(x)+dgdx(x)h(x)\frac{d}{dx}\left(g(x)\cdot h(x)\right) = g(x)\frac{dh}{dx}(x) + \frac{dg}{dx}(x)h(x).
  • Grandinės taisyklė. ddxg(h(x))=dgdh(h(x))⋅dhdx(x)\frac{d}{dx}g(h(x)) = \frac{dg}{dh}(h(x))\cdot \frac{dh}{dx}(x).

Pažiūrėkime, kaip galime naudoti (22.3.2), kad suprastume šias taisykles. Sumos taisyklei panagrinėkime tokią samprotavimo grandinę:

f(x+ϵ)=g(x+ϵ)+h(x+ϵ)≈g(x)+ϵdgdx(x)+h(x)+ϵdhdx(x)=g(x)+h(x)+ϵ(dgdx(x)+dhdx(x))=f(x)+ϵ(dgdx(x)+dhdx(x)).\begin{aligned} f(x+\epsilon) & = g(x+\epsilon) + h(x+\epsilon) \\ & \approx g(x) + \epsilon \frac{dg}{dx}(x) + h(x) + \epsilon \frac{dh}{dx}(x) \\ & = g(x) + h(x) + \epsilon\left(\frac{dg}{dx}(x) + \frac{dh}{dx}(x)\right) \\ & = f(x) + \epsilon\left(\frac{dg}{dx}(x) + \frac{dh}{dx}(x)\right). \end{aligned}

Palyginę šį rezultatą su faktu, kad f(x+ϵ)≈f(x)+ϵdfdx(x)f(x+\epsilon) \approx f(x) + \epsilon \frac{df}{dx}(x), matome, kad dfdx(x)=dgdx(x)+dhdx(x)\frac{df}{dx}(x) = \frac{dg}{dx}(x) + \frac{dh}{dx}(x), kaip ir norėta. Intuicija čia tokia: keičiant įvestį xx, gg ir hh kartu prisideda prie išvesties pokyčio atitinkamai dgdx(x)\frac{dg}{dx}(x) ir dhdx(x)\frac{dh}{dx}(x).

Sandauga subtilesnė ir reikalaus naujo pastebėjimo apie tai, kaip dirbti su šiomis išraiškomis. Pradėsime kaip anksčiau naudodami (22.3.2):

f(x+ϵ)=g(x+ϵ)⋅h(x+ϵ)≈(g(x)+ϵdgdx(x))⋅(h(x)+ϵdhdx(x))=g(x)⋅h(x)+ϵ(g(x)dhdx(x)+dgdx(x)h(x))+ϵ2dgdx(x)dhdx(x)=f(x)+ϵ(g(x)dhdx(x)+dgdx(x)h(x))+ϵ2dgdx(x)dhdx(x).\begin{aligned} f(x+\epsilon) & = g(x+\epsilon)\cdot h(x+\epsilon) \\ & \approx \left(g(x) + \epsilon \frac{dg}{dx}(x)\right)\cdot\left(h(x) + \epsilon \frac{dh}{dx}(x)\right) \\ & = g(x)\cdot h(x) + \epsilon\left(g(x)\frac{dh}{dx}(x) + \frac{dg}{dx}(x)h(x)\right) + \epsilon^2\frac{dg}{dx}(x)\frac{dh}{dx}(x) \\ & = f(x) + \epsilon\left(g(x)\frac{dh}{dx}(x) + \frac{dg}{dx}(x)h(x)\right) + \epsilon^2\frac{dg}{dx}(x)\frac{dh}{dx}(x). \\ \end{aligned}

Tai primena aukščiau atliktą skaičiavimą, ir iš tiesų matome savo atsakymą (dfdx(x)=g(x)dhdx(x)+dgdx(x)h(x)\frac{df}{dx}(x) = g(x)\frac{dh}{dx}(x) + \frac{dg}{dx}(x)h(x)) šalia ϵ\epsilon, tačiau yra problema dėl to nario, kurio dydis ϵ2\epsilon^{2}. Jį vadinsime aukštesnės eilės nariu, nes ϵ2\epsilon^2 laipsnis yra aukštesnis už ϵ1\epsilon^1 laipsnį. Vėlesniame skyriuje pamatysime, kad kartais norėsime juos sekti, tačiau kol kas pastebėkime, kad jei ϵ=0,0000001\epsilon = 0{,}0000001, tai ϵ2=0,0000000000001\epsilon^{2}= 0{,}0000000000001, kuris yra gerokai mažesnis. Kai ϵ→0\epsilon \rightarrow 0, aukštesnės eilės narius galime saugiai ignoruoti. Kaip bendrą šio priedo susitarimą, naudosime „≈\approx“, kad pažymėtume, jog du nariai yra lygūs iki aukštesnės eilės narių. Tačiau jei norime būti formalesni, galime išnagrinėti skirtumų santykį

f(x+ϵ)−f(x)ϵ=g(x)dhdx(x)+dgdx(x)h(x)+ϵdgdx(x)dhdx(x),\frac{f(x+\epsilon) - f(x)}{\epsilon} = g(x)\frac{dh}{dx}(x) + \frac{dg}{dx}(x)h(x) + \epsilon \frac{dg}{dx}(x)\frac{dh}{dx}(x),

ir pamatyti, kad kai ϵ→0\epsilon \rightarrow 0, dešinysis narys taip pat artėja prie nulio.

Galiausiai su grandinės taisykle galime vėl žengti kaip anksčiau naudodami (22.3.2) ir pamatyti, kad

f(x+ϵ)=g(h(x+ϵ))≈g(h(x)+ϵdhdx(x))≈g(h(x))+ϵdhdx(x)dgdh(h(x))=f(x)+ϵdgdh(h(x))dhdx(x),\begin{aligned} f(x+\epsilon) & = g(h(x+\epsilon)) \\ & \approx g\left(h(x) + \epsilon \frac{dh}{dx}(x)\right) \\ & \approx g(h(x)) + \epsilon \frac{dh}{dx}(x) \frac{dg}{dh}(h(x))\\ & = f(x) + \epsilon \frac{dg}{dh}(h(x))\frac{dh}{dx}(x), \end{aligned}

kur antroje eilutėje funkciją gg vertiname taip, tarsi jos įvestis (h(x)h(x)) būtų pastumta mažyčiu dydžiu ϵdhdx(x)\epsilon \frac{dh}{dx}(x).

Šios taisyklės suteikia lanksčią priemonių rinkinį, leidžiantį apskaičiuoti iš esmės bet kokią norimą išraišką. Pavyzdžiui,

ddx[log⁡(1+(x−1)10)]=(1+(x−1)10)−1ddx[1+(x−1)10]=(1+(x−1)10)−1(ddx[1]+ddx[(x−1)10])=(1+(x−1)10)−1(0+10(x−1)9ddx[x−1])=10(1+(x−1)10)−1(x−1)9=10(x−1)91+(x−1)10.\begin{aligned} \frac{d}{dx}\left[\log\left(1+(x-1)^{10}\right)\right] & = \left(1+(x-1)^{10}\right)^{-1}\frac{d}{dx}\left[1+(x-1)^{10}\right]\\ & = \left(1+(x-1)^{10}\right)^{-1}\left(\frac{d}{dx}[1] + \frac{d}{dx}[(x-1)^{10}]\right) \\ & = \left(1+(x-1)^{10}\right)^{-1}\left(0 + 10(x-1)^9\frac{d}{dx}[x-1]\right) \\ & = 10\left(1+(x-1)^{10}\right)^{-1}(x-1)^9 \\ & = \frac{10(x-1)^9}{1+(x-1)^{10}}. \end{aligned}

Kur kiekvienoje eilutėje naudotos šios taisyklės:

  1. Grandinės taisyklė ir logaritmo išvestinė.
  2. Sumos taisyklė.
  3. Konstantų išvestinė, grandinės taisyklė ir laipsnio taisyklė.
  4. Sumos taisyklė, tiesinių funkcijų išvestinė, konstantų išvestinė.

Atlikus šį pavyzdį, turėtų būti aišku du dalykai:

  1. Bet kurios funkcijos, kurią galime užrašyti naudodami sumas, sandaugas, konstantas, laipsnius, eksponentes ir logaritmus, išvestinę galima apskaičiuoti mechaniškai laikantis šių taisyklių.
  2. Žmogui laikytis šių taisyklių gali būti nuobodu ir klaidų kupina!

Laimei, šie du faktai kartu užsimena apie tolesnį kelią: tai puikus kandidatas mechanizavimui! Iš tiesų atgalinis sklidimas, prie kurio dar grįšime šiame skyriuje, yra būtent tai.

22.3.2.3 Tiesinė aproksimacija

Dirbant su išvestinėmis dažnai naudinga geometriškai interpretuoti aukščiau naudotą aproksimaciją. Visų pirma atkreipkite dėmesį, kad lygtis

f(x+ϵ)≈f(x)+ϵdfdx(x),f(x+\epsilon) \approx f(x) + \epsilon \frac{df}{dx}(x),

aproksimuoja ff reikšmę tiese, einančia per tašką (x,f(x))(x, f(x)) ir turinčia nuolydį dfdx(x)\frac{df}{dx}(x). Taip sakome, kad išvestinė suteikia funkcijos ff tiesinę aproksimaciją, kaip parodyta toliau:

# Compute sin
xs = np.arange(-np.pi, np.pi, 0.01)
plots = [np.sin(xs)]

# Compute some linear approximations. Use d(sin(x)) / dx = cos(x)
for x0 in [-1.5, 0, 2]:
    plots.append(np.sin(x0) + (xs - x0) * np.cos(x0))

d2l.plot(xs, plots, 'x', 'f(x)', ylim=[-1.5, 1.5])
# Compute sin
xs = torch.arange(-torch.pi, torch.pi, 0.01)
plots = [torch.sin(xs)]

# Compute some linear approximations. Use d(sin(x))/dx = cos(x)
for x0 in [-1.5, 0.0, 2.0]:
    plots.append(torch.sin(torch.tensor(x0)) + (xs - x0) *
                 torch.cos(torch.tensor(x0)))

d2l.plot(xs, plots, 'x', 'f(x)', ylim=[-1.5, 1.5])
# Compute sin
xs = tf.range(-tf.pi, tf.pi, 0.01)
plots = [tf.sin(xs)]

# Compute some linear approximations. Use d(sin(x))/dx = cos(x)
for x0 in [-1.5, 0.0, 2.0]:
    plots.append(tf.sin(tf.constant(x0)) + (xs - x0) *
                 tf.cos(tf.constant(x0)))

d2l.plot(xs, plots, 'x', 'f(x)', ylim=[-1.5, 1.5])

22.3.2.4 Aukštesnės eilės išvestinės

Dabar padarykime tai, kas iš pažiūros gali atrodyti keista. Paimkime funkciją ff ir apskaičiuokime išvestinę dfdx\frac{df}{dx}. Tai mums duoda ff kitimo greitį bet kuriame taške.

Tačiau išvestinę dfdx\frac{df}{dx} galima nagrinėti kaip pačią funkciją, todėl niekas netrukdo apskaičiuoti dfdx\frac{df}{dx} išvestinės ir gauti d2fdx2=dfdx(dfdx)\frac{d^2f}{dx^2} = \frac{df}{dx}\left(\frac{df}{dx}\right). Tai vadinsime antrąja ff išvestine. Ši funkcija yra ff kitimo greičio kitimo greitis, arba, kitaip tariant, kaip kinta kitimo greitis. Išvestinę galime taikyti bet kiek kartų ir gauti vadinamąją nn-ąją išvestinę. Kad žymėjimas būtų tvarkingas, nn-ąją išvestinę žymėsime

f(n)(x)=dnfdxn=(ddx)nf.f^{(n)}(x) = \frac{d^{n}f}{dx^{n}} = \left(\frac{d}{dx}\right)^{n} f.

Pabandykime suprasti, kodėl ši sąvoka naudinga. Toliau pavaizduojame f(2)(x)f^{(2)}(x), f(1)(x)f^{(1)}(x) ir f(x)f(x).

Pirmiausia panagrinėkime atvejį, kai antroji išvestinė f(2)(x)f^{(2)}(x) yra teigiama konstanta. Tai reiškia, kad pirmosios išvestinės nuolydis yra teigiamas. Dėl to pirmoji išvestinė f(1)(x)f^{(1)}(x) gali pradėti neigiama, tam tikrame taške tapti lygi nuliui, o galiausiai tapti teigiama. Tai mums pasako mūsų pradinės funkcijos ff nuolydį, todėl pati funkcija ff mažėja, išsilygina, tada didėja. Kitaip tariant, funkcija ff išgaubta į viršų ir turi vieną minimumą, kaip parodyta 22.3.1 pav..

Jei darome prielaidą, kad antroji išvestinė yra teigiama konstanta, tai pirmoji išvestinė didėja, o tai reiškia, kad pati funkcija turi minimumą.

22.3.1 pav. Jei darome prielaidą, kad antroji išvestinė yra teigiama konstanta, tai pirmoji išvestinė didėja, o tai reiškia, kad pati funkcija turi minimumą.

Antra, jei antroji išvestinė yra neigiama konstanta, tai reiškia, kad pirmoji išvestinė mažėja. Tai reiškia, kad pirmoji išvestinė gali pradėti teigiama, tam tikrame taške tapti lygi nuliui, o tada tapti neigiama. Vadinasi, pati funkcija ff didėja, išsilygina, tada mažėja. Kitaip tariant, funkcija ff išgaubta žemyn ir turi vieną maksimumą, kaip parodyta 22.3.2 pav..

Jei darome prielaidą, kad antroji išvestinė yra neigiama konstanta, tai pirmoji išvestinė mažėja, o tai reiškia, kad pati funkcija turi maksimumą.

22.3.2 pav. Jei darome prielaidą, kad antroji išvestinė yra neigiama konstanta, tai pirmoji išvestinė mažėja, o tai reiškia, kad pati funkcija turi maksimumą.

Trečia, jei antroji išvestinė visada lygi nuliui, tai pirmoji išvestinė niekada nesikeis – ji yra konstanta! Tai reiškia, kad ff didėja (arba mažėja) pastoviu greičiu, o pati ff yra tiesė, kaip parodyta 22.3.3 pav..

Jei darome prielaidą, kad antroji išvestinė lygi nuliui, tai pirmoji išvestinė yra konstanta, o tai reiškia, kad pati funkcija yra tiesė.

22.3.3 pav. Jei darome prielaidą, kad antroji išvestinė lygi nuliui, tai pirmoji išvestinė yra konstanta, o tai reiškia, kad pati funkcija yra tiesė.

Apibendrinant, antrąją išvestinę galima interpretuoti kaip aprašančią, kaip funkcija ff išlinksta. Teigiama antroji išvestinė lemia išlinkimą į viršų, neigiama antroji išvestinė reiškia, kad ff išlinksta žemyn, o nulinė antroji išvestinė reiškia, kad ff visai nelinksta.

Žengkime dar vieną žingsnį. Panagrinėkime funkciją g(x)=ax2+bx+cg(x) = ax^{2}+ bx + c. Tada galime apskaičiuoti, kad

dgdx(x)=2ax+bd2gdx2(x)=2a.\begin{aligned} \frac{dg}{dx}(x) & = 2ax + b \\ \frac{d^2g}{dx^2}(x) & = 2a. \end{aligned}

Jei turime omenyje kokią nors pradinę funkciją f(x)f(x), galime apskaičiuoti pirmąsias dvi išvestines ir rasti a,ba, b bei cc reikšmes, kurios joms leidžia atitikti šį skaičiavimą. Panašiai kaip ankstesniame skyriuje matėme, kad pirmoji išvestinė duoda geriausią aproksimaciją tiese, ši konstrukcija suteikia geriausią aproksimaciją kvadratine funkcija. Pavaizduokime tai funkcijai f(x)=sin⁡(x)f(x) = \sin(x).

# Compute sin
xs = np.arange(-np.pi, np.pi, 0.01)
plots = [np.sin(xs)]

# Compute some quadratic approximations. Use d(sin(x)) / dx = cos(x)
for x0 in [-1.5, 0, 2]:
    plots.append(np.sin(x0) + (xs - x0) * np.cos(x0) -
                              (xs - x0)**2 * np.sin(x0) / 2)

d2l.plot(xs, plots, 'x', 'f(x)', ylim=[-1.5, 1.5])
# Compute sin
xs = torch.arange(-torch.pi, torch.pi, 0.01)
plots = [torch.sin(xs)]

# Compute some quadratic approximations. Use d(sin(x)) / dx = cos(x)
for x0 in [-1.5, 0.0, 2.0]:
    plots.append(torch.sin(torch.tensor(x0)) + (xs - x0) *
                 torch.cos(torch.tensor(x0)) - (xs - x0)**2 *
                 torch.sin(torch.tensor(x0)) / 2)

d2l.plot(xs, plots, 'x', 'f(x)', ylim=[-1.5, 1.5])
# Compute sin
xs = tf.range(-tf.pi, tf.pi, 0.01)
plots = [tf.sin(xs)]

# Compute some quadratic approximations. Use d(sin(x)) / dx = cos(x)
for x0 in [-1.5, 0.0, 2.0]:
    plots.append(tf.sin(tf.constant(x0)) + (xs - x0) *
                 tf.cos(tf.constant(x0)) - (xs - x0)**2 *
                 tf.sin(tf.constant(x0)) / 2)

d2l.plot(xs, plots, 'x', 'f(x)', ylim=[-1.5, 1.5])

Šią mintį išplėsime iki Teiloro eilutės sampratos kitame skyrelyje.

22.3.2.5 Teiloro eilutė

Teiloro eilutė suteikia metodą aproksimuoti funkciją f(x)f(x), jei turime pirmųjų nn išvestinių reikšmes taške x0x_0, t. y. {f(x0),f(1)(x0),f(2)(x0),…,f(n)(x0)}\left\{ f(x_0), f^{(1)}(x_0), f^{(2)}(x_0), \ldots, f^{(n)}(x_0) \right\}. Idėja – rasti nn-ojo laipsnio daugianarį, atitinkantį visas duotas išvestines taške x0x_0.

Atvejį n=2n=2 matėme ankstesniame skyrelyje, ir šiek tiek algebros parodo, kad tai yra

f(x)≈12d2fdx2(x0)(x−x0)2+dfdx(x0)(x−x0)+f(x0).f(x) \approx \frac{1}{2}\frac{d^2f}{dx^2}(x_0)(x-x_0)^{2}+ \frac{df}{dx}(x_0)(x-x_0) + f(x_0).

Kaip matome aukščiau, vardiklis 22 yra tam, kad panaikintų 22, kurį gauname dukart diferencijuodami x2x^2, o kiti nariai visi lygūs nuliui. Ta pati logika galioja pirmajai išvestinei ir pačiai reikšmei.

Jei logiką tęsime iki n=3n=3, padarysime išvadą, kad

f(x)≈d3fdx3(x0)6(x−x0)3+d2fdx2(x0)2(x−x0)2+dfdx(x0)(x−x0)+f(x0).f(x) \approx \frac{\frac{d^3f}{dx^3}(x_0)}{6}(x-x_0)^3 + \frac{\frac{d^2f}{dx^2}(x_0)}{2}(x-x_0)^{2}+ \frac{df}{dx}(x_0)(x-x_0) + f(x_0).

kur 6=3×2=3!6 = 3 \times 2 = 3! atsiranda iš konstantos, kurią gauname priekyje, jei triskart diferencijuojame x3x^3.

Be to, nn-ojo laipsnio daugianarį galime gauti taip:

Pn(x)=∑i=0nf(i)(x0)i!(x−x0)i.P_n(x) = \sum_{i = 0}^{n} \frac{f^{(i)}(x_0)}{i!}(x-x_0)^{i}.

kur žymuo

f(n)(x)=dnfdxn=(ddx)nf.f^{(n)}(x) = \frac{d^{n}f}{dx^{n}} = \left(\frac{d}{dx}\right)^{n} f.

Iš tiesų Pn(x)P_n(x) galima laikyti geriausia nn-ojo laipsnio daugianario aproksimacija mūsų funkcijai f(x)f(x).

Nors nesigilinsime iki galo į aukščiau pateiktų aproksimacijų paklaidą, verta paminėti begalinę ribą. Šiuo atveju gerai besielgiančioms funkcijoms (žinomoms kaip realiosios analizinės funkcijos), tokioms kaip cos⁡(x)\cos(x) ar exe^{x}, galime užrašyti begalinį narių skaičių ir aproksimuoti tą pačią funkciją

f(x)=∑n=0∞f(n)(x0)n!(x−x0)n.f(x) = \sum_{n = 0}^\infty \frac{f^{(n)}(x_0)}{n!}(x-x_0)^{n}.

Pavyzdžiui, paimkime f(x)=exf(x) = e^{x}. Kadangi exe^{x} yra savo paties išvestinė, žinome, kad f(n)(x)=exf^{(n)}(x) = e^{x}. Todėl exe^{x} galima atkurti paėmus Teiloro eilutę taške x0=0x_0 = 0, t. y.

ex=∑n=0∞xnn!=1+x+x22+x36+⋯ .e^{x} = \sum_{n = 0}^\infty \frac{x^{n}}{n!} = 1 + x + \frac{x^2}{2} + \frac{x^3}{6} + \cdots.

Pažiūrėkime, kaip tai veikia kode, ir stebėkime, kaip didinant Teiloro aproksimacijos laipsnį artėjame prie norimos funkcijos exe^x.

# Compute the exponential function
xs = np.arange(0, 3, 0.01)
ys = np.exp(xs)

# Compute a few Taylor series approximations
P1 = 1 + xs
P2 = 1 + xs + xs**2 / 2
P5 = 1 + xs + xs**2 / 2 + xs**3 / 6 + xs**4 / 24 + xs**5 / 120

d2l.plot(xs, [ys, P1, P2, P5], 'x', 'f(x)', legend=[
    "Exponential", "Degree 1 Taylor Series", "Degree 2 Taylor Series",
    "Degree 5 Taylor Series"])
# Compute the exponential function
xs = torch.arange(0, 3, 0.01)
ys = torch.exp(xs)

# Compute a few Taylor series approximations
P1 = 1 + xs
P2 = 1 + xs + xs**2 / 2
P5 = 1 + xs + xs**2 / 2 + xs**3 / 6 + xs**4 / 24 + xs**5 / 120

d2l.plot(xs, [ys, P1, P2, P5], 'x', 'f(x)', legend=[
    "Exponential", "Degree 1 Taylor Series", "Degree 2 Taylor Series",
    "Degree 5 Taylor Series"])
# Compute the exponential function
xs = tf.range(0, 3, 0.01)
ys = tf.exp(xs)

# Compute a few Taylor series approximations
P1 = 1 + xs
P2 = 1 + xs + xs**2 / 2
P5 = 1 + xs + xs**2 / 2 + xs**3 / 6 + xs**4 / 24 + xs**5 / 120

d2l.plot(xs, [ys, P1, P2, P5], 'x', 'f(x)', legend=[
    "Exponential", "Degree 1 Taylor Series", "Degree 2 Taylor Series",
    "Degree 5 Taylor Series"])

Teiloro eilutės turi du pagrindinius taikymus:

  1. Teoriniai taikymai: dažnai, kai bandome suprasti per daug sudėtingą funkciją, Teiloro eilutės leidžia ją paversti daugianariu, su kuriuo galime dirbti tiesiogiai.

  2. Skaitiniai taikymai: kai kurias funkcijas, pavyzdžiui, exe^{x} ar cos⁡(x)\cos(x), mašinoms sunku apskaičiuoti. Jos gali saugoti reikšmių lenteles fiksuotu tikslumu (ir tai dažnai daroma), tačiau tai vis tiek palieka neatsakytų klausimų, pavyzdžiui: „Koks yra 1000-asis cos⁡(1)\cos(1) skaitmuo?“ Teiloro eilutės dažnai padeda atsakyti į tokius klausimus.

22.3.3 Santrauka

  • Išvestinės gali būti naudojamos išreikšti, kaip funkcijos keičiasi, kai įvestį šiek tiek pakeičiame.
  • Elementariosios išvestinės gali būti derinamos naudojant išvestinių taisykles, kad gautume savavališkai sudėtingas išvestines.
  • Išvestines galima iteruoti ir gauti antrąją ar aukštesnės eilės išvestines. Kiekvienas eilės padidinimas suteikia smulkesnės informacijos apie funkcijos elgesį.
  • Naudodami informaciją iš vieno duomenų pavyzdžio išvestinių, gerai besielgiančias funkcijas galime aproksimuoti daugianariais, gautais iš Teiloro eilutės.

22.3.4 Pratimai

  1. Kokia yra x3−4x+1x^3-4x+1 išvestinė?
  2. Kokia yra log⁡(1x)\log(\frac{1}{x}) išvestinė?
  3. Teisinga ar klaidinga: jei f′(x)=0f'(x) = 0, tai ff taške xx turi maksimumą arba minimumą?
  4. Kur yra f(x)=xlog⁡(x)f(x) = x\log(x) minimumas, kai x≥0x\ge0 (darome prielaidą, kad f(0)f(0) taške ff įgyja ribinę reikšmę 00)?

Diskusijos

Diskusijos

Diskusijos