Rețea neuronală în Python de la zero. Cum se creează inteligență artificială? Un ghid (aproape) cuprinzător

18.02.2022 Photoshop

Săptămâna aceasta ai putut citi un caz extrem de motivant de la un student GeekBrains care a studiat profesia, în care a vorbit despre unul dintre obiectivele sale care au condus la profesie - dorința de a învăța principiul muncii și de a învăța cum să creezi tu însuți boți de gaming.

Dar, într-adevăr, dorința de a crea inteligență artificială perfectă, fie că este vorba de un model de joc sau de un program mobil, a fost cea care ne-a împins pe mulți dintre noi pe calea unui programator. Problema este că în spatele tonelor de material educațional și a realității dure a clienților, tocmai această dorință a fost înlocuită cu o simplă dorință de autodezvoltare. Pentru cei care nu au început încă să-și împlinească visul din copilărie, iată un scurt ghid pentru crearea unei inteligențe artificiale reale.

Etapa 1. Dezamăgire

Când vorbim despre crearea unor roboți chiar și simpli, ochii ni se umplu de strălucire și sute de idei ne trec prin cap cu privire la ceea ce ar trebui să poată face. Cu toate acestea, când vine vorba de implementare, se dovedește că cheia pentru dezlegarea modelului real de comportament este matematica. Da, da, inteligența artificială este mult mai complicată decât scrierea de programe de aplicație - cunoștințele despre design software nu vor fi suficiente pentru tine.

Matematica este rampa științifică pe care se va construi programarea ulterioară. Fără cunoașterea și înțelegerea acestei teorii, toate ideile se vor rupe rapid din cauza interacțiunii cu o persoană, deoarece inteligența artificială nu este de fapt nimic altceva decât un set de formule.

Etapa 2. Acceptare

Când aroganța este puțin doborâtă de literatura studențească, poți începe să exersezi. Încă nu merită să te grăbești la LISP sau altele - mai întâi ar trebui să te simți confortabil cu principiile designului AI. Python este perfect atât pentru învățarea rapidă, cât și pentru dezvoltarea ulterioară - este un limbaj cel mai des folosit în scopuri științifice, pentru care veți găsi multe biblioteci care vă vor ușura munca.

Etapa 3. Dezvoltare

Acum să trecem direct la teoria AI. Acestea pot fi împărțite aproximativ în 3 categorii:

  • AI slabă - roboți pe care îi vedem în jocurile pe calculator sau simpli asistenți precum Siri. Ei fie îndeplinesc sarcini foarte specializate, fie sunt un complex nesemnificativ al acestora, iar orice imprevizibilitate a interacțiunii îi derutează.
  • AI puternice sunt mașini a căror inteligență este comparabilă cu creierul uman. În prezent nu există reprezentanți adevărați ai acestei clase, dar computere precum Watson sunt foarte aproape de atingerea acestui obiectiv.
  • AI perfectă este viitorul, un creier de mașină care ne va depăși capacitățile. Stephen Hawking, Elon Musk și franciza de film Terminator avertizează despre pericolele unor astfel de evoluții.

Desigur, ar trebui să începeți cu cei mai simpli roboți. Pentru a face acest lucru, amintiți-vă de vechiul joc „Tic Tac Toe” atunci când utilizați un câmp 3x3 și încercați să vă dați seama de algoritmii de bază ai acțiunilor: probabilitatea de victorie cu acțiuni fără erori, locurile cele mai de succes pe teren pentru plasați o piesă, necesitatea reducerii jocului la egalitate și așa mai departe.

Câteva zeci de jocuri și analizând propriile acțiuni, probabil că veți putea identifica toate aspectele importante și le veți rescrie în codul mașinii. Dacă nu, atunci continuă să te gândești și acest link va fi aici pentru orice eventualitate.

Apropo, dacă ați preluat în sfârșit limbajul Python, atunci puteți crea un bot destul de simplu, referindu-vă la acest manual detaliat. Pentru alte limbi, cum ar fi C++ sau Java, nu veți avea probleme în a găsi materiale pas cu pas. Odată ce simțiți că nu există nimic supranatural în spatele creării AI, puteți închide browserul în siguranță și puteți începe experimente personale.

Etapa 4. Excitare

Acum că lucrurile au demarat, probabil că doriți să creați ceva mai serios. Următoarele resurse vă vor ajuta în acest sens:

După cum înțelegeți chiar și din nume, acestea sunt API-uri care vă vor permite să creați o aparență de AI serioasă fără a pierde timpul.

Etapa 5. Munca

