{"id":86,"date":"2017-05-02T10:56:54","date_gmt":"2017-05-02T10:56:54","guid":{"rendered":"http:\/\/liipetti.net\/retkia\/?p=86"},"modified":"2017-05-02T17:50:36","modified_gmt":"2017-05-02T17:50:36","slug":"neuroverkot-kaytannon-johdanto-2","status":"publish","type":"post","link":"https:\/\/liipetti.net\/retkia\/neuroverkot-kaytannon-johdanto-2\/","title":{"rendered":"Neuroverkot -k\u00e4yt\u00e4nn\u00f6n johdanto 2"},"content":{"rendered":"<p>T\u00e4ss\u00e4 osassa katsotaan hieman neuroverkon sis\u00e4lle, sen rakenteeseen ja toimintaan. T\u00e4ss\u00e4 vaiheessa l\u00e4hdemme liikkeelle yksitt\u00e4isest\u00e4 keinotekoisesta &#8221;hermosolusta&#8221; ja kokeilunhaluiset voivat my\u00f6s itse yritt\u00e4\u00e4 kokeilla kuinka sellainen toimii ja oppii. Katsomme my\u00f6s kuinka n\u00e4ist\u00e4 &#8221;soluista&#8221; kootaan kerroksia ja kerroksista edelleen suurempia verkkoja.<\/p>\n<p>Neuroverkon perusosanen, keinotekoinen &#8221;hermosolu&#8221;, <em>perseptroni<\/em>, laskee k\u00e4yt\u00e4nn\u00f6ss\u00e4 sy\u00f6tteiden <strong>i<\/strong> painotetun summan. Oppivan siit\u00e4 tekee se ett\u00e4 solu pystyy oppimaan painokertoimet <strong>w <\/strong>esimerkkien pohjalta.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-64\" src=\"https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2017\/05\/perceptron-crop-300x172.png\" alt=\"Perseptroni\" width=\"300\" height=\"172\" srcset=\"https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2017\/05\/perceptron-crop-300x172.png 300w, https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2017\/05\/perceptron-crop-768x440.png 768w, https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2017\/05\/perceptron-crop-1024x587.png 1024w, https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2017\/05\/perceptron-crop-250x143.png 250w, https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2017\/05\/perceptron-crop-150x86.png 150w, https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2017\/05\/perceptron-crop.png 1604w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p>Sy\u00f6tteet ovat numeerisia (esim. 0.4 tai -0.32) ja ne voivat siksi kuvata erilaisia reaalimaailman suureita, mittaustuloksia tai vaikka p\u00f6rssikursseja. Ulostulo on my\u00f6s luonnostaan numeerinen. Jos verkosta halutaan ulostulona bin\u00e4\u00e4rinen tieto (tosi\/ep\u00e4tosi, oikein\/v\u00e4\u00e4rin, kunnossa\/h\u00e4lytys), voidaan solun per\u00e4\u00e4n lis\u00e4t\u00e4 aktivaatiofunktio, joka\u00a0esimerkiksi antaa h\u00e4lytyksen\u00a0kun summauksen arvo ylitt\u00e4\u00e4 tietyn kynnysarvon (eli matemaattisesti katsoen kyseess\u00e4 on askelfunktio, jonka arvo menee nollasta ykk\u00f6seksi kun sy\u00f6te ylitt\u00e4\u00e4 kynnysarvon).<\/p>\n<p>Solun ulostuloon lis\u00e4t\u00e4\u00e4nkin k\u00e4yt\u00e4nn\u00f6ss\u00e4 l\u00e4hes aina jokin ep\u00e4lineaarinen\u00a0aktivaatiofunktio, jolloin\u00a0solu ei vain laske sy\u00f6tteiden painotettua summaa vaan tekee my\u00f6s p\u00e4\u00e4t\u00f6ksen. Kuvassa n\u00e4kyv\u00e4 aktivaatiofunktio korvaa\u00a0negatiiviset arvot nollalla (t\u00e4t\u00e4 kutsutaan nimell\u00e4 ReLU ja se on hyvin yleisesti k\u00e4ytetty).<\/p>\n<p>Katsotaanpa k\u00e4yt\u00e4nn\u00f6ss\u00e4, apuna <a href=\"http:\/\/torch.ch\" target=\"_blank\">torch-ohjelmakirjasto<\/a>. Kokeiluihin suosittelen Ubuntua tai vastaavaa Linux-jakelua, johon torch voidaan asentaa n\u00e4iden <a href=\"http:\/\/torch.ch\/docs\/getting-started.html#_\" target=\"_blank\">ohjeiden<\/a> avulla.\u00a0Torchia voi k\u00e4ytt\u00e4\u00e4 paitsi ajettavissa ohjelmissa my\u00f6s komentotulkin kautta jolla on k\u00e4tev\u00e4 tehd\u00e4 pienimuotoisia kokeiluja. Seuraavaksi n\u00e4yt\u00e4n miten th-komentotulkissa voidaan luoda yksisoluinen neuroverkko ja kokeilla sen koulutusta.<\/p>\n<p>Ensin luomme neuroverkon jossa on kolme sy\u00f6tett\u00e4 ja yksi ulostulo, siis k\u00e4yt\u00e4nn\u00f6ss\u00e4 yksi &#8221;solu&#8221;. Torchin neuroverkoissa solun summauksessa voi olla mukana ns. bias, laitamme sen nyt nollaksi. Painokertoimet asetamme satunnaisiksi ja katsomme mit\u00e4 niiden arvoiksi tuli.<\/p>\n<pre>th&gt; require 'nn'\r\nth&gt; net = nn.Linear(3,1) \r\nth&gt; net.bias[1] = 0\r\nth&gt; net.weight = torch.rand(1,3)\r\nth&gt; print(net.weight)\r\n 0.6977 0.6862 0.8461\r\n[torch.DoubleTensor of size 1x3]\r\n<\/pre>\n<p>Seuraavaksi luomme sy\u00f6tteen kolmesta luvusta, sy\u00f6t\u00e4mme sen neurosolullemme ja katsomme mit\u00e4 saamme tulokseksi.<\/p>\n<pre>th&gt; input = torch.Tensor({0, 0.5, 0.2})\r\nth&gt; output = net:forward(input)\r\nth&gt; print(output)\r\n 0.5123\r\n[torch.DoubleTensor of size 1]<\/pre>\n<p>Oletetaan nyt ett\u00e4 t\u00e4ll\u00e4 sy\u00f6tteell\u00e4 haluttu tulos olisi 0.3. Tulos on nyt liian suuri, laskemme poikkeaman halutusta ja k\u00e4skemme yksisoluista verkkoamme korjaamaan painoarvojaan siihen suuntaan ett\u00e4 lopputulos olisi l\u00e4hemp\u00e4n\u00e4 oikeaa.<\/p>\n<pre>th&gt; dOut = output - 0.3\r\nth&gt; net:backward(input, dOut)\r\n 0.1481\r\n 0.1457\r\n 0.1797\r\n[torch.DoubleTensor of size 3]\r\nth&gt; net:updateParameters(0.1)\r\n<\/pre>\n<p>0.1 on t\u00e4ss\u00e4 oppimistahti. Yksitt\u00e4isen esimerkin perusteella ei kannata laittaa painoarvoja kokonaan uusiksi (oppimistahti = 1). K\u00e4yt\u00e4nn\u00f6ss\u00e4 haetaan aina jonkinlaista optimia joka antaa hyvi\u00e4 tuloksia kaikilla koulutusaineiston esimerkeill\u00e4. Katsotaan nyt mit\u00e4 painoarvoille on tapahtunut ja mit\u00e4 saamme tulokseksi samalla sy\u00f6tteell\u00e4:<\/p>\n<pre>th&gt; print(net.weight)\r\n 0.6977 0.6756 0.8418\r\n[torch.DoubleTensor of size 1x3]\r\nth&gt; output = net:forward(input)\r\n [0.0002s]\r\nth&gt; output\r\n 0.4849\r\n[torch.DoubleTensor of size 1]\r\n<\/pre>\n<p>N\u00e4hd\u00e4\u00e4n ett\u00e4 tulos on siirtynyt l\u00e4hemm\u00e4ksi haluttua. Jos nyt toistetaan koulutusta p\u00e4\u00e4st\u00e4\u00e4n asteittain l\u00e4hemm\u00e4ksi oikeaa tulosta.<\/p>\n<pre>th&gt; net:backward(input, dOut)\r\n 0.1481\r\n 0.1435\r\n 0.1788\r\n[torch.DoubleTensor of size 3]\r\nth&gt; net:updateParameters(0.1)\r\nth&gt; print(net:forward(input))\r\n 0.4302\r\n[torch.DoubleTensor of size 1]\r\n<\/pre>\n<p>Koulutuksen toistamisessa yhdell\u00e4 ja samalla sy\u00f6tteell\u00e4 ei kuitenkaan ole juuri j\u00e4rke\u00e4, k\u00e4yt\u00e4nn\u00f6ss\u00e4 koulutus tehd\u00e4\u00e4n aina sopivalla joukolla esimerkkej\u00e4. Huomaa my\u00f6s ett\u00e4 t\u00e4ss\u00e4 emme viel\u00e4 k\u00e4ytt\u00e4neet mit\u00e4\u00e4n aktivaatiofunktiota.<\/p>\n<p>N\u00e4in siis yksitt\u00e4inen &#8221;solu&#8221; toimii. Jos tarvitsemme enemm\u00e4n ulostuloja, voimme koota verkon useammasta solusta n\u00e4in. Kuvassa <strong>i\u00a0<\/strong>kuvaa sy\u00f6tteit\u00e4 ja\u00a0<strong>o<\/strong> yksitt\u00e4isi\u00e4 soluja. Meill\u00e4 on nyt siis kaksi solua, jotka kumpikin saavat saman sy\u00f6tteen, mutta tuottavat ulostulonsa itsen\u00e4isesti.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-65\" src=\"https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2017\/05\/layer1-crop-285x300.png\" alt=\"layer1-crop\" width=\"285\" height=\"300\" srcset=\"https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2017\/05\/layer1-crop-285x300.png 285w, https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2017\/05\/layer1-crop-768x807.png 768w, https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2017\/05\/layer1-crop-143x150.png 143w, https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2017\/05\/layer1-crop.png 882w\" sizes=\"auto, (max-width: 285px) 100vw, 285px\" \/><\/p>\n<p>Torchissa t\u00e4mm\u00f6inen verkko syntyy yht\u00e4 helposti kuin yhden solunkin tapauksessa.\u00a0Sy\u00f6te koostuu edelleen kolmesta luvusta, tulos koostuu nyt kahdesta lukuarvosta.<\/p>\n<pre>th&gt; net = nn.Linear(3,2)\r\nth&gt; net.weight = torch.rand(2,3)\r\nth&gt; net.bias = torch.Tensor():resizeAs(net.bias):fill(0)\r\nth&gt; print(net.weight)\r\n 0.0186 0.0803 0.3084\r\n 0.0921 0.9462 0.3576\r\n[torch.DoubleTensor of size 2x3]\r\nth&gt; input = torch.Tensor({0, 0.5, 0.2})\r\nth&gt; output = net:forward(input)\r\nth&gt; print(output)\r\n 0.1018\r\n 0.8292\r\n[torch.DoubleTensor of size 2]<\/pre>\n<p>Nyt olemme luoneet rinnakkaisista soluista kerroksen, jonka sy\u00f6tteen <em>dimensio<\/em>\u00a0on 3 ja tuloksen 2. Mutkikkaammat ongelmat voivat tarvita useamman p\u00e4\u00e4llekk\u00e4isen kerroksen jolloin tieto jalostuu kahdessa vaiheessa, sy\u00f6tteist\u00e4 <strong>i\u00a0<\/strong>v\u00e4likerrokseksi <strong>h\u00a0<\/strong>(<em>hidden layer)\u00a0<\/em>ja siit\u00e4 edelleen ulostuloksi <strong>o<i>.\u00a0<\/i><\/strong>T\u00e4ss\u00e4 on nyt oleellista, ett\u00e4 sek\u00e4\u00a0<strong>h<\/strong>-kerros ett\u00e4\u00a0<strong>i<\/strong>-kerros tekev\u00e4t summauksen lis\u00e4ksi jonkinlaisen p\u00e4\u00e4t\u00f6ksen (sis\u00e4lt\u00e4v\u00e4t aktivaatiofunktion).<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-66\" src=\"https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2017\/05\/layer2-crop-300x253.png\" alt=\"layer2-crop\" width=\"300\" height=\"253\" srcset=\"https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2017\/05\/layer2-crop-300x253.png 300w, https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2017\/05\/layer2-crop-768x647.png 768w, https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2017\/05\/layer2-crop-1024x863.png 1024w, https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2017\/05\/layer2-crop-178x150.png 178w, https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2017\/05\/layer2-crop-150x126.png 150w, https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2017\/05\/layer2-crop.png 1346w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p>T\u00e4m\u00e4 syntyy torchissa n\u00e4in. Huomaa kuinka lis\u00e4\u00e4mme ep\u00e4lineaarisen ReLU-funktion kummankin kerroksen j\u00e4lkeen.<\/p>\n<pre>th&gt; net = nn.Sequential()\r\nth&gt; net:add(nn.Linear(3,4))\r\nth&gt; net:add(nn.ReLU())\r\nth&gt; net:add(nn.Linear(4,2))\r\nth&gt; net:add(nn.ReLU())<\/pre>\n<p>T\u00e4ss\u00e4 osassa olemme nyt k\u00e4sitelleet yksinkertaisia neuroverkkoja, joilla voidaan k\u00e4sitell\u00e4 numeerista tietoa ja tehd\u00e4 niist\u00e4 p\u00e4\u00e4telmi\u00e4 joiden muoto on my\u00f6s numeerinen, josta voidaan haluttaessa my\u00f6s tehd\u00e4\u00a0on\/off -tieto. Olemme my\u00f6s n\u00e4hneet kuinka verkon painokertoimet muuttuvat koulutuksen aikana. Seuraavassa osassa katsomme miten verkko pystyy k\u00e4sittelem\u00e4\u00e4n kuvamuotoista tietoa.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>T\u00e4ss\u00e4 osassa katsotaan hieman neuroverkon sis\u00e4lle, sen rakenteeseen ja toimintaan. T\u00e4ss\u00e4 vaiheessa l\u00e4hdemme liikkeelle yksitt\u00e4isest\u00e4 keinotekoisesta &#8221;hermosolusta&#8221; ja kokeilunhaluiset voivat my\u00f6s itse yritt\u00e4\u00e4 kokeilla kuinka sellainen toimii ja oppii. Katsomme my\u00f6s kuinka n\u00e4ist\u00e4 &#8221;soluista&#8221; kootaan kerroksia ja kerroksista edelleen suurempia verkkoja. Neuroverkon perusosanen, keinotekoinen &#8221;hermosolu&#8221;, perseptroni, laskee k\u00e4yt\u00e4nn\u00f6ss\u00e4 sy\u00f6tteiden i\u2026<\/p>\n<p class=\"continue-reading-button\"> <a class=\"continue-reading-link\" href=\"https:\/\/liipetti.net\/retkia\/neuroverkot-kaytannon-johdanto-2\/\">Continue reading<i class=\"crycon-right-dir\"><\/i><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-86","post","type-post","status-publish","format-standard","hentry","category-neuroverkot"],"_links":{"self":[{"href":"https:\/\/liipetti.net\/retkia\/wp-json\/wp\/v2\/posts\/86","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/liipetti.net\/retkia\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/liipetti.net\/retkia\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/liipetti.net\/retkia\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/liipetti.net\/retkia\/wp-json\/wp\/v2\/comments?post=86"}],"version-history":[{"count":13,"href":"https:\/\/liipetti.net\/retkia\/wp-json\/wp\/v2\/posts\/86\/revisions"}],"predecessor-version":[{"id":100,"href":"https:\/\/liipetti.net\/retkia\/wp-json\/wp\/v2\/posts\/86\/revisions\/100"}],"wp:attachment":[{"href":"https:\/\/liipetti.net\/retkia\/wp-json\/wp\/v2\/media?parent=86"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/liipetti.net\/retkia\/wp-json\/wp\/v2\/categories?post=86"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/liipetti.net\/retkia\/wp-json\/wp\/v2\/tags?post=86"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}