{ "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "*Created by Petteri Nevavuori.*\n", "\n", "---\n", "\n", "# Deep Learning seminaari\n", "\n", "Kirjana Goodfellow et al.: Deep Learning (2016)\n", "\n", "Otsikot seuraavat pääotsikoiden tasolla kirjaa, mutta alaotsikot eivät aina." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" }, "toc": true }, "source": [ "

Table of Contents

\n", "
" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## 6. Deep Feedforward Networks" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Syväoppivat menetelmät tarjoavat nykyisellään todella tehokkaita työkaluja ennen kaikkea ohjattuun oppimiseen. Syväoppivia menetelmiä voidaan hyöydyntää ennen kaikkea sellaisissa tehtävissä, jotka ihmiselle suoraviivaisia. Tällöin kuitenkin on oltava riittävästi valmiiksi [laajassa mielessä] luokiteltua dataa, jolla menetelmiä voidaan kouluttaa. Sellaiset tehtävät, jotka vaativat ihmiseltä enemmän pohdintaa, ovat toistaiseksi näiden menetelmien ulottumattomissa." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Perustavimman laatuiset myötäkytketyt neuroverkot (*feedforward neural networks*) tunnetaan nimellä monitasoiset perseptronit (*multilayer perceptron, MLP*). Myötäkytkennän tavoitteena on jonkin funktion approksimointi. Se voi ollaverkolle syötetyn datasetin generoineen datantuottoprosessin funktion approksimointia tai sitten vaikkapa syötteiden luokittelufunktion oppiminen. Kuten aiemmissakin koneoppimismenetelmissä, myötäkytketty verkko oppii funktion $y=f(x;\\theta)$, jossa $\\theta$ tarkoittaa mallin opittavia parametreja (painoja)." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Myötäkytketyiksi verkkoja kutsutaan niiden sisäisen informaation kulkutavan vuoksi. Informaatio etenee suoraviivaisesti syötteestä verkon kerroksien läpi tuottaen lopulta ulostulon - takaisinkytkentöjä ei myötäkytketyissä verkoissa ole. Mikäli takaisinkytkentä löytyy, on kyse rekursiivisista neuroverkoista (*recurrent neural networks*), joskin nekin pohjaavat myötäkytkettyihin verkkoihin. Monet spesifimmät neuroverkot, kuten kuvantunnistuksessa käytetyt konvoluutioverkot (*convolutional neural networks*), rakentuvat myötäkytkennän ajatukselle." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Neuroverkkojen inspiraatio on aivojen neuroneissa ja synapseissa. Synapsit ovat painotettuja yhteyksiä neuronien, laskentayksiköiden tai porttien välillä. Samoin neuroverkot koostuvat kerroksiin järjestetyistä neuroneista, jotka yhdistyvät toisiinsa synapseilla, painoilla. Neuroverkkoihin liittyy seuraavia merkittäviä termejä:" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ " - **Neuroni** (*neuron*): Neuroverkon laskentayksikkö, joka muuntaa vektoreita skalaareiksi jonkun aktivointifunktion mukaisesti. Voidaan mieltää myös yhdeksi neuroverkon kytketyistä funktioista. Neuronin lisäksi näistä käytetään usein nimitytstä yksikkö. Neuroverkkojen graafiesityksissä solmut vastaavat neuroneita." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- **Aktivointifunktio** (*activation function*): Biologisten neuronien tapaan myös neuroverkkojen neuroneilla voi olla aktivointifunktioita. Mikäli sellaista ei ole, mallinnetaan syötedatasettiä lineaarisesti. Mikäli neuroneilla on aktivointifunktio, neuroniin syötteenä tuleva vektori muutetaan funktion mukaan. Neuvona on nykyisin käyttää piilokerroksissa oikaistua lineaarifunktiota (*rectified linear unit*). Aktivointifunktioita on useita." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- **Kerros** (*layer*): Neuroverkot muodostavat käytännössä funktioiden ketjuja. Funktiot sijaitsevat kukin omalla kerroksellaan, johon syöte tulee joko datana tai edellisestä kerroksesta. Perinteisesti kerrokset jaetaan syöttökerrokseen (*input layer*), piilokerrokseen/-siin (*hidden layer(s)*) ja ulostulokerrokseen (*output layer*)." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- **Syvyys** (*depth*): Syvyys määräytyy kerroksien perusteella. Käytännössä syvyys määrittyy piilokerrosten mukaan." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- **Leveys** (*width*): Leveys määräytyy piilokerrosten neuronien määrällä. Mitä enemmän neuroneja kerroksissa on, sitä leveämmästä neuroverkosta on kyse." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Perinteisissä menetelmissä keinot vaikuttaa mallin funktioon tai funktioiden joukkoon rajoittuvat joko mahdollisimman geneeristen funktioiden käyttöön tai sitten käsipelillä funktion rakentamiseen. Syväoppivat menetelmät eroavat perinteisistä menetelmistä siten, että ne pyrkivät oppimaan omat funktionsa koulutuksen aikana. Tämän lisäksi niiden kohdalla on myös mahdollista vaikuttaa siihen, mitä ja miten opitaan." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### 6.1. Learning XOR" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "XOR-portti on perinteinen mallinnusongelma, jolla esitellään neuroverkkojen kyvykkyyttä perinteisten koneoppimismenetelmien rinnalla. XOR-portti ottaa vastaan kaksi syötettä ja aktivoituu vain (=1), mikäli jompi kumpi sisääntuloista on päällä (=1). Jos sisääntulot ovat samanarvoiset, joko pois päältä tai päällä, portti pysyy kiinni (=0). " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Lineaariset menetelmät kohtaavat ylitsepääsemättömiä ongelmia tämän ongelman ratkaisussa. Yksi lineaarinen funktio ei riitä mallintamaan tilannetta, jossa tarvitaan kaksi eri funktiota portin mallintamiseen. Yksinkertainen yhden piilokerroksen neuroverkko, jonka leveys on kaksi neuronia, riittää jo tämän ongelman kelvolliseen mallintamiseen." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### 6.2. Gradient-Based Learning" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "*Gradient descentin* eli jyrkimmän virheen laskun menetelmän käyttö on pääpiirteittäin aivan vaastaavaa perinteisiin menetelmiin verrattuna. Erona on lineaarisiin malleihin nähden, että epälineaarisuudestaan (*non-linearity*) johtuen neuroverkkojen koulutuksessa tavoitteena on mahdollisimman pieni virhe mahdollisen globaalin minimin sijasta. Tämä on suoraa seurasta epälineaarisuudesta. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Gradientteja käytetään neuroverkkojenkin kohdalla kohdefunktion pienentämiseen. Neuroverkkojen kanssa käytettyjä kohdefunktioita löytyy useita ja ne ovat pääpiirteittäin samoja perinteisten menetelmien kanssa. Luokitteluongelmille löytyy omat kohdefunktiot, kuten myös klusterointi- ja regressio-ongelmille. Usein käytetty menetelmä on aiemmin esitelty logaritminen suurimman todennäköisyyden funktio (*maximum log-likelihood*), kun koulutettava malli pyrkii mallintamaan datasetin tuottanutta jakaumaa. kohdefunktioiden kanssa käytetään usein regularisointiparametria. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Kohdefunktioista laskettujen neuronikohtaisten gradienttien tulee olla lukuina riittävän suuria ja ennustettavia. Mikäli gradientit jäävät pieniksi, kohdefunktiot kyllästyvät (*saturate*) eli tasaantuvat (*flatten*) eivätkä tarjoa enää riittävän suuria gradientteja verkon parametrien koulutukseen. kohdefunktioista negatiivinen logaritminen todennäköisyys (*negative log-likelihood*) auttaa tämän ongelman välttämisessä, kun se neuroverkon ulostuloneuronien funktioina käytetään exponentiaalisia funktioita (esim. sigmoid-funktioita)." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Pelkkien parametrien oppimisen lisäksi neuroverkot voidaan valjastaa oppimaan toiminnallisia (*functional*) funktioita. Tällöin malli ei pyri tuottamaan tarkkoja datasetin tuottprosessin kuvauksia, vaan esimerkiksi keskiarvoja tietyissä rajoissa." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Output Units" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Neuroverkkojen kohdalla kohdefunktion valinta on suoraan kytköksissä ulostulokerroksen neuronien tyyppeihin. Kuten piilokerroksienkin neuronien kohdalla, ulostulokerroksen neuronien tarkoituksena suorittaa muunnos (*transformation*) vektorisyötteestä luvuksi, joka on oppimistavoitteen kannalta käyttökelpoinen. Ulostulokerroksen neuronityypit voidaan karkeasti jakaa aktivointifunktioiden osalta seuraaviin yleisimmin käytettyihin tyyppeihin:" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ " - **Lineaariyksiköt**: Laskevat suoraan sisääntulovektorin arvon ilman mitään muunnoksia. Käyttökelpoinen todennäköisyysjakaumille.\n", " " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ " - **Sigmoid-yksiköt**: Käytetään binäärisen ulostulon laskentaan (Bernoullin jakauma). Sen sijaan, että tuotettaisiin vain kovia arvoja 0 tai 1, yksiköt tuottavat todennäköisyysarvoja välillä [0,1]. Näin vältetään 0-gradientin ongelma, jolloin funktio saturoituisi eikä koulutusta voitaisi verkolle tällöin tehdä. Toisaalta sigmoid-yksikötkin voivat saturoitua, mutta näissä tapauksissa verkko on saavuttanut jo \"oikean vastauksen\", eli yksikköön tuleva syöte on joko äärimmäisen negatiivinen ($\\sigma \\to 0$) tai positiivinen ($\\sigma \\to 1$).\n", " " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ " - **Softmax-yksiköt**: Laajennos sigmoid-yksiköstä binäärisen arvon sijasta *n* arvoon. Käytetään etenkin luokittelijoiden kanssa *n* luokan todennäköisyysjakauman kuvaamiseen. Yksikkö tuottaa normalisoidun vektorin (alkioiden summa on 1), josta negatiivisen logatrimisen todennäköisyyden avulla nostetaan esiin todennäköisin vektorin arvoista. Näin sekä koulutusta saadaan tehostettua. Ylipäätään softmax-yksikkö hyötyy eniten suurimman todennäköisyyden funktion käytöstä sisäisesti, sillä muiden menetelmien kanssa kyseiset yksiköt voisivat saturoitua väärässä kohdassa. Kuten sigmoid-yksiköt, softmax-yksikötkin voivat saturoitua vastaavaissa olosuhteissa.\n", " " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Näiden lisäksi neuroverkot voivat sovittua melkein mihin tahansa ulostulokerroksen aktivointifunktioon. Mallin voidaan haluta esimerkiksi tuottavan yhtenä ulostulona $y$:n varianssia eri $x$:n näytteille, jolloin malli on nimeltään heteroskedastinen. Moniarvoregressiossa (*multimodal regressiossa*) yhdelle $x$:n näytteelle tahdotaan tuottaa useampi $y$:n arvo (esim. puheen generointi taajuuksien osalta), jolloin verkkoja nimitetään niiden ulostulon perusteella yhdistelmäjakaumaverkoiksi (*mixture density networks*). Näissä tapauksissa ollaan kuitenkin tekemisissä ehdollisten Gaussin jakaumien kanssa, jolloin gradientteihin pohjaavat optimointimenetelmät ovat osoittautuneet jokseenkin epävarmoiksi." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Joskaan kaikkia aktivointifunktioita ei ole mielekästä käytää piilokerroksissa, myös ulostulokerroksen aktivointifunktiot ovat kelvollisia piilokerroksen funktioita." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### 6.3. Hidden Units" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Piilokerrosten suunnittelu on erittäin aktiivinen jatkuvan tutkimuksen osa-alue eikä siihen ole vielä olemassa kattavaa teoreettista säännöstöä. Perustuen kuitenkin kokeelliseen tutkimukseen, oikaistut lineaariyksiköt ovat erittäin pätevä perusvalinta piilokerrosten aktivointifunktioksi monenkirjavien vaihtoehtojen joukosta. Tätä alleviivataan. Joskin koneoppimisen osalta ja etenkin kohdefunktion minimoimisen osalta on ongelmallista, mikäli käytetyt funktiot eivät ole differentoitavissa, neuroverkkojen kohdalla tämä ei muodostu ongelmaksi: Neuroverkot eivät tavoittele kohdefunktion globaalia minimiä, vaan pelkkä merkittävä virheen pienentäminen on jo riittävää mallin sovittumiseksi." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Rectified Linear Unit" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Oikaistun lineaariyksikön (*rectified linear unit, ReLU*) kaava on melko selkeä:\n", "\n", "$$ g(z) = \\max{\\{0,z\\}} \\text{, jossa z: edellisen kerroksen ulostulo.} $$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Mikäli yksikköön tuleva syöte $z$ on negatiivinen, se tuottaa arvon 0. Muussa tapauksessa yksikkö päästää syötteen sellaisenaan eteenpäin. Oikaistut lineaariyksiköt ovat nimensäkin mukaisesti hyvin läheisesti lineaariyksikköjä vastaavia, joskin negatiiviset arvot leikataan pois nollaan. Tällöin aktiivisina yksiköstä lasketut derivaatat ovat riittävän suuria ja johdonmukaisia gradienttien laskentaan. Ainoa selkeä ongelmakohta näiden yksiköiden kohdalla ovat sellaiset näytteet, jotka todellisuudessa ovat aktiivisia nollassa. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Yksiköstä löytyy ainakin seuraavat muunnokset:" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ " - **Itseisarvoyksikkö** (*absolute value rectification*): Yksinkertaisuudessaan nollan sijasta negativiisista arvoista tuotetaan itseisarvo. TÄmä on käyttökelpoinen lähestymistapa esimerkiksi kohteentunnistuksessa." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ " - **Vuotava oikaistu lineaariyksikkö** (*leaky ReLU*): Tiukan leikkauksen sijasta negatiiviset arvot vaimennetaan huomattavasti positiivisiin arvoihin nähden. Vaimennuskerroin on vakio." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ " - **Oppiva oikaistu lineaariyksikkö** (*parametric ReLU, PReLU*): Muutoin sama, kuin vuotava lineaariyksikkö, mutta vaimennuskerroin on opittavissa." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ " - **Maxout-yksikkö**: Edellisen kerroksen ulostulon $z$ alkiot ryhmitellään $k$ ryhmään, joista yksikkö valitsee jonkin ryhmän suurimman elementin.\n", " " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Alla on vielä osa lineaariyksiköistä kuvattuna:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "image/png": "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\npzdOqzrqjSNSVs7p3ICYRlGMik9gZFwCs1du56HzOlAl3P/eim7ac5DR8YnMW7uLC2Ib8sj5Hamq\n3jjlkp4VKZf2Z2TzwOeL+OSPjfRoVpMXh3WhYZR644hI4SVv28/IuASWbN7LlX2acedZ7TQrLOID\njWtWYfz1vRjz3UpemZHM/HW7GTc8lg4N/KfnzleLtnDn5AVk5+TywtAYLujayNchyVGo0JFyZ+GG\nVEbE/cH6XWmMPq01N53citAAPHhRREqXc46J8zfw4JTFVAqrwNuXd+fU4+r6OiyRoBYWUoHbzmxL\n71bR3Dw+kcGv/MLdA9txRe/y3XMnPSuHx6Yu4aM56+ncKJKxw2JpVku9cco7FTpSbuTmOt75eQ1P\nf7WMWlUrEn9dL3o0V28cESm8velZ3PPJQr5csJleLaJ5aVgX6qo3jki50btlLaaPOpHbJybx8BdL\nmL1yB88OiaFmRLivQ/uHFVv3MeLjBJZv3cd1J7bgtjPUG8dfqNCRcmH7vgxum5jETyu2c2aHujx9\nYWeiqpS/ZCci5d8f63czMi6Bzanp3H5mW244qSUh2gVJpNypGRHOW5d35/1f1vLEtGWc9dJMXrq4\nC73LSc8d5xwfz1vPI18soVqlUN6/qgcnqTeOX1GhIz43a+V2bh6fxL70LB47vyP/OkG9cUSk8HJz\nHa/9tIoXvl1BveqVmHB9L7o1VW8ckfLMzLiiT3OOb16TEXEJ/Ovtufxf/5aMPs23PXdS07K465MF\nTF+0hX6ta/H80BjqVNOssL9RoSM+k5Xj6Y3zxk+raV2nKv+75gTa1lNvHBEpvK1707llQiI/J+/k\n7M71eWJwJyIrqzeOiL/o0CCSL0f05aEpi3nlx1X8umonY4b5pufOb2t3MSougW37Mrh7QDuu7ddC\nvXH8lAod8Yl1Ow8wMj6RpJQ9XHJCE+4/uz2Vw7ULkogU3o/LtnHrxCTSMrN5+sJODO3eWLPCIn6o\nSngoz1wUQ9/Wtbn3k4UMHDuLJy/oxDmdy6bnTk6u4+Ufkhnz/Qoae3vjxDRWbxx/pkJHytzniRu5\n99NFVDB47V9dGdCpvq9DEhE/lJGdw9PTl/POz2toV68aL1/Sk1Z1NCss4u/Oi2lAbOMoRsYncNPH\nCcxeuYMHzm1fqj13NqceZFR8IvPW7OL8Lg149PyOVKukWWF/p0JHysyBjGwenLKYSb9voHvTGowZ\nHqveOCJSJKu372dEXAKLN+3lit7NuGuAeuOIBJLGNasw4fpevPjtCl77aRW/rd3FuOFdad+geonf\n1zeLt3DH5AVkZufy/JAYLuym3jiBQoWOlIlFG1MZEZfgWbJ2amtGnqLeOCJSeM45Jv3u6Y0THlqB\n/17WndPbqzeOSCAKC6nAHWe1o0+rWtw8PpHzX/2Zewcex2W9mpbI8tT0rByemLaUD35dR8eG1Rk7\nLJYWtauWQORSXqjQkVLlnOOdn9fy1PSlREdU5ONre9KzRbSvwxIRP7QvPYt7P13ElKRN9GxRk5cu\njqVepHZBEgl0fVrVYvqoftw2MYkHpyxm1sodPHtRZ2oUo+fOyq37GBGXwLIt+7imb3NuP6stFUM1\nKxxoVOhIqdm539Mb58fl2zm9fV2eubB4SUlEgldiyh5GxP3Bpj3p3Hp6G/7v5FbqjSMSRKKrVuSd\nK47n3Z/X8tT0ZQwYM4sXL+5Cr5aF+/DUOUf8byk8/MViIsJDeffK4zm5bZ1Silp8TYWOlIqfk3cw\nenwiqQezeGRQBy7tWTLTzCISXHJzHW/OWs1zXy+nbvVKjL+uJ92b1fR1WCLiA2bGVX2b06N5TUbG\nJXDJW3O46eRWjDq1dYGWw6emZXH3pwuYtnALfVvV4oWhMdSprlnhQKZCR0pUVk4uL3y7gtd/WkXL\n2lX54KoeHFe/5A8cFJHAt21vOrdMSGJ28g4GdqrHk4M7E1lFuyCJBLuODSP5wttzZ9wPyfyyaidj\nhnWhUY0j99z5fd0uRsYlsnVvOncNaMd16o0TFAp0NLiZnWVmy80s2czuOszlFc1svPfyuWbWrKQD\nlfIvZVcaQ17/lddmrGLY8Y354qa+KnLkH5RPpCB+XL6NAWNmMX/dLp68oBOvXNJVRY78jXJJcIuo\nGMqzQ2IYM6wLy7fsY+CYWUxbuPkf1/P0xlnJ0DfmUKECTLyhFzec1FJFTpA45oyOmYUArwCnAxuA\n38xsinNuSZ6rXQ3sds61MrNhwNPAxaURsJRPU5I2ce8nC8HglUu6cnZn9caRf1I+kWPJynU89uUS\n3prt6Y0TP7wnreuqN478nXKJHDKoS0NiG9dgRHwC//e/PxjeowkPnNMegC2p6Ywen8Cc1bs4L6YB\njw3uSHX1xgkqBVm61gNIds6tBjCzeGAQkDeZDAIe8p6eBLxsZuacc0e6UQcczMwpSsx+JSPHBfQ4\nM7JzeHthBrM2JtCtaY1jTh1L0CuVfCKBYfX2/Tw2J511e9dwWa+m3DPwOPXGkSNRLpE/NYmuwqQb\nevH8N56l87+t3UWvWlmMnjmTzOxcnr2oMxd1a6RjhYNQQQqdhkBKnp83ACcc6TrOuWwzSwWigR1H\nutF1e3M57oGvChetv/o2sMdpwIhTCn4woAS1UsknUr5k5eSSejCLPWmZ7E7LYk9aFrvTMkn1ft+d\nlkXqwUx2H/Cef9DzPT0rl4gweOPSbpzZoZ6vhyHlm3KJ/E1YSAXuGtCOPq2iuWVCEh8uyaRDg+qM\nHR5LS/XGCVoFKXQOV/7m/zSkINfBzK4DrgOoXqcRQ9sE/vRhRmYmFcMDe0vlRpUy6Ry+mdmz/rk2\nNlDs37+fGTNm+DqMQFAq+aR27doB//z44m8w1zkOZsP+TMeBLMf+LMf+LDiQeei09/xM/jqd5fmd\nIwkxiAiDqmFGRJhRNdyoXdWIqFGBauEhdI7MpOL2ZcyYsazsBlrGlE9KRInlElA+CTT3dw9h3gbH\nSc2zSVk8/28VcaAJ9OeyuApS6GwAGuf5uRGw6QjX2WBmoUAksCv/DTnn3gTeBGjbtq175qozihKz\nX5kxYwb9+/f3dRilSmOUQii1fBLoz09x/gadc6Rl5rA7LZM9eWZY9hzMYs8B76zLwcx/zLykHswi\n9wiLfMygeqUwalQJJ7JKOM2qeE9X9nyvERH25+moKn99r1ox9KjLR4LhtRYMYywDJZZLQPkkEFUP\ngjFCcDyXxVGQQuc3oLWZNQc2AsOAS/JdZwpwOfArcBHwg9bAishhKJ8UU0Z2zt+LlbRDBUpWntPe\nguagd5lYWhaZOblHvM2I8BCi8hQkDaMq5ylOwomqHOYtXMKp4T2/euUwNewUX1IuEZFjOmah413X\nehPwNRACvOOcW2xmjwDznXNTgLeBD80sGc+nJcNKM2gR8U/KJ3/JPnQcy6FjWQ7kOZ1/5iUtiy27\n0zj4/VcczDry5ibhoRWoUSWMqMqeoqVFrapEVQkjqoqnQDl02lO4eK4TWTmMiqE64F/8i3KJiBRE\ngRqGOuemAdPynfdAntPpwJCSDU1EAlGg5RPnHHvTs/McaO89uP7AoYPu8xyA/+fB+ZnsTT/ygSwh\nFYyoymFEemdPGkRVooalcVyLxtSICP/bkrC8y8Iqh4VoVyEJGoGWS0Sk5BWo0BERCXTOOQ5m5fx9\n6deRlocd/Os6qQezyDnSgSxA9UqheWZUwmlWK+KvIsU7s/LncS1VwomsEka1iqH/aGbnWYfdvrQf\nBhERkYChQkdEAk5mdu5fB9cfyMyzJCzLW8AcZnnYwSwys498HEuV8BCiKnuXgUWEcVy96vlmVP46\nluXQ6cjKYdpyXURExEdU6IiI39tyIJezx876s4g5cJQmvWEh9rcZlqbRVejSOOqwx7IcmnmJrBym\nxpUiIiJ+RoWOiPg9B9StXom29aoR5d0ZLCrCO8OS71iWKuE6jkVERCQYqNAREb9XP6IC71xxvK/D\nEBERkXJEi8dFRERERCTgqNAREREREZGAo0JHREREREQCjgodEREREREJOCp0REREREQk4KjQERER\nERGRgKNCR0REREREAo4KHRERERERCTgqdEREREREJOCo0BERERERkYCjQkdERERERAKOCh0RERER\nEQk4KnRERERERCTgqNAREREREZGAo0JHREREREQCjjnnfHPHZvuA5T6587JVC9jh6yBKmcYYONo6\n56r5OojCCpJ8Eix/g8EwzmAYIyiflGfB8DcYDGOE4BhnkXNJaElHUgjLnXPdfXj/ZcLM5gf6ODXG\nwGFm830dQxEFfD4Jpr/BQB9nMIwRlE/Ks2D4GwyGMUJwjLM4uURL10REREREJOCo0BERERERkYDj\ny0LnTR/ed1kKhnFqjIHDX8fpr3EXRjCMEYJjnMEwRvDfcfpr3IWhMQaOYBhnkcfos80IRERERERE\nSouWromIiIiISMAps0LHzIaY2WIzyzWzI+4OYWZnmdlyM0s2s7vKKr6SYmY1zexbM1vp/V7jCNfL\nMbNE79eUso6zKI713JhZRTMb7718rpk1K/soi6cAY7zCzLbnee6u8UWcxWFm75jZNjNbdITLzczG\neh+DBWbWtaxjPJZgyCfKJf6dS0D5xHt5uc4nwZBLQPlE+aT8K7Vc4pwrky/gOKAtMAPofoTrhACr\ngBZAOJAEtC+rGEtonM8Ad3lP3wU8fYTr7fd1rIUc1zGfG+D/gNe9p4cB430ddymM8QrgZV/HWsxx\nngh0BRYd4fKBwHTAgJ7AXF/HfJgYAz6fKJf4by4pxDiVT3wff8DnEu8YlE+c8kl5/iqtXFJmMzrO\nuaXOuWM14OoBJDvnVjvnMoF4YFDpR1eiBgHve0+/D5zvw1hKUkGem7xjnwScamZWhjEWVyD8/R2T\nc24msOsoVxkEfOA85gBRZla/bKIrmCDJJ8olHv6YS8D///4KxN/zSZDkElA+UT4p50orl5S3Y3Qa\nAil5ft7gPc+f1HXObQbwfq9zhOtVMrP5ZjbHzPwh4RTkufnzOs65bCAViC6T6EpGQf/+LvROm04y\ns8ZlE1qZCoTXIfj/OJRL8NtcAsonh/j76xACYwzKJyif+LkivQ5DSzICM/sOqHeYi+51zn1ekJs4\nzHnlblu4o42zEDfTxDm3ycxaAD+Y2ULn3KqSibBUFOS58Yvn7ygKEv8XQJxzLsPMbsDzKdEppR5Z\n2SoXz2Mw5BPlkj8FWi4B5ZNDfP5cBkMuAeWTPJRPAjOfFOl5LNFCxzl3WjFvYgOQtwJtBGwq5m2W\nuKON08y2mll959xm75TatiPcxibv99VmNgOIxbP+srwqyHNz6DobzCwUiOTo05DlzTHH6JzbmefH\n/wJPl0FcZa1cvA6DIZ8olwCBmUtA+eQQn78OgyGXgPKJl/KJRyDmkyK9Dsvb0rXfgNZm1tzMwvEc\nNOYXu37kMQW43Hv6cuAfnxaZWQ0zq+g9XQvoAywpswiLpiDPTd6xXwT84LxHkPmJY44x33rQ84Cl\nZRhfWZkCXObd4aQnkHpoyYOf8fd8olzi4Y+5BJRPDgmEfOLvuQSUT5RP/F/Rcklp76KQZ7eEwXiq\nsQxgK/C19/wGwLR8uyqswPMJwr1lFV8JjjMa+B5Y6f1e03t+d+At7+newEI8u2YsBK72ddwFHNs/\nnhvgEeA87+lKwEQgGZgHtPB1zKUwxieBxd7n7kegna9jLsIY44DNQJb3NXk1cANwg/dyA17xPgYL\nOcJORD4eQ8DnE+US/84lBRyn8onv4w/4XOKNX/lE+aRcf5VWLjHvL4uIiIiIiASM8rZ0TURERERE\npNhU6IiIiIiISMBRoSMiIiIiIgFHhY6IiIiIiAQcFToiIiIiIhJwVOiIiIiIiEjAUaEjIiIiIiIB\nR4WOiIiIiIgEnP8H4mJX5JU8YS0AAAAASUVORK5CYII=\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import matplotlib.pyplot as plt\n", "import numpy as np\n", "plt.rcParams['figure.figsize'] = 14,2\n", "\n", "titles = ['ReLU','Leaky ReLU','Absolute Rectification']\n", "x = np.arange(-100,101)/100\n", "fns = [[max(0,i) for i in x],np.concatenate((x[x<0]*0.1,x[x>=0])),np.absolute(x)]\n", "\n", "for i in range(3):\n", "\n", " plt.subplot(131+i)\n", " plt.plot(x,fns[i])\n", " plt.title(titles[i])\n", " plt.ylim(-0.3,1)\n", " plt.xlim(-1,1)\n", " plt.grid()\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Joka tapauksessa lineaaristen yksikköjen etuna on havainto, jonka mukaan neuroverkot näyttävät oppivat paremmin, kun niiden neuronien ulostulot ovat lähes lineaarisia." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Logistic Sigmoid and Hyperbolic Tangent" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true, "slideshow": { "slide_type": "fragment" } }, "source": [ "Ennen lineaarisia aktivointifunktioita käytetyimmät aktivointifunktiot olivat logistinen sigmoidaalifunktio $g(z) = \\sigma (z)$ ja hyperbolinen tangenttifunktio $g(z) = \\text{tanh}(z)$.\n", "\n", "Sigmoidaalifunktiot tuottavat lukuja $[0,1]$ väliltä, kun taas tangenttifunktiot laajemmalta väliltä $[-1,1]$." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Sigmoidaalifunktio toimii parhaiten syötteen $z$ ollessa lähellä nollaa ja se saturoituu helposti äärimmäisillä syötteen arvoilla. Sigmoidaalifunktio saa arvon $0.5$ kohdassa $\\sigma (0)$, kun taas $\\text{tanh}(0)=0$. Hyperbolinen tangenttifunktio mallintaa dataa todenmukaisemmin. Tästä syystä hyperbolinen tangenttifunktio toimii sigmoidaalifunktioita paremmin samoissa käyttötilanteissa. Joka tapauksessa näiden funktioiden käytöstä piilokerroksessa ollaan siirrytty kohti ReLU-funktioita." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Other Hidden Units" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Muitakin ei niin yleisesti käytettyjä piilokerroksen aktivointifunktioita kyllä löytyy, mutta niiden suorituskyky ei juurikaan poikkea yleisemmin käytetyistä. Niitä on monia, mutta joitakin listataan:" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- **Lineaarinen aktivointifunktio**:Eli ei varsinaista aktivointifunktiotia lainkaan. Voidaan käyttää piirreavaruuden kaventamiseen." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- **Softmax**: Piilokerroksissa käytettynä ovat kelvollisia vain selkeästi erikoistuneemmissa verkoissa." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- **Radiaalifunktio** (*radial basis function, RBF*): Funktio aktivoituu, mitä lähempänä syöte on funktion keskipistettä. Laajentaa piirreavaruutta." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- **Softplus**: Pehmennetty oikaistu lineaarifunktio." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- **Lineaari-tanh** (*hard tanh*): Kuin ReLU, mutta muodostaa aktivointialueen tanh-funktion alueella $[-1,1]$." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### 6.4. Architecture Design" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Aktivointifunktioiden lisäksi syväoppivien verkkojen arkkitehtuuri vaikuttaa merkittävästi opetettavan mallin kyvykkyytteen. Arkkitehtuurilla vastataan seuraaviin kysymyksiin:\n", "\n", " - Montako neuronia verkossa tulisi olla?\n", " - Miten neuronit yhdistyvät toisiinsa?" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Verkot ovat perinteisesti yhdistetty toisiinsa kerrosten (*layer*) tasolla, tavallisesti ketjumaisesti. Yksi kerros muodostaa yhden opittavan funktion. Näissä verkoissa tärkeimmät suunnittelun painopisteet ovat verkon syvyydessä ja kerrosten leveydessä. Optimaalinen ratkaisu löydetään toistaiseksi vain kokeilemalla." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Universal Approximation Properties and Depth" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Epälineaaristen ongelmien ratkaisu vaatii perinteisillä menetelmillä erikoistuneen mallintavien funktioiden suunnittelua. Näin ei kuitenkaan ole syväoppivien verkkojen kanssa, sillä myötäkytketyt piilokerroksia omaavat verkot toimivat ns. universaaleina funktioiden likiarvojen arvioijina tai ennustajina (*universal approximation*)." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Tähän liittyvä teoreema (*universal approximation theorem*) sanoo, että riittävällä määrällä piiloneuroneja mikä tahansa myötkytketty verkko voi oppia funktion määrätystä syöteavaruudesta toiseen jollain nollaa suuremmalla virheen määrällä. Ainoa rajoite on, että opittavat funktion piirreavaruuden tulee olla jokin rajoitettu joukko *n*-piirteisessä avaruudessa, ts. $\\mathbb{X} \\subset \\mathbb{R}$." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Käytännössä tämä tarkoittaa, että riittävän suurella verkolla voidaan oppia ainakin jossain määriin kuvaamaan hankalaakin epälineaarista johonkin datasettiin liittyvää funktiota. Kuvaamaan siksi, että takeita funktion oppimisesta eli virheettömästä kuvauksesta ei kuitenkaan ole. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Teoreema ottaa enimmäkseen kantaa samoin vain yhden piilokerroksen eli matalaan (*shallow*) verkkoon ja keskustelee etenkin leveyden kasvattamisesta. Kun syvyyttä kasvatetaan, voidaan leveyttä pienentää, ja tällöin syvyydestä muodostuu merkittävin oppimiskykyyn vaikuttava tekijä." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Sovittuvuuden lisäksi syviä malleja voidaan hyödyntää tilastollisten syiden vuoksi. Syväoppivat menetelmät, kuten aiemminkin on jo todettu, oppivat kuvaamaan datasetin tuottoprosessia lähtökohtaisesti monen funktion yhdistelmänä. Empiiristen tutkimusten perusteella myös mallin syvyydellä näyttää olevan merkitystä mallien paremman sovittuvuuden kannalta." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Other Architectural Considerations" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Keskustelun rajoittaminen vain syvyyteen ja leveyteen on mielekästä vain perinteisten myötäkytkettyjen ketjutettujen (*chained*) verkkojen kanssa. Käytännössä keskustelu arkkitehtuurista on neuroverkkojen kohdall kuitenkin laajempaa. Muuttamalla kerrosten välisiä kytkentätapoja voidaan saada aikaan huomattavan erikoistuneita verkkoja, kuten kuvantunnistuksen konvoluutioverkkoja (*convolutional networks*) tai rekursiivisia verkkoja (*recursive networks*). " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Kerrosten välillä voi esiintyä osittais- ja takaisinkytkentöjä. Osittaiskytkennöillä vain osa kerroksen neuroneista on kytketty johonkin toiseen osaan joko edeltävää tai seuraavaa kerrosta. Näin voidaan mallintaa esimerkiksi paikallisia funktioita tai piirrejoukkoja tai pienentää laskennallisia vaatimuksia. Takaisinkytkennässä kerroksen ulostulo syötetään myös verkkoon itseensä sisääntulona, jolloin esimerkiksi sekvenssien tai tilapäismuistin mallintaminen muodostuu käytännölliseksi mahdollisuudeksi. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### 6.5. Back-Propagation and Other Differentiation Algorithms" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Takaisinetenemisalgoritmi (*back-propagation algorithm*) tai tunnetummin *backprop* on algoritmi, joka on vastuussa gradienttien laskemisesta verkkojen koulutuksen toisessa vaiheessa. Koulutuksen ensimmäisessä vaiheessa syöte etenee kerrosten läpi aina ulostulokerrokseen asti, jossa lopuksi lasketaan valitulla virhefuntiolla verkon suorituskyky $P$. *Backprop* astuu kuvaan toisessa vaiheessa, kun syötteen pohjalta saatu mallin virhe on saatava oikeassa suhteessa laskettua kullekkin mallin parametrille $\\theta_i$ eli painolle." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Backprop ei kuitenkaan vielä opeta mallia, vaan laskee vasta opetukseen tarvittavan gradientin. Esimerkiksi stokastisella jyrkimmän laskun menetelmällä (*stochastic gradient descent*) saadaan sitten laskettua parametrien muutossuunta. Backprop ei myöskään ole vain perinteisten MLP-verkkoihin gradienttin laskenta-algoritmi, vaan sillä voidaan laskea lähes funktiosta kuin funktiosta." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Backprop hyödyntää differentiaalilaskennan ketjusääntöä, jolla voidaan derivoida yhdistettyjä funktioita ja täten laskea osittaisderivaatat. Osittaisderivaatasta sanotaan Wikipediasssa seuraavaa:\n", "\n", "> Osittaisderivaatalla voidaan tutkia, mikä vaikutus yhden muuttujan muutoksella on funktion arvoon varioitavan muuttujan arvon ympäristössä. (*[Wikipedia: Osittaisderivaatta](https://fi.wikipedia.org/wiki/Osittaisderivaatta)*)\n", "\n", "Toisin sanoen osittaisderivaatoilla voidaan syväoppimiseen liittyen laskea mallin painojen osuus mallin kokonaisvirheestä." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Olkoot $y=g(x)$ ja $z = f(y)$. Derivoinnin ketjusääntöä hyödyntäen osittaisderivaatta muuttujan $x$ suhteen on kaavana\n", "\n", "$$\\frac{dz}{dx}=\\frac{dz}{dy}\\frac{dy}{dx}.$$\n", "\n", "Kielellisesti ilmaistuna muuttujan $z$ osaderivaatta muuttujan $x$ suhteen saadaan muuttuja $z$ muuttujan $y$ suhteen ja muuttuja $y$ muuttujan $x$ suhteen laskettujen osaderivaattojen tulona." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Tämä on yleistettävissä myös vektoreihin, jolloin päästään mallien parametrivektoreihin ja virheen osaderivaattojen laskentaan suhteessa kuhunkin parametriin (Jakobin matriisi). Tällöin jokaisen parametrin osaderivaatan laskukaava on\n", "\n", "$$\\frac{\\delta z}{\\delta x_i}=\\sum_j \\frac{\\delta z}{\\delta y_j}\\frac{\\delta y_j}{\\delta x_i}.$$\n", "\n", "Tällöin jokaisen vektorin osaderivaatta jokaisen vektorin $x$ alkion suhteen lasketaan kunkin vektorin $y$ alkion osalta. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Recursively Applying the Chain Rule to Obtain Backprop" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Mikäli backprop-algoritmi otettaisiin käyttöön vain sellaisenaan verkossa, jossa osittaisderivaatat laskettaisiin monen kerroksen ja neuronin kohdalla, tulisi samoja laskuja suoritettua useasti ja implementaatio olisi tällöin tehoton. Esimerkiksi kahdella piilokerroksella ensimmäisen kerroksen painojen virheen osittaisderivaattojen laskenta vaatisi toisen kerroksen neuronien kohdalla tapahtuvan virheen osittaisderivaattojen laskennan jälkimmäisen kerroksen jokaisen neuronin kohdalla *ja* kutakin ensimmäisen kerroksen neuronia varten." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Ratkaisu tähän laskujen moninkertaistukseen on ottaa käyttöön mallien parametreille eli painoille vektorien sijasta tensorit. Tensoreiden käyttö mahdollistaa painojen skalaariarvoja sisältävän vektorin yhdistämisen vektoriin, jossa on talletettuna painokohtaisesti lasketut gradientit eli osittaisderivaatat. Näin ne tarvitsee laskea vain kerran, eikä kallista moneen kertaan tapahtuvaa laskentaa ole pakko suorittaa." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### General Backprop" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Itse algoritmi on yksinkertainen. Selvitettäessä gradienttia eli osittaisderivaattaa jollekin skalaarille $z$ (esim. mallin ulostuloarvo) suhteessa syötteeseen $x$ lasketaan gradientit kullekin $z$ ja $x$ välissä olevalle parametrille. Gradientit lasketaan taso kerraallaan, edeten aina ulostuloarvosta $z$ sitä edeltäneisiin kerroksiin ja näiden kerroksien neuronien painoihin. Neuronikohtaiset gradientit lasketaan summaamalla kaikki $z$ suunnasta lasketut gradientit yhteen." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Kuten koneoppimismenetelmien kehityksessä ja käytössä yleensä, myös backpropin käytössä on huomioitava siihen lähtökohtaisesti vain toiminta- ja kehitysympäristön kautta liittyviä asioita - pääsääntöisesti nämä asiat ovat ohjelmointiin liittyviä virheen- ja tyyppikäsittelyn asioita. Itse algoritmi on kuitenkin jo kehitetty vastaamaan naiivin gradientin laskennan korkeaa laskentahintaa (*computational cost*) helpottamaan." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Differentiation outside the Deep Learning Community" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Esitelty ja syväoppimisyhteisössä laajalti käytetty backprop on kuitenkin vain yksi derivaattojen laskenta- eli differointimenetelmä muiden joukossa. Automaattisen differoinnin tutkimuskenttä keskittyy etenkin tähän alueeseen. Backprop on vain osa laajempaa käänteisen moodin kerääntymisen (*revese mode accumulation*) algoritmien perhettä. Kulmakertoimen lisäksi differointia voidaan tehdä myös korkeammissa differointiulottuvuuksissa (esim. toisen asteen derivaatat) tai -järjestyksissä. Optimaalisen gradientinlaskennan ongelma on NP-täydellinen, eli sen laskenta on erittäin haastava ja lähes mahdoton ratkaista. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Huomionarvoista on kuitenkin se, että koska kirjan kirjoittavat ovat ilmeisen aktiivisesti tekemisissä TensorFlow-kirjaston kanssa, heidän kommenttejaan bakcpropin eksplisiittisestä koodauksesta varjostaa ennen kaikkea TensorFlowin toteutus ja käyttötapa. Esimerkiksi PyTorchin kanssa optimointi on yksi sellaisenaan käytettävä osa kirjastoa ja siinä on valmiina sellaisenaan käyttökelpoiset toteutukset muutamalle käytetyimmistä optimointi-implementaatiosta." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### 6.6 Historical Notes" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Modernit syväoppivat verkot nojaavat vahvasti jo monta sataa vuotta sitten kehitettyihin matemaattisiin ajatuksiin. Backpropin pohjana toimiva differentiaalilaskennan ketjusääntö on kehitetty jo 1600-luvulla. Matemaattista optimointia on myös tehty jo satoja vuosia sitten, mutta *gradient descent* on sekin jo 1800-luvulla kehitetty. Funktioiden approksimaatiomenetelmiä on kehitetty aktiivisesti aina 1940-luvulta, jolloin myös perinteisten monikerroksisten neuroverkkojen esiaste, perseptroni, on kehitetty. Dynaamisen ohjelmoinnin myötä 1960- ja 1970-luvuilla ketjusäännön tehokasta laskentaa alettiin tutkia laajemmmin ja jo 1980-luvulla kehitettyjä menetelmiä ehdotettiinkin neuroverkkojen kanssa käytettäviksi. Kyseisen vuosikymmenen puolivälissä backprop sai julkisuutta ja sitä alettiin hyödyntää laajemmin koneoppimisongelmissa." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Ensimmäinen hypekäyrän huippu saavutettiin jo 1990-luvun alussa, kunnes suvantovaiheen jälkeen toinen huippu koettiin vuonna 2006. Myötäkytkettyjen verkkojen perustana toimivat ajatukset neuroneja sisältävien kerrosten yhdistämisestä eivät kuitenkaan ole merkittävissä määrin enää muuttuneet 1980-luvun jälkeen. Verkkojen suorituskyvyn kehitys onkin purettavissa kahteen päätekijään: datasettien koon kasvun myötä helpottuneeseen tarkempien mallien koulutukseen ja laskentatehon kasvun myötä koossa ja tehossa kasvaneisiin verkkoihin." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Pienempiä, mutta kuitenkin merkittäviä, muutoksia ovat olleet optimointialgoritmien tutkimus ja kehitys. Siirtyminen keskimääräisestä neliövirheestä ristientropian (esim. MLE) menetelmiin 1990-luvulla vaikutti suorituskyvyn kehittymiseen huomattavasti. Myös jo käsitely sigmoidaalifunktioiden korvaaminen lineaarifunktioilla piilokerroksissa edesautti tätä kehitystä edelleen. Vuodesta 2012 alkaen syväoppivia verkkoja on pidetty itsenäisesti varteenotettavina koneoppimisen ja optimoinnin menetelminä." ] } ], "metadata": { "celltoolbar": "Slideshow", "hide_input": false, "kernelspec": { "display_name": "Python 3", "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.6.5" }, "toc": { "nav_menu": {}, "number_sections": false, "sideBar": true, "skip_h1_title": true, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": true, "toc_position": {}, "toc_section_display": true, "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 2 }