Neural Network

Neural network on ollut pitkään kehityksen kohteena, koska älykkään ohjelman luominen on siitänyt ihmisten silmissä. Neuraali verkko ei itsessään ole älykäs. Se on tavallaan vain funktio, joka toteuttaa tietyn sille ohjatun toimenpiteen, joka on tavallaan opetettu verkolle.

Verkko on täynnä avoimen lähde koodin neuroverkkoja, joiden käyttöön otto on päähän hakkaamista. Ohjeet ovat monesti tehty varsin typerästi. Useimmista saa kuvan, että ne on luotu lähinnä kuvan tunnistusta varten.

Toisaalta netissä on myös ohjeita, joiden pohjalta pääsee rakentamaan itse neuroverkon. Seuraava esimerkki on yksinkertainen neuroverkko esimerkki, miten neuroverkon saa ratkaisemaan yksinkertaisia laskutehtäviä, kuten yhteen laskun ja kertolaskun. Neuroverkko on parhaimmillaan etsiessään aineista yhteneväisyyksiä, mutta tiellä menetelmien ymmärtämiseen on hyvä ensin tutustua, miten päätteleminen oikeasti verkossa tapahtuu.

Yhteen laskeva neuroverkko

Neuroverkot perustuvat painotusten ympärille. Laskennan tärkein metoodi on metoodi, jolta kysytään vastausta ongelmaan. Mutta ennen ongelmaa tarvitsemme python luokan, jonne laskennan sijoitamme.

class Neural:
     def __init__(self, minLoops=100, perStep=0.01):
         self.weigths = []
         self.minLoops = minLoops
         self.perStep = perStep

     def TellMe(self, question: []):
         activation = self.weigths[0]
         for i in range(len(question) - 1):
             activation += self.weigths[i + 1] * question[i]
         return round(activation, 2)

Tämä luokka ei käytä neuraalissa verkossa tuttua aktivaatifunktiota, vaan aktivoi itsensä pelkällä numerolla. Tämä on tarkoitettu helposti ymmärettäväksi esimerkiksi, joten en ole sekoittanut tähän aktivaatiofunktiota, koska sitä ei käytännössä tarvita. Tämä on enemmänkin pieni esimerkki leikki siitä, millä tavalla matemaattikka vaikuttaa verkoin toimintaan.

TellMe funtio laskee painotusten avulla vastauksen. Panoitukset ovat tärkein lenkki oppivan verkon toiminnassa. Verkko on itseasiassa pelkkä tila muisti, joka talletettujen painotusten avulla toistaa opittua algoritmia.

Luokka muuttuu toimivaksi sen jälkeen, kun siihen lisätään treenaus mahdollisuus.

class Neural:
     def __init__(self, minLoops=100, perStep=0.01):
         self.weigths = []
         self.minLoops = minLoops
         self.perStep = perStep

     def TellMe(self, question: []):
         activation = self.weigths[0]
         for i in range(len(question) - 1):
             activation += self.weigths[i + 1] * question[i]
         return round(activation, 2)

     def LetsTrain(self, train, expected):
         self.weigths = [0.0 for i in range(len(train[0]))]
         ret = 0
         counter = 0
         while ret != 100 and counter < 60:
             for epoch in range(self.minLoops):
                 sum_error = 0.0
                 line = 0
                 for row in train:
                     maybe = self.TellMe(row)
                     error = expected[line] - maybe
                     sum_error += error ** 2
                     self.weigths[0] = self.weigths[0] + self.perStep * error
                     for i in range(len(row) - 1):
                         self.weigths[i + 1] = self.weigths[i + 1] + self.perStep * error * row[i]
                     line += 1
             ret = self.validation(train, expected)
             counter += 1

Lisäksi tämä vaatii vielä yhden lisä funktion, jotta se on vähän optimoidumpi.

def validation(self, train, expected):
       line = 0
       right = 0
       for row in train:
           value = self.TellMe(row)
           if (value == expected[line]):
               right += 1
           line += 1
       ret = right / line * 100
       print(str(ret) + '%')
       return ret