Acum că aveți o idee clară despre cum să creați AI și ce să utilizați, este timpul să vă duceți cunoștințele la nivelul următor. În primul rând, aceasta va necesita studierea unei discipline numită „Învățare automată”. În al doilea rând, trebuie să învățați cum să lucrați cu bibliotecile corespunzătoare ale limbajului de programare ales. Pentru Python-ul pe care îl analizăm, acestea sunt Scikit-learn, NLTK, SciPy, PyBrain și Numpy. În al treilea rând, în dezvoltare nu există nicio cale de ocolire. Ei bine, și cel mai important, acum puteți citi literatură despre AI cu o înțelegere completă a problemei:

  • Inteligența artificială pentru jocuri, Ian Millington;
  • Modele de programare a jocurilor, Robert Naystorm;
  • Algoritmi AI, structuri de date și idiomuri în Prolog, Lisp și Java, George Luger, William Stubfield;
  • Computational Cognitive Neuroscience, Randall O'Reilly, Yuko Munakata;
  • Inteligența artificială: o abordare modernă, Stuart Russell, Peter Norvig.

Și da, toată sau aproape toată literatura pe această temă este prezentată într-o limbă străină, așa că dacă doriți să creați AI profesional, trebuie să vă îmbunătățiți limba engleză la un nivel tehnic. Cu toate acestea, acest lucru este relevant pentru orice domeniu de programare, nu-i așa?

Rețelele neuronale sunt create și antrenate în principal în Python. Prin urmare, este foarte important să aveți o înțelegere de bază despre cum să scrieți programe în el. În acest articol voi vorbi pe scurt și clar despre conceptele de bază ale acestui limbaj: variabile, funcții, clase și module.

Materialul este destinat persoanelor care nu sunt familiarizate cu limbajele de programare.

Mai întâi trebuie să instalați Python. Apoi, trebuie să instalați un mediu convenabil pentru scrierea programelor în Python. Portalul este dedicat acestor doi pași.

Dacă totul este instalat și configurat, puteți începe.

Variabile

Variabilă- un concept cheie în orice limbaj de programare (și nu numai în ele). Cel mai simplu mod de a gândi o variabilă este ca o cutie cu o etichetă. Această cutie conține ceva (un număr, o matrice, un obiect, ...) care este valoros pentru noi.

De exemplu, dorim să creăm o variabilă x care să stocheze valoarea 10. În Python, codul pentru crearea acestei variabile ar arăta astfel:

În stânga noi anuntam noi o variabilă numită x. Acest lucru este echivalent cu a pune o etichetă de nume pe cutie. Urmează semnul egal și numărul 10. Semnul egal joacă un rol neobișnuit aici. Nu înseamnă că „x este egal cu 10”. Egalitatea în acest caz pune numărul 10 în casetă. Pentru a spune mai corect, noi atribui variabila x este numărul 10.

Acum, în codul de mai jos putem accesa această variabilă și, de asemenea, putem efectua diverse acțiuni cu ea.

Puteți afișa pur și simplu valoarea acestei variabile pe ecran:

X=10 print(x)

print(x) reprezintă un apel de funcție. Le vom lua în considerare în continuare. Important este acum că această funcție imprimă pe consolă ceea ce este situat între paranteze. Între paranteze avem x. Anterior, am atribuit lui x valoarea 10. Acesta este ceea ce 10 este tipărit în consolă dacă rulați programul de mai sus.

Se pot efectua diverse operații simple cu variabile care stochează numere: adunare, scădere, înmulțire, împărțire și exponențiere.

X = 2 y = 3 # Adunarea z = x + y print(z) # 5 # Diferența z = x - y print(z) # -1 # Produs z = x * y print(z) # 6 # Diviziunea z = x / y print(z) # 0,66666... ​​​​# Exponentiation z = x ** y print(z) # 8

În codul de mai sus, creăm mai întâi două variabile care conțin 2 și 3. Apoi creăm o variabilă z care stochează rezultatul operației pe x și y și tipărește rezultatele pe consolă. Acest exemplu arată clar că o variabilă își poate schimba valoarea în timpul execuției programului. Deci, variabila noastră z își schimbă valoarea de până la 5 ori.

Funcții

Uneori devine necesar să efectuați aceleași acțiuni din nou și din nou. De exemplu, în proiectul nostru avem deseori nevoie să afișăm 5 rânduri de text.

„Acesta este un text foarte important!”
„Acest text nu poate fi citit”
„Greșeala din linia de sus a fost făcută intenționat”
"Bună și la revedere"
"Sfârşit"

Codul nostru va arăta astfel:

