Një përpjekje për të kuptuar më thellë Rrjetet Neurale.

Kodi i plotë i këtij algoritmi është në Github: MNIST-from-Scratch

Që kur fillova të zbatoja algoritme nga Tensorflow dhe Sklearn për shkencën e të dhënave, doja të kuptoja vërtet se çfarë po ndodhte nën kapuç, dhe jo vetëm të zbatoja algoritmet që shkroi dikush tjetër. Me këtë projekt, më në fund mund të kem një kuptim më të thellë të përhapjes së prapme, dhe jo vetëm të fus vlera në një kuti misterioze-magjike Keras dhe të marr rezultate.

Doja të bëja një algoritëm Neural Net që është fleksibël në një mënyrë që të mund të zgjedh sa shtresa dhe sa neurone në secilën prej atyre shtresave ka, gjithashtu doja të jem në gjendje të zgjidhja se cili funksion aktivizimi zbatohet midis çdo shtrese. (sigmoid ose Relu). Duke e quajtur klasën kështu:

model = MNISTalgorithm([784, "relu", 200, "sigmoid", 80, "softmax", 10])

Pra, para së gjithash, le të importojmë paketat që na duhen:

Importet:

import numpy as np
import matplotlib.pyplot as plt
import time
import pickle #optional, for saving the model
from sklearn.datasets import fetch_openml
from sklearn.model_selection import train_test_split

Ne do të përdorim Numpy për të bërë llogaritjet e matricës, është shumë më e lehtë dhe më e shpejtë përdorimi i vargjeve NumPy sesa përdorimi i listave të python.

Përgatitja dhe vizualizimi:

Rrjeti nervor do të funksionojë më mirë kur vlerat X janë midis 0 dhe 1 në këtë rast, dhe ne duhet t'i kthejmë vlerat Y (numrat e plotë midis 0 dhe 9) në kategorike, sepse në fund duam që probabilitetet që çdo imazh të jetë secila. numri.

Tani do të ishte e dobishme të vizualizonim të gjitha format e secilës matricë me të cilën kemi të bëjmë:

SHAPES: 
- X original: 70000 x 785 
- Y original: 70000 x 10 
- X Train: 59500 x 785 
- Y Train: 59500 x 10 
- X Test: 10500 x 785 
- Y Test: 10500 x 10

Duke eksploruar grupin e të dhënave, mund të shohim se ka 70000 imazhe me 784 piksel (plus kolonën e 1-së), që do të thotë se çdo imazh është 28 x 28 piksel. I ndava 70000 shembujt në x_train(59500) dhe x_test(10500) që do të përdoren pas trajnimit për të matur aftësinë e modelit për të përgjithësuar.

Rrjeti nervor:

Tani, pjesa e komplikuar. Mendova se do ta bëja rrjetin nervor një klasë më të organizuar dhe kjo klasë do të ketë funksionet e mëposhtme të rëndësishme:

  1. __init__: Ju futni strukturën dhe hiperparametrat.
  2. Inicializimi: Peshat dhe paragjykimet inicializohen në mënyrë të rastësishme.
  3. ‹Funksionet e aktivizimit›: Është një grup funksionesh aktivizimi dhe funksionet e tyre përkatëse të gradientit.
  4. Përpara: Bën përhapjen përpara pas strukturës së imputuar.
  5. CostFunction: Llogarit funksionin e kostos në mënyrë që të mund të gjurmojmë uljen përgjatë epokave.
  6. Gradientët: Llogarit gradientin e çdo funksioni të peshës dhe paragjykimit w.r.t, ai nxjerr një fjalor që përmban një matricë gradientësh për çdo matricë Theta (shpjegohet më vonë).

7. Saktësia: Llogaritet Saktësia e modelit.

8. Train: Ai organizon rendin e të gjitha proceseve, nxjerr historinë e funksionit të kostos në epoka të ndryshme dhe Thetën e trajnuar përfundimtare, ju futni x-të dhe y-të: model.train(x_train, y_train, x_test, y_test)

Me listën tonë të funksioneve gati, le ta shkruajmë në kod:

__fillimi__()

Këtu do të fusim parametrat e përdorur në trajnim dhe strukturën e rrjetit nervor, brenda këtij funksioni do të vendosim vlerat e imputuara në "vetë", kështu që mund të përdoret më vonë në funksione të tjera.