No, niin nyt meillä neuroverkko jolle voi opettaa niin jännää juttua kuin yhteen laskua. Kokeillaampa. Opetetaan verkko laskemaan yhteen arvolla 2. Jokainen tällainen solu toteuttaa vain omat rajansa. Näistä voi tietenkin rakentaa suuremman kokonaisuuden, jossa neuroverkot toimivat kokonaisuutena. Mutta meidän neuroverkkoamme opetetaan tällä tavalla. Otetaan kaksi arrayta

train = [[-1,2],[1,2], [3,2], [5,2], [7,2] , [9,2]]
expected =[1, 3, 5, 7, 9, 11  ]

neuron = Neural()
neuron.LetsTrain(train=train, expected= expected)

answer = neuron.TellMe([13,2])

print(answer)

Huimaa, vastaus on 15. Validatio verkollamme on hämmentävä 100%, joka on tällaisille tiettyyn kaavaan perustuville neuroverkoille päivän selvyys. Kun käytetään ei suoraviivaiseen toimintaan perustuvia verkkoja, niin validatio ei ihan ole näin selvää.

Kertotaulu

Pienellä muutoksella saadaan sama verkko oppimaan kertolaskua.

class Neural:
    def __init__(self, minLoops=100, perStep=0.01):
        self.weigths = []
        self.minLoops = minLoops
        self.perStep = perStep

    def TellMe(self, question: []):
        activation = self.weigths[0]
        for i in range(len(question) - 1):
            activation *= self.weigths[i + 1] * question[i]
        return round(activation, 2)

    def LetsTrain(self, train, expected):
        self.weigths = [0.0 for i in range(len(train[0]))]
        ret = 0
        counter = 0
        while ret != 100 and counter < 60:
            for epoch in range(self.minLoops):
                sum_error = 0.0
                line = 0
                for row in train:
                    maybe = self.TellMe(row)
                    error = expected[line] - maybe
                    sum_error += error ** 2
                    self.weigths[0] = self.weigths[0] + self.perStep * error
                    for i in range(len(row) - 1):
                        self.weigths[i + 1] = self.weigths[i + 1] + self.perStep * error * row[i]
                    line += 1
            ret = self.validation(train, expected)
            counter += 1

    def validation(self, train, expected):
        line = 0
        right = 0
        for row in train:
            value = self.TellMe(row)
            if (value == expected[line]):
                right += 1
            line += 1
        ret = right / line * 100
        print(str(ret) + '%')
        return ret

train = [[2,2], [3,2], [4,2], [5,2], [6,2] , [7,2]]
expected =[4, 6, 8, 10, 12, 14  ]

neuron = Neural()
neuron.LetsTrain(train=train, expected= expected)

answer = neuron.TellMe([10,2])

print(answer)

Jep, noin 20. Tarkkuutta voi säädellä roundin kanssa, sillä laskentatapa verkossamme on hieman epätarkka.

Kehitysmahdollisuuksia.

Verkon saisi itseoppivaksi helpolla. TellMe funtion sisään voisi rakentaa itse treenausalueen, joka tarkistaisi listasta, onko se jo saanut kertotaulun tunnusarvon, eli kahden kertotaulussa arvon 2, kolmen kertotaulussa arvon 3 ja niin edelleen. Jos se ei olisi saanut, niin verkko treenaisi itsensä ensin ja vastaisi vasta sitten kysymykseen - eli koko treenausvaihe olisi aivan turha, kun verkko itse hoitaisi asian.

On vain mielikuvituksesta kiinni, mitä itse luoduilla verkoilla voi tehdä. Tämä oli kevyt esimerkki leikki siitä, mikä on neuroverkon pääidea. Kaikki verkot ovat lopulta jonkilaisia versioita juuri kuvatusta esimerkistä - ihan siitä huolimatta minkälaisia ns. Layereitä niissä kuvataan olevan. Noin ohjelmointiteknisesti verkot ovat oikeasti aika simppeleitä - vain matematiikka puoli voi toisinaan olla vaikeammin ymmärettävää.