X = 10 y = x + 8 - 2 print("Acesta este un text foarte important!") print("Acest text nu poate fi citit") print("Eroarea din linia de sus a fost făcută intenționat") print(" Bună și pa") print ("The End") z = x + y print(„Acesta este un text foarte important!") print(„Acest text nu poate fi citit") print(„Greșeala din linia de sus a fost făcută intenționat”) print(„Bună ziua și pa”) print („Sfârșitul”) test = z print(„Acesta este un text foarte important!”) print(„Acest text nu poate fi citit”) print(„Greșeala în linia de sus a fost făcută intenționat") print("Salut și pa") print("Sfârșit")

Totul pare foarte redundant și incomod. În plus, a existat o eroare în a doua linie. Poate fi reparat, dar va trebui să fie fixat în trei locuri deodată. Ce se întâmplă dacă aceste cinci linii sunt apelate de 1000 de ori în proiectul nostru? Și totul este în locuri și fișiere diferite?

Mai ales pentru cazurile în care trebuie să executați frecvent aceleași comenzi, puteți crea funcții în limbaje de programare.

Funcţie- un bloc separat de cod care poate fi numit după nume.

O funcție este definită folosind cuvântul cheie def. Acesta este urmat de numele funcției, apoi de paranteze și două puncte. În continuare, trebuie să enumerați, indentat, acțiunile care vor fi efectuate atunci când funcția este apelată.

Def print_5_lines(): print("Acesta este un text foarte important!") print("Acest text nu poate fi citit") print("Eroarea din linia de sus a fost făcută intenționat") print("Salut și pa") print(„Sfârșitul”)

Acum am definit funcția print_5_lines(). Acum, dacă în proiectul nostru trebuie din nou să inserăm cinci linii, atunci pur și simplu numim funcția noastră. Acesta va efectua automat toate acțiunile.

# Definiți funcția def print_5_lines(): print("Acesta este un text foarte important!") print("Acest text nu poate fi citit") print("Eroarea din linia de sus a fost intenționată") print("Salut și pa ") print(" End") # Codul proiectului nostru x = 10 y = x + 8 - 2 print_5_lines() z = x + y print_5_lines() test = z print_5_lines()

Convenabil, nu-i așa? Am îmbunătățit serios lizibilitatea codului. În plus, funcțiile sunt de asemenea bune, deoarece dacă doriți să schimbați unele dintre acțiuni, atunci trebuie doar să corectați funcția în sine. Această modificare va funcționa în toate locurile în care este apelată funcția dvs. Adică, putem corecta eroarea din a doua linie a textului de ieșire („nu” > „nu”) din corpul funcției. Opțiunea corectă va fi apelată automat în toate locurile din proiectul nostru.

Funcții cu parametri

Este cu siguranță convenabil să repeți pur și simplu mai multe acțiuni. Dar asta nu este tot. Uneori vrem să transmitem o variabilă funcției noastre. În acest fel, funcția poate accepta date și le poate folosi în timpul executării comenzilor.

Variabilele pe care le transmitem funcției sunt numite argumente.

Să scriem o funcție simplă care adună două numere date și returnează rezultatul.

Def sum(a, b): rezultat = a + b returnează rezultat

Prima linie arată aproape la fel ca funcțiile obișnuite. Dar între paranteze există acum două variabile. Acest parametrii funcții. Funcția noastră are doi parametri (adică necesită două variabile).

Parametrii pot fi utilizați în interiorul unei funcții la fel ca variabilele obișnuite. Pe a doua linie creăm un rezultat variabil, care este egal cu suma parametrilor a și b. Pe a treia linie returnăm valoarea variabilei rezultat.

Acum, în cod suplimentar, putem scrie ceva de genul:

Nou = suma(2, 3) print(nou)

Numim funcția sum și îi transmitem pe rând două argumente: 2 și 3. 2 devine valoarea variabilei a, iar 3 devine valoarea variabilei b. Funcția noastră returnează o valoare (suma 2 și 3) și o folosim pentru a crea o nouă variabilă, new .

Ține minte. În codul de mai sus, numerele 2 și 3 sunt argumentele funcției de sumă. Și în funcția de sumă în sine, variabilele a și b sunt parametri. Cu alte cuvinte, variabilele pe care le transmitem unei funcții atunci când este apelată se numesc argumente. Dar în interiorul funcției, aceste variabile transmise sunt numite parametri. De fapt, acestea sunt două nume pentru același lucru, dar nu trebuie confundate.

Să ne uităm la un alt exemplu. Să creăm o funcție pătrat(a) care ia un număr și îl pătratează:

Def pătrat(a): returnează a * a

Funcția noastră constă dintr-o singură linie. Returnează imediat rezultatul înmulțirii parametrului a cu a .

Cred că ați ghicit deja că trimitem și date către consolă folosind o funcție. Această funcție se numește print() și afișează argumentul transmis în consolă: un număr, un șir, o variabilă.

Matrice

Dacă o variabilă poate fi gândită ca o cutie care stochează ceva (nu neapărat un număr), atunci matricele pot fi gândite ca rafturi de cărți. Acestea conțin mai multe variabile simultan. Iată un exemplu de matrice de trei numere și un șir:

Matrice =

Iată un exemplu când o variabilă nu conține un număr, ci un alt obiect. În acest caz, variabila noastră conține o matrice. Fiecare element de matrice este numerotat. Să încercăm să afișăm un element al matricei:

Array = print(matrice)

În consolă vei vedea numărul 89. Dar de ce 89 și nu 1? Chestia este că în Python, ca și în multe alte limbaje de programare, numerotarea matricelor începe de la 0. Prin urmare, array ne oferă doilea element al matricei, nu primul. Pentru a-l apela pe primul, a trebuit să scrieți array .

Dimensiunea matricei

Uneori este foarte util să obțineți numărul de elemente dintr-o matrice. Puteți utiliza funcția len() pentru aceasta. Acesta va număra numărul de elemente și va returna numărul acestora.

Array = print(len(matrice))

Consola va afișa numărul 4.

Condiții și cicluri

În mod implicit, orice program pur și simplu execută toate comenzile într-un rând de sus în jos. Dar există situații în care trebuie să verificăm o anumită condiție și, în funcție de faptul că este adevărată sau nu, să realizăm diferite acțiuni.

În plus, este adesea nevoie să repeți aproape aceeași secvență de comenzi de multe ori.

În prima situație, condițiile ajută, iar în a doua, ciclurile ajută.

Termeni

Sunt necesare condiții pentru a efectua două seturi diferite de acțiuni, în funcție de faptul dacă afirmația testată este adevărată sau falsă.

În Python, condițiile pot fi scrise folosind constructul if: ... else: .... Să avem o variabilă x = 10. Dacă x este mai mic de 10, atunci vrem să împărțim x la 2. Dacă x este mai mare sau egal cu 10, atunci vrem să creăm o altă variabilă, new , care este egală cu suma lui x și numărul 100. Aceasta asa ar arata codul:

X = 10 dacă (x< 10): x = x / 2 print(x) else: new = x + 100 print(new)

După crearea variabilei x, începem să ne scriem condiția.

Totul începe cu cuvântul cheie dacă (tradus din engleză ca „dacă”). În paranteză indicăm expresia care trebuie verificată. În acest caz, verificăm dacă variabila noastră x este într-adevăr mai mică de 10. Dacă este într-adevăr mai mică de 10, atunci o împărțim la 2 și imprimăm rezultatul pe consolă.

Apoi urmează cuvântul cheie else, după care începe un bloc de acțiuni care vor fi efectuate dacă expresia dintre paranteze după if este falsă.

Dacă este mai mare sau egală cu 10, atunci creăm o nouă variabilă new, care este egală cu x + 100 și, de asemenea, o scoatem în consolă.

Cicluri

Buclele sunt necesare pentru a repeta acțiunile de mai multe ori. Să presupunem că vrem să afișăm un tabel cu pătratele primelor 10 numere naturale. Se poate face așa.

Print("Patratul 1 este " + str(1**2)) print("Patratul 2 este " + str(2**2)) print("Patratul 3 este " + str(3**2)) print( "Pătratul 4 este " + str(4**2)) print("Pătratul 5 este " + str(5**2)) print("Pătratul 6 este " + str(6**2)) print("Pătrat 7 este " + str(7**2)) print("Patratul lui 8 este " + str(8**2)) print("Patratul lui 9 este " + str(9**2)) print("Patrat din 10 este " + str(10**2))

Nu fi surprins de faptul că adăugăm linii. „începutul liniei” + „sfârșitul” în Python înseamnă pur și simplu concatenarea șirurilor: „începutul liniiend”. În același mod mai sus, adăugăm șirul „Pătratul lui x este egal cu ” și rezultatul ridicării numărului la puterea a 2-a, convertit folosind funcția str(x**2).

Codul de mai sus pare foarte redundant. Ce se întâmplă dacă trebuie să tipărim pătratele primelor 100 de numere? Suntem chinuiti sa ne retragem...

Pentru astfel de cazuri există cicluri. Există 2 tipuri de bucle în Python: while și for. Să ne ocupăm de ele unul câte unul.

Bucla while repetă comenzile necesare atâta timp cât condiția rămâne adevărată.

X = 1 în timp ce x<= 100: print("Квадрат числа " + str(x) + " равен " + str(x**2)) x = x + 1

Mai întâi creăm o variabilă și îi atribuim numărul 1 Apoi creăm o buclă while și verificăm dacă x este mai mic decât (sau egal cu) 100. Dacă este mai mică (sau egală), atunci efectuăm două acțiuni:

  1. Ieșiți pătratul x
  2. Măriți x cu 1

După a doua comandă, programul revine la starea. Dacă condiția este din nou adevărată, atunci executăm din nou aceste două acțiuni. Și așa mai departe până când x devine egal cu 101. Atunci condiția va reveni fals și bucla nu va mai fi executată.

Bucla for este concepută pentru a repeta peste matrice. Să scriem același exemplu cu pătratele primei sute de numere naturale, dar printr-o buclă for.

Pentru x în interval (1.101): print("Pătratul numărului " + str(x) + " este " + str(x**2))

Să ne uităm la prima linie. Folosim cuvântul cheie for pentru a crea o buclă. În continuare, specificăm că vrem să repetăm ​​anumite acțiuni pentru toți x din intervalul de la 1 la 100. Funcția range(1,101) creează o matrice de 100 de numere, începând de la 1 și terminând cu 100.

Iată un alt exemplu de iterare printr-o matrice folosind o buclă for:

Pentru i în: print(i * 2)

Codul de mai sus scoate 4 numere: 2, 20, 200 și 2000. Aici puteți vedea clar cum ia fiecare element al matricei și efectuează un set de acțiuni. Apoi ia următorul element și repetă același set de acțiuni. Și așa mai departe până când elementele din matrice se epuizează.

Clase și obiecte

În viața reală, nu operăm cu variabile sau funcții, ci cu obiecte. Pix, mașină, persoană, pisică, câine, avion - obiecte. Acum să aruncăm o privire mai atentă la pisică.

Are niște parametri. Acestea includ culoarea hainei, culoarea ochilor și porecla ei. Dar asta nu este tot. Pe lângă parametri, pisica poate efectua diverse acțiuni: toarcă, șuiera și zgârie.

Tocmai am descris schematic toate pisicile în general. Similar descrierea proprietăților și acțiunilor un obiect (de exemplu, o pisică) în Python se numește clasă. O clasă este pur și simplu un set de variabile și funcții care descriu un obiect.

Este important să înțelegeți diferența dintre o clasă și un obiect. Clasa - sistem, care descrie obiectul. Obiectul este ea realizare materială. Clasa unei pisici este o descriere a proprietăților și acțiunilor sale. Obiectul pisicii este pisica reală în sine. Pot exista multe pisici reale diferite - multe obiecte pentru pisici. Dar există o singură clasă de pisici. O bună demonstrație este imaginea de mai jos:

Clasele

Pentru a crea o clasă (schema pisicii noastre), trebuie să scrieți clasa de cuvinte cheie și apoi să specificați numele acestei clase:

Clasa pisica:

În continuare trebuie să enumerăm acțiunile acestei clase (acțiuni pisici). Acțiunile, după cum probabil ați ghicit, sunt funcții definite în cadrul unei clase. Astfel de funcții din cadrul unei clase sunt de obicei numite metode.

Metodă- o funcție definită în interiorul unei clase.

Am descris deja verbal metodele pisicii mai sus: toarcet, șuierat, zgâriat. Acum să o facem în Python.

# Clasa clasa pisicii Cat: # Purr def purr(self): print("Purrr!") # Hiss def hiss(self): print("Shhh!") # Scratch def scrabble(self): print("Scratch-scratch !")

Este atât de simplu! Am luat și definit trei funcții obișnuite, dar numai în interiorul clasei.

Pentru a face față parametrului de sine de neînțeles, să mai adăugăm o metodă pisicii noastre. Această metodă va apela simultan toate cele trei metode deja create.

# Clasa clasa pisicii Cat: # Purr def purr(self): print("Purrr!") # Hiss def hiss(self): print("Shhh!") # Scratch def scrabble(self): print("Scratch-scratch !") # Toate împreună def all_in_one(self): self.purr() self.hiss() self.scrabble()

După cum puteți vedea, parametrul self, necesar oricărei metode, ne permite să accesăm metode și variabile ale clasei în sine! Fără acest argument, nu am putea efectua astfel de acțiuni.

Să setăm acum proprietățile pisicii noastre (culoarea blanii, culoarea ochilor, porecla). Cum să faci asta? În absolut orice clasă puteți defini funcția __init__(). Această funcție este întotdeauna apelată atunci când creăm un obiect real al clasei noastre.

În metoda __init__() evidențiată mai sus, setăm variabilele pisicii noastre. Cum facem asta? În primul rând, trecem 3 argumente acestei metode, care sunt responsabile pentru culoarea hainei, culoarea ochilor și porecla. Apoi, folosim parametrul self pentru a seta imediat pisica noastră la cele 3 atribute descrise mai sus atunci când creăm un obiect.

Ce înseamnă această linie?

Self.wool_culo = culoare_lană

În partea stângă, creăm un atribut pentru pisica noastră numit wool_color, iar apoi atribuim acestui atribut valoarea conținută în parametrul wool_color pe care l-am transmis funcției __init__(). După cum puteți vedea, linia de mai sus nu este diferită de crearea normală a variabilelor. Doar prefixul self indică faptul că această variabilă aparține clasei Cat.

Atribut- o variabilă care aparține unei clase.

Așadar, am creat o clasă de pisici gata făcută. Iată codul lui:

# Cat class class Cat: # Acțiuni care trebuie efectuate la crearea unui obiect „Cat” def __init__(self, wool_culo, eyes_culo, name): self.wool_color = wool_color self.eyes_color = eyes_color self.name = name # Purr def purr( self): print("Purrr!") # Hiss def hiss(self): print("Shhh!") # Scratch def scrabble(self): print("Scratch-scratch!") # Toate împreună def all_in_one(self) : self.purr() self.hiss() self.scrabble()

Obiecte

Am creat o diagramă a pisicii. Acum să creăm un obiect de pisică reală folosind această schemă:

Pisica_mea = Pisica ("negru", "verde", "Zosya")

În rândul de mai sus, creăm o variabilă my_cat și apoi îi atribuim un obiect din clasa Cat. Toate acestea arată ca un apel la o funcție Cat(...) . De fapt, acest lucru este adevărat. Cu această intrare numim metoda __init__() a clasei Cat. Funcția __init__() din clasa noastră ia 4 argumente: obiectul self class, care nu trebuie specificat, precum și încă 3 argumente diferite, care devin apoi atribute ale pisicii noastre.

Deci, folosind linia de mai sus, am creat un obiect de pisică reală. Pisica noastră are următoarele atribute: blană neagră, ochi verzi și porecla Zosya. Să imprimăm aceste atribute pe consolă:

Imprimare (culoarea_pisica_mea.lână) imprimare (culoarea_pisica_mea.ochii) imprimare (numele_pisica_mea)

Adică putem accesa atributele unui obiect scriind numele obiectului, punând un punct și indicând numele atributului dorit.

Atributele pisicii pot fi modificate. De exemplu, să schimbăm numele pisicii noastre:

My_cat.name = „Nyusha”

Acum, dacă afișați din nou numele pisicii în consolă, veți vedea Nyusha în loc de Zosia.

Permiteți-mi să vă reamintesc că clasa pisicii noastre îi permite să efectueze anumite acțiuni. Dacă ne mângâim pe Zosya/Nyusha, ea va începe să toarcă:

My_cat.purr()

Executarea acestei comenzi va imprima textul „Purrr!” pe consolă. După cum puteți vedea, accesarea metodelor unui obiect este la fel de ușor ca accesarea atributelor acestuia.

Module

Orice fișier cu extensia .py este un modul. Chiar și cel în care lucrezi la acest articol. De ce sunt necesare? Pentru comoditate. Mulți oameni creează fișiere cu funcții și clase utile. Alți programatori conectează aceste module terțe și pot folosi toate funcțiile și clasele definite în ele, simplificându-le astfel munca.

De exemplu, nu trebuie să pierdeți timpul scriind propriile funcții pentru a lucra cu matrice. Este suficient să conectați modulul numpy și să folosiți funcțiile și clasele acestuia.

În prezent, alți programatori Python au scris peste 110.000 de module diferite. Modulul numpy menționat mai sus vă permite să lucrați rapid și convenabil cu matrici și matrice multidimensionale. Modulul de matematică oferă multe metode de lucru cu numere: sinusuri, cosinus, conversia grade în radiani etc., etc....

Instalarea modulului

Python este instalat împreună cu un set standard de module. Acest set include un număr foarte mare de module care vă permit să lucrați cu matematică, solicitări web, să citiți și să scrieți fișiere și să efectuați alte acțiuni necesare.

Dacă doriți să utilizați un modul care nu este inclus în setul standard, va trebui să îl instalați. Pentru a instala modulul, deschideți linia de comandă (Win + R, apoi introduceți „cmd” în câmpul care apare) și introduceți comanda în ea:

Pip install [nume_modul]

Procesul de instalare a modulului va începe. Când se finalizează, puteți utiliza în siguranță modulul instalat în programul dvs.

Conectarea și utilizarea modulului

Modulul terță parte este foarte ușor de conectat. Trebuie doar să scrieți o linie scurtă de cod:

Importă [nume_modul]

De exemplu, pentru a importa un modul care vă permite să lucrați cu funcții matematice, trebuie să scrieți următoarele:

Importă matematică

Cum se accesează o funcție de modul? Trebuie să scrieți numele modulului, apoi să puneți un punct și să scrieți numele funcției/clasei. De exemplu, factorialul 10 se găsește astfel:

Math.factorial(10)

Adică, am apelat la funcția factorial(a), care este definită în interiorul modulului de matematică. Acest lucru este convenabil, deoarece nu trebuie să pierdem timpul și să creăm manual o funcție care calculează factorialul unui număr. Puteți conecta modulul și puteți efectua imediat acțiunea necesară.

De data aceasta am decis să studiez rețelele neuronale. Am reușit să dobândesc abilități de bază în această chestiune în vara și toamna lui 2015. Prin abilități de bază, vreau să spun că pot crea o rețea neuronală simplă de la zero. Puteți găsi exemple în depozitele mele GitHub. În acest articol, voi oferi câteva explicații și voi împărtăși resurse pe care le puteți găsi utile în studiul dumneavoastră.

Pasul 1. Neuroni și metoda feedforward

Deci, ce este o „rețea neuronală”? Să așteptăm cu asta și să ne ocupăm mai întâi de un neuron.

Un neuron este ca o funcție: ia mai multe valori ca intrare și returnează una.

Cercul de mai jos reprezintă un neuron artificial. Primește 5 și returnează 1. Intrarea este suma celor trei sinapse conectate la neuron (trei săgeți în stânga).

În partea stângă a imaginii vedem 2 valori de intrare (în verde) și un offset (în maro).

Datele de intrare pot fi reprezentări numerice a două proprietăți diferite. De exemplu, la crearea unui filtru de spam, acestea ar putea însemna prezența a mai mult de un cuvânt scris cu MAJUSCULE și prezența cuvântului „Viagra”.

Valorile de intrare sunt înmulțite cu așa-numitele „greutăți”, 7 și 3 (evidențiate cu albastru).

Acum adăugăm valorile rezultate cu offset și obținem un număr, în cazul nostru 5 (evidențiat cu roșu). Aceasta este intrarea neuronului nostru artificial.

Apoi neuronul efectuează un calcul și produce o valoare de ieșire. Avem 1 pentru că valoarea rotunjită a sigmoidului la punctul 5 este 1 (vom vorbi mai detaliat despre această funcție mai târziu).

Dacă acesta ar fi un filtru de spam, faptul că ieșirea 1 ar însemna că textul a fost marcat ca spam de către neuron.

Ilustrație a unei rețele neuronale de pe Wikipedia.

Dacă combinați acești neuroni, obțineți o rețea neuronală care se propagă direct - procesul merge de la intrare la ieșire, prin neuroni conectați prin sinapse, ca în imaginea din stânga.

Pasul 2. Sigmoid

După ce ați urmărit lecțiile Welch Labs, este o idee bună să consultați Săptămâna 4 din cursul de învățare automată al Coursera despre rețelele neuronale, pentru a vă ajuta să înțelegeți cum funcționează acestea. Cursul intră foarte adânc în matematică și se bazează pe Octave, în timp ce eu prefer Python. Din acest motiv, am sărit peste exerciții și am obținut toate cunoștințele necesare din videoclipuri.

Un sigmoid pur și simplu mapează valoarea ta (pe axa orizontală) într-un interval de la 0 la 1.

Prima mea prioritate a fost să studiez sigmoidul, așa cum a figurat în multe aspecte ale rețelelor neuronale. Știam deja ceva despre asta din a treia săptămână a cursului mai sus menționat, așa că am urmărit videoclipul de acolo.

Dar nu vei ajunge departe doar cu videoclipurile. Pentru o înțelegere completă, am decis să-l codez eu. Așa că am început să scriu o implementare a algoritmului de regresie logistică (care folosește sigmoid).

A durat o zi întreagă, iar rezultatul a fost cu greu satisfăcător. Dar nu contează, pentru că mi-am dat seama cum funcționează totul. Codul poate fi văzut.

Nu trebuie să faceți acest lucru singur, deoarece necesită cunoștințe speciale - principalul lucru este că înțelegeți cum funcționează sigmoidul.

Pasul 3. Metoda de backpropagation

Înțelegerea modului în care funcționează o rețea neuronală de la intrare la ieșire nu este atât de dificilă. Este mult mai dificil de înțeles cum o rețea neuronală învață din seturile de date. Principiul pe care l-am folosit se numește

James Loy, Georgia Tech. Un ghid pentru începători pentru crearea propriei rețele neuronale în Python.

Motivație: Pe baza experienței personale în studiul învățării profunde, am decis să creez o rețea neuronală de la zero, fără o bibliotecă de antrenament complexă, cum ar fi, de exemplu, . Cred că pentru un Data Scientist începător este important să înțeleagă structura internă a unei rețele neuronale.

Acest articol conține ceea ce am învățat și sper să vă fie de folos și vouă! Alte articole utile pe această temă:

Ce este o rețea neuronală?

Cele mai multe articole despre rețelele neuronale fac paralele cu creierul atunci când le descriu. Este mai ușor pentru mine să descriu rețelele neuronale ca o funcție matematică care mapează o intrare dată la o ieșire dorită, fără a intra în prea multe detalii.

Rețelele neuronale constau din următoarele componente:

  • strat de intrare, x
  • cantitate arbitrară straturi ascunse
  • strat de ieșire, ŷ
  • trusa cântareŞi deplasariîntre fiecare strat W Şi b
  • alegere funcții de activare pentru fiecare strat ascuns σ ; in aceasta lucrare vom folosi functia de activare sigmoid

Diagrama de mai jos arată arhitectura unei rețele neuronale cu două straturi (rețineți că stratul de intrare este de obicei exclus atunci când se numără numărul de straturi dintr-o rețea neuronală).

Crearea unei clase de rețea neuronală în Python este simplă:

Antrenamentul rețelei neuronale

Ieșire ŷ rețea neuronală simplă cu două straturi:

În ecuația de mai sus, ponderile W și părtinirea b sunt singurele variabile care afectează ieșirea ŷ.

Desigur, valorile corecte pentru ponderi și părtiniri determină acuratețea predicțiilor. Procesul de reglare fină a greutăților și a distorsiunilor din datele de intrare este cunoscut sub numele de antrenament al rețelei neuronale.

Fiecare iterație a procesului de învățare constă din următorii pași

  • calculând ieșirea prezisă ŷ, numită propagare directă
  • actualizarea ponderilor și a prejudecăților, numită backpropagation

Graficul secvenţial de mai jos ilustrează procesul:

Distributie directa

După cum am văzut în graficul de mai sus, propagarea directă este doar un calcul simplu, iar pentru o rețea neuronală de bază cu 2 straturi, rezultatul rețelei neuronale este dată de:

Să adăugăm o funcție de propagare înainte la codul nostru Python pentru a face acest lucru. Rețineți că, pentru simplitate, am presupus că decalajele sunt 0.

Cu toate acestea, avem nevoie de o modalitate de a evalua „bonitatea” prognozelor noastre, adică cât de departe sunt previziunile noastre). Funcția de pierdere doar ne permite să facem asta.

