{"id":300,"date":"2021-10-13T17:16:13","date_gmt":"2021-10-13T17:16:13","guid":{"rendered":"http:\/\/liipetti.net\/retkia\/?p=300"},"modified":"2021-10-13T17:16:39","modified_gmt":"2021-10-13T17:16:39","slug":"neurokuvatreenit-harj-4","status":"publish","type":"post","link":"https:\/\/liipetti.net\/retkia\/neurokuvatreenit-harj-4\/","title":{"rendered":"Neurokuvatreenit, harj 4"},"content":{"rendered":"\n<p>T\u00e4h\u00e4n astisissa harjoituksissa olemme luoneet pikselikuvan, mitanneet sen samankaltaisuutta tavoitteeseen, ja ohjanneet t\u00e4m\u00e4n poikkeaman avulla kuvaa kohti tavoitetta. Kuva on koko ajan ollut pikselimuotoinen RGB-kuva, olemme siis ohjanneet suoraan kuvan pikseleit\u00e4. T\u00e4ss\u00e4 harjoituksessa kuva syntyy aivan toisella tavalla, niinkin erikoisella ettei se ole mitenk\u00e4\u00e4n kovin yleinen. Kun aloin tehd\u00e4 n\u00e4it\u00e4 harjoituksia maaliskuussa 2021, t\u00e4m\u00e4 oli kuitenkin uusinta uutta, ja sen verran omaa luokkaansa, ett\u00e4 sopii hyvin vastapainoksi sille ett\u00e4 muutamme kuva pikseleit\u00e4 suoraan. <\/p>\n\n\n\n<p>Pikselien sijaan meill\u00e4 on funktio, joka antaa koordinaattien perusteella pikselien arvot. Kuulostaa varmaan villilt\u00e4, oli matemaattinen funktion k\u00e4site tuttu tai ei. Voidaan ajatella, ett\u00e4 meill\u00e4 on musta laatikko. jonne voimme antaa pikselin koordinaatit (paikat kuvassa) ja saamme sielt\u00e4 pikselin RGB-arvot. Viel\u00e4 hurjempaa on, ett\u00e4 funktio ei edes tied\u00e4 mit\u00e4\u00e4n pikseleist\u00e4. Se on jatkuva, eli saamme sielt\u00e4 pikselien arvot my\u00f6s pikselien v\u00e4lill\u00e4. Kuva ei ole sidottu tiettyyn resoluutioon, periaatteessa voisimme saada kuvan sielt\u00e4 mill\u00e4 hyv\u00e4ns\u00e4 resoluutiolla.  <\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/siren-only2.png\" alt=\"\" class=\"wp-image-302\" width=\"457\" height=\"292\" srcset=\"https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/siren-only2.png 715w, https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/siren-only2-300x192.png 300w, https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/siren-only2-235x150.png 235w, https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/siren-only2-150x96.png 150w\" sizes=\"auto, (max-width: 457px) 100vw, 457px\" \/><\/figure>\n\n\n\n<p><a rel=\"noreferrer noopener\" href=\"https:\/\/vsitzmann.github.io\/siren\/\" target=\"_blank\">SIREN<\/a> toteuttaa t\u00e4llaisen funktion neuroverkon avulla; k\u00e4yt\u00e4nn\u00f6ss\u00e4 se on neuroverkko joka koostuu kerroksista ja joka opetetaan yhdell\u00e4 ainoalla kuvalla. Koordinaatit annetaan liukulukuina v\u00e4lill\u00e4 -1 &#8230; 1, jolloin \u00e4\u00e4rip\u00e4\u00e4t vastaavat kuvan reunoja ja (0,0) kuva keskipistett\u00e4. Pikselit l\u00f6ytyv\u00e4t, tai l\u00f6ydet\u00e4\u00e4n, sielt\u00e4 v\u00e4lilt\u00e4. Samaten pikselin RGB-arvot saadaan v\u00e4lill\u00e4 -1 &#8230; 1 miss\u00e4 -1 vastaa mustaa ja 1 t\u00e4ytt\u00e4 v\u00e4ri\u00e4.<\/p>\n\n\n\n<p>Kuinka me sitten saamme kuvan sielt\u00e4 ulos, puhumattakaan siit\u00e4 miten tuo on koulutettavissa? Teemme yksinkertaisesti wrapperin, ohjelman joka toimii ik\u00e4\u00e4nkuin k\u00e4\u00e4reen\u00e4 SIREN:ille, k\u00e4y kaikki pikselit l\u00e4pi muuttamalla koordinaattien arvoja sopivin v\u00e4lein, ja tallettaa saadut arvot pikselikuvaan. Itse asiassa, koska neuroverkot yleens\u00e4 tehd\u00e4\u00e4n k\u00e4sittelem\u00e4\u00e4n kokonainen er\u00e4 kerrallaan, voimme tehd\u00e4 tensorin, jossa on kaikkien pikselien koordinaatit, ja n\u00e4in saada kerralla valmis pikselikuva ulos. Juuri n\u00e4in t\u00e4m\u00e4n harjoituksen SIREN-toteutus toimii.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/warpper-only2.png\" alt=\"\" class=\"wp-image-304\" width=\"407\" height=\"381\" srcset=\"https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/warpper-only2.png 705w, https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/warpper-only2-300x281.png 300w, https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/warpper-only2-160x150.png 160w, https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/warpper-only2-150x140.png 150w\" sizes=\"auto, (max-width: 407px) 100vw, 407px\" \/><\/figure>\n\n\n\n<p>Kuinka sitten sovitamme t\u00e4mm\u00f6isen kummajaisen siihen mit\u00e4 olemme tekem\u00e4ss\u00e4? Olemme tekem\u00e4ss\u00e4 kuvaa, meid\u00e4n pit\u00e4\u00e4 korvata pikselimatriisi imgG SIREN:ill\u00e4 ja wrapperill\u00e4, siit\u00e4 saamme pikselimatriisin ja voimme jatkaa kuten t\u00e4h\u00e4nkin asti.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/harj4.png\" alt=\"\" class=\"wp-image-306\" width=\"449\" height=\"315\" srcset=\"https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/harj4.png 852w, https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/harj4-300x211.png 300w, https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/harj4-768x540.png 768w, https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/harj4-213x150.png 213w, https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/harj4-150x105.png 150w\" sizes=\"auto, (max-width: 449px) 100vw, 449px\" \/><\/figure>\n\n\n\n<p>K\u00e4yd\u00e4\u00e4n sitten itse koodin kimppuun. SIREN l\u00f6ytyy pip-pakettina, asentuu komennolla<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">pip install siren-pytorch\n<\/pre>\n\n\n\n<p>ja itse ohjelmassa otamme em. paketista k\u00e4ytt\u00f6\u00f6n Sirenin ja sen wrapperin<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">from siren_pytorch import SirenNet, SirenWrapper<\/pre>\n\n\n\n<p>Katsotaan t\u00e4ll\u00e4 kertaa my\u00f6s kaikki parametrit t\u00e4ss\u00e4. Tarvitsemme kuvatiedoston, koulutustahdin, koulutuskierrosten m\u00e4\u00e4r\u00e4n, lopullisen kuvakoon, nimen jolla tallennetaan. Voimme valita n\u00e4ytet\u00e4\u00e4nk\u00f6 kuvaa my\u00f6s n\u00e4yt\u00f6ll\u00e4 ikkunassa. Tavoitefunktiossa k\u00e4yt\u00e4mme nyt SSIM:i\u00e4 ja pikselikohtaista virhett\u00e4 (MSE).  <\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># use command line parameters\nparser = argparse.ArgumentParser()\n\n# define params and their types with defaults if needed\n\nparser.add_argument('--image', type=str, default=\"test.png\", help='path to image')\nparser.add_argument('--lr', type=float, default=0.0005, help='learning rate')\nparser.add_argument('--niter', type=int, default=150, help='number of iterations')\nparser.add_argument('--imageSize', type=int, default=256, help='image size')\nparser.add_argument('--name', type=str, default=\"harj4\", help='basename for storing images')\nparser.add_argument('--show', action=\"store_true\", help='show image in a window')\nparser.add_argument('--ssim', type=float, default=1, help='ssim weight')\nparser.add_argument('--mse', type=float, default=1, help='mse weight')\n\n\n# get params into opt object, so we can access them like opt.image\n\nopt = parser.parse_args()<\/pre>\n\n\n\n<p>Luodaan sitten itse SIREN ja sille wrapper, aluksi kiinteill\u00e4 asetuksilla. Voimme my\u00f6hemmin muuttaa koodia niin ett\u00e4 niit\u00e4kin voi antaa komentorivilit\u00e4. <\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># NOW LET'S SET UP SIREN\n\nsiren = SirenNet(\n    dim_in = 2,                        # input dimension, ex. 2d coor\n    dim_hidden = 256,                  # hidden dimension\n    dim_out = 3,                       # output dimension, ex. rgb value\n    num_layers = 6,                    # number of layers\n    w0_initial = 30.,                   # different signals may require different omega_0 in the first layer - this is a hyperparameter\n    final_activation = nn.Tanh()\n)\n\nwrapper = SirenWrapper(\n    siren,\n    image_width = opt.imageSize,\n    image_height = opt.imageSize\n)\n<\/pre>\n\n\n\n<p>Ennen kuin alamme optimoida, pit\u00e4\u00e4 viel\u00e4 valita mit\u00e4 tarkalleen optimoidaan, mik\u00e4 on sit\u00e4 mink\u00e4 haluamme muuttuvan koulutuksen my\u00f6t\u00e4. Ja jotta hommassa olisi mielt\u00e4, muutoksen t\u00e4ytyy kohdistua johonkin sellaiseen mink\u00e4 muuttaminen pystyy viem\u00e4\u00e4n kuvaa l\u00e4hemm\u00e4s tavoitetta. Aiemmissa harjoituksissa annoimme itse pikselien muuttua. Nyt pit\u00e4isi saada SIREN oppimaan se funktio, joka vastaa haluttua kuvaa. <\/p>\n\n\n\n<p>SIREN on neuroverkko, joka on nimenomaan suunniteltu oppimaan t\u00e4llainen funktio. Ja ensimm\u00e4inen neuroverkko jonka otamme k\u00e4ytt\u00f6\u00f6n t\u00e4ss\u00e4 kurssissa. Emme nyt sukella sen sisuskaluihin, riitt\u00e4\u00e4 ett\u00e4 se koostuu kerroksista, ja kukin kerros k\u00e4sitt\u00e4\u00e4 suuren m\u00e4\u00e4r\u00e4 opittavissa olevia parametreja, enimm\u00e4kseen painokertoimia joita k\u00e4ytet\u00e4\u00e4n laskennassa. Ja meid\u00e4n ei nyt edes tarvitse tiet\u00e4\u00e4 enemp\u00e4\u00e4 n\u00e4ist\u00e4 parametreist\u00e4, Siren on aito torch.nn -moduli, siin\u00e4 on rajapinta jonka kautta l\u00f6yd\u00e4mme ne parametrit ja voimme luoda optimoijan seuraavasti<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># Now we want to optimize parameters inside SIREN to produce the image\n\noptimizer = torch.optim.Adam(siren.parameters(), opt.lr)<\/pre>\n\n\n\n<p>Itse koulutussilmukka kokonaisuudessaan on t\u00e4ss\u00e4. Aluksi nollamme optimoijan gradientin, mik\u00e4 tarkoittaa yksinkertaisesti sit\u00e4 ett\u00e4 edellisen kierroksen aikana havaittu poikkeama unohdetaan. Haetaan kuva Sirenin wrapperilta. Lasketaan virhe, sek\u00e4 SSIM:in ett\u00e4 pikselivirheen avulla. Sitten valutetaan virhe takaperin, mink\u00e4 seurauksena konepellin alla on ns. gradientti, tieto siit\u00e4 kuinka paljon kukin verkon painokerroin on pieless\u00e4 ja mihin suuntaan. Optimoija sitten s\u00e4\u00e4t\u00e4\u00e4 niit\u00e4 hivenen oikeaan suuntaan, n\u00e4in verkko oppii.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">for i in range(0, niter):\n    optimizer.zero_grad()\n    \n    # get image from Siren\n    imgout = wrapper()\n    \n     # calculate loss\n\n    loss = opt.ssim * (1 - ssim(imgT.unsqueeze(0), imgout)) \n\n    # in addition to SSIM, we now also use pixel loss as measured by MSE loss \n    # MSE = mean square error (google for more)\n\n    if opt.mse &gt; 0:\n        loss += opt.mse * F.mse_loss(imgT.unsqueeze(0), imgout)\n\n    # run backwards to find gradient (how to change imgG to make loss smaller) \n    loss.backward()\n\n    # run optimizer to change imgT\n    optimizer.step()\n\n    # print loss to show how we are doing\n    print(i, loss.item())\n\n    # save image\n    if (i &lt; 10) or (i % 10 == 0):\n        save_image(imgout, opt.name+str(i)+\".jpg\", normalize=True)\n\n    # show on screen\n    if opt.show:\n        show_on_screen(imgout[0], opt.name)\n    <\/pre>\n\n\n\n<p>Kun t\u00e4t\u00e4 kokeilee ajaa, huomaa heti eron suoran pikselikuvan tekoon. Alussakaan kuva ei ole ns. lumisadetta, kohinaa, vaan jonkinlaista v\u00e4rit\u00e4pl\u00e4st\u00f6\u00e4. Ja kun sireenin antaa oppia, niin alkaahan sielt\u00e4 kuva l\u00f6yty\u00e4.<\/p>\n\n\n\n<figure class=\"wp-block-gallery columns-4 is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex\"><ul class=\"blocks-gallery-grid\"><li class=\"blocks-gallery-item\"><figure><img loading=\"lazy\" decoding=\"async\" width=\"256\" height=\"256\" src=\"https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/t1-ssim1mse10-1.jpg\" alt=\"\" data-id=\"314\" data-link=\"https:\/\/liipetti.net\/retkia\/?attachment_id=314\" class=\"wp-image-314\" srcset=\"https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/t1-ssim1mse10-1.jpg 256w, https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/t1-ssim1mse10-1-150x150.jpg 150w\" sizes=\"auto, (max-width: 256px) 100vw, 256px\" \/><\/figure><\/li><li class=\"blocks-gallery-item\"><figure><img loading=\"lazy\" decoding=\"async\" width=\"256\" height=\"256\" src=\"https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/t1-ssim1mse110.jpg\" alt=\"\" data-id=\"315\" data-link=\"https:\/\/liipetti.net\/retkia\/?attachment_id=315\" class=\"wp-image-315\" srcset=\"https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/t1-ssim1mse110.jpg 256w, https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/t1-ssim1mse110-150x150.jpg 150w\" sizes=\"auto, (max-width: 256px) 100vw, 256px\" \/><\/figure><\/li><li class=\"blocks-gallery-item\"><figure><img loading=\"lazy\" decoding=\"async\" width=\"256\" height=\"256\" src=\"https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/t1-ssim1mse150.jpg\" alt=\"\" data-id=\"316\" data-link=\"https:\/\/liipetti.net\/retkia\/?attachment_id=316\" class=\"wp-image-316\" srcset=\"https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/t1-ssim1mse150.jpg 256w, https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/t1-ssim1mse150-150x150.jpg 150w\" sizes=\"auto, (max-width: 256px) 100vw, 256px\" \/><\/figure><\/li><li class=\"blocks-gallery-item\"><figure><img loading=\"lazy\" decoding=\"async\" width=\"256\" height=\"256\" src=\"https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/t1-ssim1mse1320.jpg\" alt=\"\" data-id=\"317\" data-full-url=\"https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/t1-ssim1mse1320.jpg\" data-link=\"https:\/\/liipetti.net\/retkia\/?attachment_id=317\" class=\"wp-image-317\" srcset=\"https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/t1-ssim1mse1320.jpg 256w, https:\/\/liipetti.net\/retkia\/wp-content\/uploads\/2021\/10\/t1-ssim1mse1320-150x150.jpg 150w\" sizes=\"auto, (max-width: 256px) 100vw, 256px\" \/><\/figure><\/li><\/ul><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>T\u00e4h\u00e4n astisissa harjoituksissa olemme luoneet pikselikuvan, mitanneet sen samankaltaisuutta tavoitteeseen, ja ohjanneet t\u00e4m\u00e4n poikkeaman avulla kuvaa kohti tavoitetta. Kuva on koko ajan ollut pikselimuotoinen RGB-kuva, olemme siis ohjanneet suoraan kuvan pikseleit\u00e4. T\u00e4ss\u00e4 harjoituksessa kuva syntyy aivan toisella tavalla, niinkin erikoisella ettei se ole mitenk\u00e4\u00e4n kovin yleinen. Kun aloin tehd\u00e4 n\u00e4it\u00e4\u2026<\/p>\n<p class=\"continue-reading-button\"> <a class=\"continue-reading-link\" href=\"https:\/\/liipetti.net\/retkia\/neurokuvatreenit-harj-4\/\">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":[8],"tags":[],"class_list":["post-300","post","type-post","status-publish","format-standard","hentry","category-neurokuvatreenit"],"_links":{"self":[{"href":"https:\/\/liipetti.net\/retkia\/wp-json\/wp\/v2\/posts\/300","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=300"}],"version-history":[{"count":11,"href":"https:\/\/liipetti.net\/retkia\/wp-json\/wp\/v2\/posts\/300\/revisions"}],"predecessor-version":[{"id":319,"href":"https:\/\/liipetti.net\/retkia\/wp-json\/wp\/v2\/posts\/300\/revisions\/319"}],"wp:attachment":[{"href":"https:\/\/liipetti.net\/retkia\/wp-json\/wp\/v2\/media?parent=300"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/liipetti.net\/retkia\/wp-json\/wp\/v2\/categories?post=300"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/liipetti.net\/retkia\/wp-json\/wp\/v2\/tags?post=300"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}