Një artikull mbi mënyrën se si arrihet pandryshueshmëria e përkthimit nga NN-të konvolucionale dhe rëndësia e tij.

HYRJE:
— — — — — — — — — — — —
Ka shumë përparësi të përdorimit të rrjeteve nervore konvolucionale për zgjidhjen e detyrave që lidhen me vizionin kompjuterik.
Ato a janë arkitektura e paracaktuar e rrjetit nervor kur bëhet fjalë për klasifikimet e imazheve, zbulimin e objekteve, transferimin e stilit të imazhit etj. Pra, pyetja është pse ato janë kaq të njohura në komunitetin e mësimit të makinerive?
mirë, ka shumë arsye, këtu do të listoj disa:

1. Ndarja e peshës : Ndryshe nga rrjeti nervor i rrjedhshëm i cili karakterizohet nga shtresa të dendura, NN konvolucionist përbëhet nga rregullimi sekuencial i shtresave konvolucionale. Një shtresë e vetme konvolucionale përbëhet nga filtra të shumtë.

Puna është se këta filtra janë zakonisht të përmasave të vogla (veçanërisht kur kemi të bëjmë me imazhe të thjeshta), si një rrjet peshash me madhësi (5*5).
Pra, nëse keni 40 filtra në shtresën e parë konvolucionale, numri total i peshave që duhet të stërvitni është 5*5*40=1000. Krahasoni këtë me një shtresë standarde të dendur, që ka 100 neurone, të aplikuar në një imazh mnist të madhësisë (28,28).
Numri total i parametrave këtu është 28*28*100=78400!!. Ky është një ndryshim gjigant.
Të kesh më pak pesha lejon që NN Convolutional të konvergohet më shpejt në një minimum, ndërkohë që zvogëlon probabilitetin e përshtatjes së tepërt dhe përdorimit më pak memorie dhe duke marrë më pak kohë trajnimi.
(Nëse keni vështirësi të kuptoni argumentin e mësipërm, ( http://cs231n.github.io/convolutional-networks/#overview) ka një shpjegim më të mirë, më të thellë)

2. Mësimi me transferim: Të mësuarit me transferim është një teknikë që i jep NN tuaj një fillim në trajnim.
Është vënë re se në përgjithësi shtresat e mëparshme të NN zakonisht mësojnë veçori të thjeshta dhe shtresat e mëvonshme punojnë në veçoritë e shtresave të mëparshme për të gjeneruar abstraksione komplekse.
Kjo është veçanërisht e vërtetë për NN-të konvolucionale. Studiuesit kanë zbuluar se në shumicën e rasteve shtresat e hershme të cnn-ve mësojnë veçori të thjeshta dhe gjenerike si zbulimi i skajeve, filtrat e gabonit, etj, të cilat mbeten pak a shumë të njëjta, pavarësisht nga detyra ose grupi i të dhënave të imazhit të përdorur.
Pra, nën transferim duke mësuar, ne kopjojmë peshat e shtresave të hershme në mënyrë që NN-të Convolutional të mos kenë nevojë të fillojnë nga e para çdo herë. Pas kësaj ne sintonizojmë rrjetin me grupin e të dhënave të detyrave. Duke përdorur mësimin e transferimit , ne zvogëlojmë kohën e trajnimit dhe i bëjmë shtresat e hershme më të fuqishme pasi ato kanë mësuar në thelb nga grupe të dhënash të shumta dhe jo nga një, dhe më shumë të dhëna do të thotë më pak përshtatje për trajnimin e të dhënave.
Është interesante, numri i shtresave që ju mund të kopjoni nga një NN konvolucional ekzistues në një të ri është drejtpërdrejt proporcionale me ngjashmërinë midis grupit të të dhënave të përdorur për të trajnuar rrjetin fillestar dhe grupin e të dhënave të detyrës së re. Ka një studim kërkimor tërheqës dhe të lehtë për t'u lexuar (https://papers.nips.cc/paper/5347-how-transferable-are-features-in-deep-neural-networks.pdf) , nëse dikush është e interesuar.

3. Pandryshueshmëria e përkthimit: Pandryshueshmëria e përkthimit, në thelb, është aftësia për të injoruar zhvendosjet postionale, ose përkthimet, të objektivit në imazh. Një mace është akoma një mace, pavarësisht nëse shfaqet në gjysmën e sipërme apo në gjysmën e poshtme të imazhit.
NN-të konvolucioniste kanë pandryshueshmëri të integruar të përkthimit dhe për këtë arsye janë më të përshtatshme për trajtimin e grupeve të të dhënave të imazheve sesa homologët e tyre të zakonshëm.

“Por Si…”, ju pyesni?


Le të thellohemi më thellë në thellësitë e NN-ve konvolucionale për të zbuluar.

Arritja e pandryshueshmërisë së përkthimit në NN-të konvolucioniste:

Së pari, më lejoni të jap një përkufizim më zyrtar të pandryshueshmërisë së përkthimit:

Assume a transformation T, which shifts the position of the target in the input image x by some amount ,
 
then a NN having translation invariance would satisfy the equation
 NN(T(x))=NN(x)

që do të thotë, nëse NN ka pandryshueshmëri të përkthimit, prodhimi i NN nuk do të ndryshojë kur të aplikohet transformimi T.

Kjo pandryshueshmëri e përkthimit në NN konvolucioniste arrihet nga një kombinim i shtresave konvolucionale dhe shtresave maksimale të bashkimit.
Së pari, shtresa konvolucionale e redukton imazhin në një grup karakteristikash dhe pozicionet e tyre përkatëse. Pastaj shtresa maksimale e bashkimit merr daljen nga shtresa konvolucionale dhe redukton rezolucionin dhe kompleksitetin e saj.
E bën këtë duke nxjerrë vetëm vlerën maksimale nga një rrjet. Pra, informacioni rreth pozicionit të saktë të vlerës maksimale në rrjet hidhete.
Kjo është ajo që i mbush CNN-të me pandryshueshmërinë e përkthimit.

Në figurën e mëposhtme, filtri CNN është trajnuar për të zbuluar shkronjën 'C' në imazhin e hyrjes.
Pra, le të futim një imazh të shkronjës 'C'.

Tani le ta zhvendosim shkronjën 'C' poshtë në imazh me gjatësi 1 pixel.

Duke krahasuar daljen në 2 rastet, mund të shihni se shtresa maksimale e bashkimit jep të njëjtin rezultat. Informacioni i pozicionit lokal humbet. Kjo është pandryshueshmëria e përkthimit në veprim. Kjo do të thotë që nëse trajnojmë një NN konvolutional mbi imazhet e një objektivi, cnn do të funksionojë automatikisht edhe për imazhet e zhvendosura të atij objektivi.

Por nëse mendoni për këtë … nëse do ta kishim zhvendosur shkronjën 'C' më ashpër, rezultati do të kishte qenë i ndryshëm.
Për ta bërë më efektive pandryshueshmërinë e përkthimit, ne mund të përdorim shtresa më konvolucionale + max bashkimi, si të njëpasnjëshme Shtresat maksimale të bashkimit përpilojnë efektin e pandryshueshmërisë së përkthimit. (përpiquni të mendoni pse është kështu).

Tani e gjithë kjo ka qenë vetëm teori. Për ta parë atë në veprim, ne do të krahasojmë pandryshueshmërinë e përkthimit të rrjetit nervor konvolucionist dhe NN standard duke trajnuar të dyja në një detyrë të klasifikimit të imazhit.

Eksperimentimi me pandryshueshmërinë e përkthimit:

Ne do të zgjedhim detyrën klasike të klasifikimit të imazheve MNIST për të krahasuar performancën e 3 arkitekturave NN.
1. NN standarde
2. NN konvolucionale me 1 shtresë (konvolucionale + bashkim maksimal)
3. Konvolucionist NN me 2 shtresa (konvolucionale + bashkim maksimal).

Së pari, le të krijojmë grupet e të dhënave të kërkuara:

(x_train, y_train), (x_test, y_test) = mnist.load_data() 
x_testShift = shiftImageDataset(4,3,x_test) 
x_testShiftMin = shiftImageDataset(1,1,x_test)

ne krijojmë 2 grupe të dhënash të reja nga grupi bazë i të dhënave testuese që ka zhvendosur imazhet e shifrave të shkruara me dorë.

x_testShift është grupi i të dhënave x_test me çdo imazh të zhvendosur rastësisht nga një vlerë në [4,-4] përgjatë boshtit x dhe me [3,-3] përgjatë boshtit y.

x_testShiftMin është grupi i të dhënave x_test me çdo imazh të zhvendosur rastësisht nga një vlerë në [1,-1] përgjatë boshtit x dhe nga [1,-1] përgjatë boshtit y. (përkthim më pak i rëndë i imazhit).

ne do të përdorim këto grupe të dhënash me 2 ndërrime për të matur se si funksionojnë rrjetet kundrejt shtrembërimit të vogël të përkthimit (x_testShiftMin) në të dhëna kundrejt shtrembërimit të madh të përkthimit (x_testShift).

Funksioni i mëposhtëm u përdor për të krijuar grupet e të dhënave të zhvendosura duke zhvendosur imazhet:

def shiftImageDataset(maxXShift,maxYShift,x_dataset):
    x_Shift=[]
    for i in range(y_test.shape[0]):
        randShiftx=np.random.rand()*maxXShift  
        randShifty=np.random.rand()*maxYShift 
        ra=np.random.rand(2)
        if ra[0]>0.5:
            randShiftx=randShiftx*-1 
        if ra[1]>0.5:
            randShifty=randShifty*-1    
        M = np.float32([[1, 0, randShiftx], [0, 1, randShifty]])
        (rows, cols) = x_dataset[i].shape[:2]
        shiftedImage = cv2.warpAffine(x_dataset[i], M, (cols, rows))
        x_Shift.append(shiftedImage)
    x_Shift=np.array(x_Shift)
    x_Shift=x_Shift.reshape(10000,28,28,1)
    return x_Shift

Në thelb, funksioni i zhvendos imazhet në grupin e të dhënave me një vlerë të rastësishme në [maxXshift,-maxXshift] dhe [maxYshift,-maxYshift] përgjatë boshtit x dhe y respektivisht.

Tani, le të krijojmë 3 modelet duke përdorur Keras:

input_shape = (28, 28, 1)
# Standard NN with 2 hidden layers
stdmodel = Sequential()
stdmodel.add(Dense(100,activation='relu' ,input_shape=input_shape))
stdmodel.add(Dropout(0.5))
stdmodel.add(Dense(100,activation='relu',input_shape=input_shape))
stdmodel.add(Dropout(0.25))
stdmodel.add(Flatten())
stdmodel.add(Dense(10, activation = "softmax"))

#Convolutional NN with 1 (conv + max pool)layer
modelcnn1 = Sequential()
modelcnn1.add(Conv2D(filters = 20,kernel_size = (5,5),padding = 'valid',strides=1,activation ='relu', input_shape = input_shape))
modelcnn1.add(MaxPooling2D(pool_size=(2,2)))
modelcnn1.add(Flatten())
modelcnn1.add(Dense(100,activation='relu'))
modelcnn1.add(Dense(10, activation = "softmax"))
#Convolutional NN with 2(conv + max pool)layer
modelcnn2 = Sequential()
modelcnn2.add(Conv2D(filters = 20,kernel_size = (5,5),padding = 'valid',strides=1,activation ='relu', input_shape = input_shape))
modelcnn2.add(MaxPooling2D(pool_size=(2,2)))
modelcnn2.add(Conv2D(filters = 40, kernel_size = (5,5),strides=1,padding = 'valid',activation ='relu'))
modelcnn2.add(MaxPooling2D(pool_size=(2,2)))
modelcnn2.add(Flatten())
modelcnn2.add(Dense(100,activation='relu'))
modelcnn2.add(Dense(10, activation = "softmax"))

Tani është koha për të trajnuar 3 modelet në grupin e të dhënave të trenave MNIST dhe për të parë se çfarë saktësie ka secili në grupet tona të të dhënave të imazheve të zhvendosura.

batch_size = 128
lrn_rate=0.0001
epochs=100  #use early stopping if models start overfitting
stdmodel.compile(optimizer=Adam(lr=lrn_rate),loss=tf.keras.losses.categorical_crossentropy,metrics=['accuracy'])
stdmodel.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=epochs,
          verbose=1,
          validation_data=(x_test, y_test))
score = stdmodel.evaluate(x_test, y_test, verbose=0)
scoreShiftMin = stdmodel.evaluate(x_testShiftMin, y_test, verbose=0)
scoreShift=stdmodel.evaluate(x_testShift, y_test, verbose=0)

Ngjashëm me lart, ne vlerësojmë 2 modelet cnn në 3 grupet e të dhënave (x_test, x_testShiftMin, x_testShift).

Më poshtë është saktësia e modeleve kundrejt 3 grupeve të të dhënave testuese:

Ashtu siç parashikoi teoria jonë.

NN standarde funksionon dobët kur krahasohet me NN-të konvolutional në imazhet e zhvendosura. Performanca e tij bie pasi shtrembërimi rritet nga testShiftMin në testShift. Kjo ndodh sepse NN standard i mungon pandryshueshmëria e integruar e përkthimit.

'modelcnn1' i cili kishte 1 shtresë (bashkim konvolucional + max) është më i qëndrueshëm në trajtimin e imazheve të zhvendosura. Por prapëseprapë ajo nuk ka të bëjë me grupin testues testShift, i cili kishte ndërrime më të mëdha në imazhe. Kjo është për shkak se efekti i një shtrese të vetme max bashkimi nuk është mjaftueshëm i fuqishëm për t'u marrë me zhvendosje të mëdha të pozicionit të objektivit në imazh.

'modelcnn2' i cili kishte 2 shtresa (konvolucionare + max pooling) është më e mira e grupit. Ai performon mjaft mirë kundër zhvendosjeve më të mëdha të imazhit në grupin e të dhënave testShift. Kjo është për shkak të efektit komponues të përdorimit të 2 shtresave maksimale të bashkimit.

Disavantazhi i Max Pooling:

Çështja kryesore me bashkimin maksimal është se rrjeti nuk arrin të mësojë lidhjen hapësinore midis veçorive të ndryshme, dhe kështu do të japë një pozitiv fals nëse të gjitha tiparet janë të pranishme në pozicionin e gabuar në lidhje me njëra-tjetrën.
Imazhi i mëposhtëm ilustron pika.

Kjo ndodh sepse shtresa maksimale e bashkimit aplikohet në daljet e çdo filtri nga shtresa e mëparshme e konvolucionit veçmas. Pra, shtresa tjetër mund të japë rezultate vetëm në bazë të pranisë së veçorive.
Ndërsa shkojmë në shtresat pasuese, gjithnjë e më shumë informacion hapësinor humbet, pasi shtresa maksimale e bashkimit kompon efektin e pandryshueshmërisë së përkthimit. Në fund zbulon një fytyrë edhe kur syri është i pranishëm në vendin e gojës. Moment mjaft i sikletshëm për një AI.

Kjo është arsyeja pse disa njerëz nuk i duan shtresat maksimale të bashkimit. Bashkimi është në thelb një proces me humbje. Por ne nuk mund ta heqim thjesht sepse siguron pandryshueshmërinë e përkthimit dhe reduktimin e dimensionalitetit (zvogëlon madhësinë hapësinore të paraqitjes në mënyrë eksponenciale për të zvogëluar sasinë e parametrave dhe llogaritjeve në rrjet, dhe gjithashtu përmirëson përshtatjen e tepërt).

Pra, a ka mënyra të tjera për ta bërë të pandryshueshëm përkthimin tuaj konvolucionar NN përveç përdorimit të shtresave maksimale të bashkimit?

Rritja e të dhënave:
Shtimi i të dhënave është një formë rregullimi që përdoret për ta bërë Modelin më të fortë ndaj shtrembërimeve në të dhëna . Ne e bëjmë këtë duke krijuar shtrembërimin në të dhënat tona të trajnimit dhe duke trajnuar modelin në këto të dhëna "të shtuara".
Në rastin tonë, ne presim shtrembërim të rëndë të përkthimit në të dhënat e testimit, kështu që ne do ta trajnojmë modelin tonë në imazhe që kanë shtrembërime të ngjashme.

Ajo që do të thotë këtu është se ne do të trajnojmë rrjetin tonë për imazhe të mëdha të zhvendosura për ta bërë atë më të përkthimit të pandryshueshëm në ndërrime të mëdha. Kjo do të na lejojë të kemi performancë më të mirë në të dhënat x_testShift duke ruajtur të njëjtin nr. të shtresave.
ne do të përdorim keras ImageDataGenerator , i cili është një gjenerator python që nxjerr imazhe të shtrembëruara në të cilat rrjeti mund të trajnohet.

datagen = ImageDataGenerator(
        featurewise_center=False,  # set input mean to 0 in data
        samplewise_center=False,  # set each sample mean to 0
        featurewise_std_normalization=False,  
        samplewise_std_normalization=False, 
        zca_whitening=False,  # apply ZCA whitening
        rotation_range=0,  # randomly rotate images by degree
        zoom_range = 0, # Randomly zoom image 
        width_shift_range=0.1,  # randomly shift images horizontally 
        height_shift_range=0.1,  # randomly shift images vertically 
        horizontal_flip=False,  # randomly flip images
        vertical_flip=False)  # randomly flip images 

Edhe pse ImageDataGenerator ofron shtrembërime të ndryshme, ne do të përdorim vetëm 'width_shift_range' dhe ' height_shift_range'. ne përdorim vlerën "0.1" si fraksionin maksimal të gjerësisë (ose lartësisë) totale me të cilën imazhi do të zhvendoset.

Koha për të trajnuar CNN tonë duke përdorur ImageDataGenerator.

datagen.fit(x_train)
batch_size = 128
lrn_rate=0.0001
epochs=100
modelcnn2.compile(optimizer=Adam(lr=lrn_rate),loss=tf.keras.losses.categorical_crossentropy,metrics=['accuracy'])
modelcnn2.fit_generator(datagen.flow(x_train,y_train, batch_size=batch_size),
epochs = epochs,
validation_data = (x_test,y_test),
 verbose = 1, steps_per_epoch=x_train.shape[0] // batch_size)
score=modelcnn2.evaluate(x_test, y_test, verbose=0)
scoreShiftMin = modelcnn2.evaluate(x_testShiftMin, y_test,verbose=0)
scoreShift=modelcnn2.evaluate(x_testShift, y_test, verbose=0)

Konfigurimi ynë i ri na jep një saktësi prej 0.9933,0.9918,.9839 respektivisht në x_test, x_testShiftMin dhe x_testShift, që është shumë më e mirë se ajo që kemi marrë më parë në modelcnn2. Është e qartë se trajnimi i rrjetit tonë mbi të dhënat e shtuara e ka bërë atë më të pandryshueshëm përkthimin.

Përveç shtimit të të dhënave, ka alternativa të tjera për përdorimin e bashkimit maksimal.
Autorët e Përpjekja për Thjeshtësi: Rrjeti Gjithë Convolutional (https://arxiv.org/abs/1412.6806) rekomandojnë zëvendësimin e shtresave maksimale të bashkimit me shtresat e konvertimit që kanë filtra me madhësi 3*3 dhe hap=2.

Të tjerë kanë sugjeruar arkitektura më të ndërlikuara për të kapërcyer disavantazhet e bashkimit maksimal, si grumbullimi me ruajtjen e detajeve në rrjetet e thella (https://arxiv.org/pdf/1804.04076.pdf) ose rrjetet me kapsula (https://arxiv. org/abs/1805.04424).

Por këto janë histori për një ditë tjetër.

Përfundim:
Në këtë postim u përpoqa të përvijoj si avantazhet ashtu edhe disavantazhet e pandryshueshmërisë së përkthimit nga bashkimi maksimal. Mësuam se si mund të fitohet kjo veçori duke përdorur shtresat e njëpasnjëshme të bashkimit maksimal ose me shtimin e të dhënave.
Shpresojmë që ky postim t'ju ndihmojë të kuptoni më mirë NN-të konvolucionale në përgjithësi.

Burimet:

CS231n Rrjetet neurale konvolucionare për njohjen vizuale: (http://cs231n.github.io/convolutional-networks/#overview)

Sa të transferueshme janë veçoritë në rrjetet nervore të thella?: https://papers.nips.cc/paper/5347-how-transferable-are-features-in-deep-neural-networks.pdf

Rrjeti Gjithë Konvolutional (https://arxiv.org/abs/1412.6806)