Funcția de pierdere

Există multe funcții de pierdere disponibile, iar natura problemei noastre ar trebui să ne dicteze alegerea funcției de pierdere. În această lucrare vom folosi suma erorilor pătrate ca functie de pierdere.

Suma erorilor pătrate este media diferenței dintre fiecare valoare prezisă și cea reală.

Scopul învățării este de a găsi un set de ponderi și părtiniri care să minimizeze funcția de pierdere.

Propagarea inversă

Acum că am măsurat eroarea în prognoza noastră (pierderea), trebuie să găsim o cale propagarea erorii înapoiși actualizați ponderile și părtinirile noastre.

Pentru a cunoaște cantitatea adecvată pentru a ajusta ponderile și prejudecățile, trebuie să cunoaștem derivata funcției de pierdere în raport cu ponderile și părtinirile.

Să reamintim din analiză că Derivata unei functii este panta functiei.

Dacă avem o derivată, atunci putem pur și simplu să actualizăm ponderile și părtinirile prin creșterea/scăderea lor (vezi diagrama de mai sus). Se numește coborâre în gradient.

Cu toate acestea, nu putem calcula direct derivata funcției de pierdere în raport cu ponderi și părtiniri, deoarece ecuația funcției de pierdere nu conține ponderi și părtiniri. Deci avem nevoie de o regulă de lanț care să ne ajute la calcul.