inicializimi ()

Ne po inicializojmë në mënyrë të rastësishme Theta, e cila është një matricë me peshat dhe paragjykimet (rreshti i parë). Ka metoda të tjera për të inicializuar, por shpesh nuk bën shumë ndryshim, thjesht mbajeni afër 0.

Funksionet e aktivizimit

Këtu janë funksionet e aktivizimit që kam zbatuar. Mënyra se si bëra kodin bën të mundur zbatimin e lehtë të funksioneve të tjera të aktivizimit, mos ngurroni të shtoni më shumë nëse dëshironi.

Vërejtje: softmax mund të përdoret vetëm në shtresën e fundit.

përpara ()

Tani është kur fillon të ndërlikohet. Këtë funksion e bëra në një mënyrë që nxjerr një fjalor që përmban daljen e çdo hapi të procesit, për të kuptuar kodin tim mund t'ju duhet një kuptim i mirë i vargjeve f.

kostoFunksioni ()

Ky funksion përdoret gjatë trajnimit për të raportuar performancën e modelit, nuk ndërhyn në trajnim, kështu që zbatimi i tij është fakultativ. Ai tregon se sa gabim është modeli duke matur besimin e tij në parashikimet e sakta ose të gabuara. Unë jam duke përdorur funksionin e kostos logjistike:

gradientët ()

Këtu do të llogarisim derivatin e çdo peshe dhe paragjykim për funksionin e kostos, nuk do të shpjegoj saktësisht se si funksionon matematikisht, por do t'ju jap një kuptim të strukturës së tij. Derivati ​​i një shtrese ndikohet drejtpërdrejt nga shtresa tjetër, llogaritjet bëhen prapa nga shtresa e fundit në të parën.

Meqenëse fillimisht kam planifikuar ta bëj këtë projekt në një mënyrë që mund të pranojë çdo numër shtresash, ky funksion ishte një sfidë e madhe për mua dhe mund të duket konfuze, por gjithçka që bëra ishte të zbatoja funksionin matematikor të përhapjes së pasme, në një mënyrë që respekton strukturën e imputuar në fillim, nëse doni informacione të mëtejshme për zbatimin tim, thjesht lini një koment!

saktësi ()

Ky është një funksion i thjeshtë që llogarit saktësinë e modelit, qëllimi është të raportojë performancën e modelit si funksioni i kostos, por në përqindje. Ai funksionon duke bërë kalimin përpara, më pas llogarit mesataren e një grupi parashikimesh të drejta(1) dhe të gabuara (0).

tren ()

Tani më në fund është pjesa që ne bashkojmë gjithçka. Ky funksion do të jetë përgjegjës për të organizuar të gjitha proceset në model, mjaft të rëndësishme, dhe është këtu ku po ndodh mësimi në Machine Learning, ku Theta modifikohet në të vërtetë për t'iu përshtatur të dhënave. Do të futen 4 grupet e të dhënave dhe do të përdorë batch_size që është imputuar më herët, në mënyrë që të mund të zgjedhim midis zbritjes stokastike ose gradientit të plotë ose çdo gjëje në mes.

Dhe kjo eshte!

Këto ishin të gjitha funksionet që përdoren në model, tani le të thërrasim klasën dhe të trajnojmë një model për veten tonë:

Siç mund ta shihni, në çdo epokë saktësia përmirësohet, që do të thotë se modeli po mëson, ne mund ta shohim këtë më qartë pasi të përshkruajmë historinë e vlerave të kostos siç mund ta shihni në foto, ka një zbritje të qartë.

konkluzioni

Ky projekt ka qenë një mënyrë e shkëlqyeshme për mua për të kuptuar mirë mekanizmat e Rrjeteve Neurale, kam goditur shumë barriera dhe i kapërceva ato, shpresoj që ky artikull t'ju ketë ndihmuar edhe juve të kuptoni pak më shumë rreth kësaj teme. Kodi i plotë i këtij algoritmi është në Github: MNIST-from-Scratch

Faleminderit që lexuat!

-Lorenzo Varalo

Më shumë përmbajtje në plainenglish.io. Regjistrohu për "buletinin tonë javor falas". Merrni qasje ekskluzive në mundësitë e shkrimit dhe këshilla në Discord në komunitet.