Pf! Acest lucru a fost greoi, dar ne-a permis să obținem ceea ce aveam nevoie — derivata (panta) a funcției de pierdere în raport cu ponderile. Acum putem ajusta greutățile în consecință.

Să adăugăm funcția de backpropagation la codul nostru Python:

Verificarea funcționării rețelei neuronale

Acum că avem codul nostru complet Python pentru a efectua propagarea înainte și înapoi, să ne plimbăm prin rețeaua neuronală cu un exemplu și să vedem cum funcționează.


Setul ideal de cântare

Rețeaua noastră neuronală trebuie să învețe setul ideal de greutăți pentru a reprezenta această funcție.

Să antrenăm rețeaua neuronală pentru 1500 de iterații și să vedem ce se întâmplă. Privind graficul pierderilor de iterație de mai jos, putem vedea clar că pierderea scade monoton la un minim. Acest lucru este în concordanță cu algoritmul de coborâre a gradientului despre care am discutat mai devreme.

Să ne uităm la predicția finală (ieșirea) din rețeaua neuronală după 1500 de iterații.

Noi am făcut-o! Algoritmul nostru de propagare înainte și înapoi a arătat că rețeaua neuronală funcționează cu succes, iar predicțiile converg către valorile adevărate.

Rețineți că există o mică diferență între predicții și valorile reale. Acest lucru este de dorit deoarece previne supraadaptarea și permite rețelei neuronale să se generalizeze mai bine la datele nevăzute.

Gânduri finale

Am învățat multe în procesul de scriere a propriei mele rețele neuronale de la zero. În timp ce bibliotecile de învățare profundă precum TensorFlow și Keras vă permit să construiți rețele profunde fără a înțelege pe deplin funcționarea interioară a unei rețele neuronale, consider că este util pentru aspiranții cercetători ai datelor să obțină o înțelegere mai profundă a acestora.

Am investit mult din timpul meu personal în această lucrare și sper că o veți găsi de folos!