Noen få ord om mønstergjenkjenning. Hva er tekstgjenkjenningsalgoritmen? Enkel sak, endimensjonal separasjon

  • Opplæringen

Jeg har lenge ønsket å skrive en generell artikkel som inneholder det helt grunnleggende om bildegjenkjenning, en guide til grunnleggende metoder, fortelle når du skal bruke dem, hvilke oppgaver de løser, hva som er mulig å gjøre om kvelden på kneet, og hva som er bedre å ikke tenke på uten å ha et team på 20 personer.

Jeg har skrevet noen artikler om optisk gjenkjenning i lang tid, så de skriver til meg et par ganger i måneden forskjellige folk med spørsmål om dette temaet. Noen ganger får du følelsen av at du bor sammen med dem forskjellige verdener... På den ene siden forstår du at en person mest sannsynlig er en profesjonell i et relatert emne, men i metoder optisk gjenkjenning vet veldig lite. Og det mest støtende er at han prøver å bruke en metode fra et nærliggende kunnskapsområde, som er logisk, men som ikke fungerer helt i bildegjenkjenning, men forstår ikke dette og blir veldig fornærmet hvis han begynner å fortelle noe fra det helt grunnleggende. Og med tanke på at det å fortelle fra det grunnleggende er mye tid, som ofte ikke er det, blir det enda tristere.

Denne artikkelen ble unnfanget slik at en person som aldri har beskjeftiget seg med bildegjenkjenningsmetoder, i løpet av 10-15 minutter kunne skape i hodet sitt et visst grunnbilde av verden tilsvarende temaet, og forstå i hvilken retning han skulle grave. Mange av teknikkene som er beskrevet her er anvendelige for radar- og lydbehandling.
Jeg starter med et par prinsipper som vi alltid begynner å fortelle en potensiell kunde, eller en person som ønsker å begynne med optisk gjenkjenning:

  • Når du løser et problem, gå alltid fra det enkleste. Det er mye lettere å henge en oransje etikett på en person enn å følge en person og fremheve ham med kaskader. Det er mye lettere å ta et kamera med høyere oppløsning enn å utvikle en superoppløsningsalgoritme.
  • Den strenge formuleringen av problemet i optiske gjenkjenningsmetoder er størrelsesordener viktigere enn i problemer systemprogrammering: en overflødig ord i TK kan legge til 50% av arbeidet.
  • I anerkjennelsesoppgaver er det ingen universelle løsninger... Du kan ikke lage en algoritme som bare "gjenkjenner enhver inskripsjon". Et skilt på gaten og et tekstark er fundamentalt forskjellige objekter. Sannsynligvis kan du lage en generell algoritme (her er et godt eksempel fra Google), men det vil kreve mye arbeid av et stort team og bestå av dusinvis av forskjellige subrutiner.
  • OpenCV er en bibel som har mange metoder, og som du kan løse 50 % av volumet av nesten ethvert problem med, men OpenCV er bare en liten del av det du faktisk kan gjøre. I en studie ble konklusjonene skrevet: "Problemet er ikke løst med OpenCV-metoder, derfor er det uløselig." Prøv å unngå dette, ikke vær lat og nøkternt evaluer gjeldende oppgave hver gang fra bunnen av, uten å bruke OpenCV-maler.
Det er veldig vanskelig å gi noen universelle råd, eller fortelle deg hvordan du lager en slags struktur som du kan bygge en løsning på vilkårlige problemer rundt datamaskin syn... Hensikten med denne artikkelen er å strukturere hva du kan bruke. Jeg skal prøve å bryte eksisterende metoder inn i tre grupper. Den første gruppen er foreløpig filtrering og bildeforberedelse. Den andre gruppen er logisk behandling av filtreringsresultater. Den tredje gruppen er beslutningsalgoritmer basert på logisk prosessering. Grensene mellom gruppene er svært betingede. For å løse et problem er det langt fra alltid nødvendig å bruke metoder fra alle grupper, noen ganger er to, og noen ganger til og med én, nok.

Listen over metoder gitt her er ufullstendig. Jeg foreslår å legge til kritiske metoder i kommentarene som jeg ikke har skrevet, og tilskrive 2-3 medfølgende ord til hver.

Del 1. Filtrering

I denne gruppen har jeg plassert metoder som lar deg fremheve interesseområder i bilder uten å analysere dem. De fleste av disse metodene bruker en slags enhetlig transformasjon på alle piksler i bildet. På filtreringsnivå analyseres ikke bildet, men punktene som passerer filtreringen kan betraktes som områder med spesielle egenskaper.
Terskelbinarisering, valg av histogramområde
Den enkleste transformasjonen er terskelbinariseringen av bildet. Til RGB-bilder og i gråtonebilder er terskelen fargeverdien. Møte ideelle oppgaver hvor en slik transformasjon er tilstrekkelig. La oss si at du automatisk vil velge objekter på et hvitt ark:




Valget av terskelen der binarisering skjer, bestemmer i stor grad selve binariseringsprosessen. V i dette tilfellet, bildet har blitt binarisert av gjennomsnittsfargen. Vanligvis gjøres binarisering ved hjelp av en algoritme som adaptivt velger terskelen. Denne algoritmen kan være valget av forventning eller modus. Og du kan velge den største toppen av histogrammet.

Binarisering kan gi veldig interessante resultater når vi jobber med histogrammer, inkludert i en situasjon der vi vurderer et bilde ikke i RGB, men i HSV. Segmenter for eksempel fargene av interesse. Dette prinsippet kan brukes til å bygge både en merkedetektor og en menneskehuddetektor.
Klassisk filtrering: Fourier, LPF, HPF
De klassiske metodene for filtrering fra radar og signalbehandling kan med hell brukes i en rekke mønstergjenkjenningsoppgaver. Tradisjonell metode i radar, som nesten aldri brukes i bilder i sin rene form, er Fourier-transformasjonen (nærmere bestemt FFT). Et av få unntak som bruker endimensjonal transformasjon Fourier, - bildekomprimering. For bildeanalyse er en endimensjonal transformasjon vanligvis ikke nok, du må bruke en mye mer ressurskrevende todimensjonal transformasjon.

Det er få som faktisk beregner det, vanligvis er det mye raskere og enklere å bruke konvolusjon av området av interesse med et ferdig filter skjerpet for høye (HPF) eller lave (LPF) frekvenser. Denne metoden tillater selvfølgelig ikke spektrumanalyse, men i spesifikk oppgave videobehandling trenger vanligvis ikke en analyse, men et resultat.


Det meste enkle eksempler filtre som implementerer understreking lave frekvenser(Gaussisk filter) og høye frekvenser(Gabor-filter).
For hvert punkt i bildet velges et vindu og multipliseres med et filter av samme størrelse. Resultatet av denne konvolusjonen er den nye poengverdien. Når du implementerer et lavpassfilter og et høypassfilter, oppnås bilder av følgende type:



Wavelets
Men hva om vi bruker en vilkårlig karakteristisk funksjon for konvolusjon med et signal? Da skal den hete «Wavelet transform». Denne definisjonen av wavelets er ikke korrekt, men tradisjonelt har det utviklet seg at i mange kommandoer wavelet-analyse er søket etter et vilkårlig mønster i et bilde ved å bruke konvolusjon med en modell av dette mønsteret. Det er et sett klassiske funksjoner brukes i wavelet-analyse. Disse inkluderer Haar wavelet, Morlet wavelet, meksikansk hatt wavelet, etc. Haar primitiver, som det var flere av mine tidligere artikler om (,), refererer til slike funksjoner for todimensjonalt rom.


Over er 4 eksempler på klassiske wavelets. 3D Haar wavelet, 2D Meyer wavelet, Mexican Hat wavelet, Daubechies wavelet. Et godt eksempelÅ bruke den utvidede tolkningen av wavelets er problemet med å finne en bluss i øyet, som selve blusen er bølgen for:

Klassiske wavelets brukes vanligvis til å komprimere bilder, eller for å klassifisere dem (beskrevet nedenfor).
Sammenheng
Etter en slik fri tolkning av wavelets fra min side, er det verdt å nevne den faktiske korrelasjonen som ligger til grunn for dem. Når du filtrerer bilder, er dette uerstattelig verktøy... Den klassiske applikasjonen er videostrømkorrelasjon for å finne skift eller optiske strømmer. Den enkleste detektoren shift er også på en måte en forskjellskorrelator. Der bildene ikke samsvarer, var det bevegelse.

Filtreringsfunksjoner
En interessant klasse av filtre er funksjonsfiltrering. Dette er rent matematiske filtre som lar deg oppdage en enkel matematisk funksjon på bildet (rett linje, parabel, sirkel). Et akkumulerende bilde er bygget inn som for hvert punkt i originalbildet tegnes et sett med funksjoner som genererer det. Den mest klassiske transformasjonen er Hough-transformasjonen for linjer. I denne transformasjonen, for hvert punkt (x; y), tegnes settet med punkter (a; b) av den rette linjen y = ax + b, for hvilke likhet er sann. Vi får flotte bilder:


(det første plusset er til den som er den første som finner fangsten på bildet og en slik definisjon og forklarer det, det andre pluss til den som er den første som sier det som vises her)
Hough-transformasjonen lar deg finne alle parameteriserbare funksjoner. For eksempel en sirkel. Det er en modifisert transformasjon som lar deg søke etter alle former. Denne transformasjonen er fryktelig glad i matematikere. Men når du behandler bilder, fungerer det dessverre ikke alltid. Høyt Lav hastighet arbeid, veldig høy følsomhet for kvaliteten på binarisering. Selv i ideelle situasjoner foretrakk jeg å klare meg med andre metoder.
Analogen til Hough-transformasjonen for rette linjer er Radon-transformasjonen. Det beregnes gjennom FFT, som gir en ytelsesfordel i en situasjon hvor det er mange poeng. I tillegg kan den brukes på et ikke-binarisert bilde.
Filtrering av konturer
En egen klasse med filtre er kant- og konturfiltrering. Kontur er veldig nyttig når vi vil gå fra å jobbe med et bilde til å jobbe med objekter i det bildet. Når emnet er komplekst nok, men godt definert, er det ofte det den eneste måten arbeider med det er valget av konturene. Finnes hele linjen algoritmer, løse problemet filtreringskonturer:

Oftest er det Kenny som brukes, som fungerer bra og som har implementering i OpenCV (Sobel er også der, men han ser dårligere ut for konturer).



Andre filtre
Over er filtrene, modifikasjoner som bidrar til å løse 80-90% av problemene. Men i tillegg til dem er det mer sjeldne filtre som brukes i lokale oppgaver. Det er dusinvis av slike filtre, jeg vil ikke liste opp alle. Interessante er iterative filtre (for eksempel en aktiv utseendemodell), samt ridgelet- og curvlet-transformasjoner, som er en legering av klassisk wavelet-filtrering og analyse i radontransformasjonsfeltet. Beamlet-transformasjonen fungerer fint på grensen til wavelet-transformasjonen og logisk analyse, slik at du kan fremheve konturene:

Men disse transformasjonene er veldig spesifikke og er skreddersydd for sjeldne oppgaver.

Del 2. Logisk behandling av filtreringsresultater

Filtrering gir et sett med data som er egnet for behandling. Men ofte kan du ikke bare ta og bruke disse dataene uten å behandle dem. I denne delen vil det være flere klassiske metoder som lar deg gå fra bildet til egenskapene til objekter, eller til selve objektene.
Morfologi
Overgangen fra filtrering til logikk er etter min mening metodene for matematisk morfologi (,,). Faktisk er dette de enkleste operasjonene for å bygge opp og erodere binære bilder. Disse metodene lar deg fjerne støy fra et binært bilde ved å øke eller redusere eksisterende elementer. På grunnlag av matematisk morfologi er det konturalgoritmer, men vanligvis bruker de en slags hybridalgoritmer eller algoritmer i kombinasjon.
Konturanalyse
Algoritmer for å få grenser er allerede nevnt i avsnittet om filtrering. De resulterende grensene er ganske enkelt konvertert til konturer. For Cannys algoritme skjer dette automatisk; for andre algoritmer kreves ytterligere binarisering. Du kan få en kontur for en binær algoritme, for eksempel ved billealgoritmen.
Konturen er en unik egenskap ved et objekt. Dette gjør det ofte mulig å identifisere objektet langs konturen. Det er et kraftig matematisk apparat som lar deg gjøre dette. Apparatet kalles konturanalyse (,).

For å være ærlig har jeg aldri klart å bruke konturanalyse i reelle problemer. Det kreves for ideelle forhold. Enten er det ingen grense, eller så er det for mye støy. Men hvis du trenger å gjenkjenne noe under ideelle forhold, er konturanalyse et flott alternativ. Fungerer veldig raskt, vakker matematikk og klar logikk.
Spesielle punkter
Enkeltpunkter er unike egenskaper ved et objekt som lar deg assosiere et objekt med seg selv eller med lignende objektklasser. Det er flere dusin måter å fremheve slike punkter. Noen metoder fremhever spesielle punkter i tilstøtende rammer, noen etter lang tid og når du endrer belysning, noen lar deg finne spesielle punkter som forblir slik selv når objektet roteres. La oss starte med metoder som lar oss finne entallspunkter som ikke er så stabile, men som raskt beregnes, og så går vi i økende kompleksitet:
Første klasse. Enkeltpunkter som er stabile i sekunder. Slike punkter brukes til å lede objektet mellom tilstøtende videobilder, eller for å slå sammen bilder fra nabokameraer. Disse punktene inkluderer lokale bildemaksima, bildevinkler (den beste av detektorene, kanskje Haris-detektoren), punkter der spredningsmaksima nås, visse gradienter, etc.
Andre klasse. Spesielle punkter som er stabile med endringer i lyssetting og små bevegelser av motivet. Slike punkter brukes først og fremst til opplæring og etterfølgende klassifisering av objekttyper. For eksempel er en fotgjengerklassifiserer eller en ansiktsklassifiser et produkt av et system bygget rundt slike punkter. Noen av de tidligere nevnte wavelets kan være grunnlaget for slike punkter. For eksempel Haar primitiver, søk etter høydepunkter, søk etter andre spesifikke funksjoner... Disse punktene inkluderer punkter funnet med retningsgradienthistogram-metoden (HOG).
Tredje klasse. Stabile poeng. Jeg vet bare om to metoder som gir fullstendig stabilitet og om deres modifikasjoner. Disse er SURF og SIFT. De lar deg finne spesielle punkter selv når du roterer bildet. Beregningen av slike poeng tar lengre tid enn andre metoder, men nok begrenset tid... Dessverre er disse metodene patentert. Selv om algoritmene i Russland ikke er patentert, så bruk dem for hjemmemarkedet.

Del 3. Opplæring

Den tredje delen av historien vil være viet metoder som ikke fungerer direkte med bildet, men som gjør det mulig å ta beslutninger. Hovedsakelig ulike metoder maskinlæring og beslutningstaking. Nylig Yandyks postet et kurs om dette emnet på Habr, det er veldig godt utvalg... Her er den i tekstversjon. For en seriøs studie av temaet, anbefaler jeg sterkt at du ser på dem. Her vil jeg prøve å skissere flere grunnleggende metoder som brukes i mønstergjenkjenning.
I 80 % av situasjonene er essensen av læring i gjenkjenningsproblemet som følger:
Det er et testsett som inneholder flere klasser av objekter. La det være tilstedeværelsen / fraværet av en person på bildet. For hvert bilde er det et sett med funksjoner som har blitt identifisert av en funksjon, enten det er Haar, HOG, SURF eller en slags wavelet. Læringsalgoritmen skal bygge en slik modell, etter hvilken den skal kunne analysere et nytt bilde og bestemme hvilke av objektene som er på bildet.
Hvordan gjøres det? Hver av testbilder er et punkt i funksjonsrommet. Koordinatene er vekten til hver av funksjonene i bildet. La våre tegn være: "Tilstedeværelsen av øyne", "Tilstedeværelsen av en nese", "Tilstedeværelsen av to hender", "Tilstedeværelsen av ører", etc. ... menneskelig. For en person i et slikt rom vil poenget være riktig. For apen er poenget for hesten. Klassifisereren er trent på et utvalg eksempler. Men ikke alle fotografier viste hender, andre har ikke øyne, og i den tredje har apen en menneskelig nese på grunn av en feil i klassifiseringen. Den trente menneskelige klassifisereren deler automatisk funksjonsrommet på en slik måte at det sier: hvis den første funksjonen ligger i området 0,5 I hovedsak er formålet med klassifikatoren å tegne i funksjonsrommet områdene som er karakteristiske for klassifiseringsobjektene. Slik vil den suksessive tilnærmingen til svaret for en av klassifisørene (AdaBoost) i todimensjonalt rom se ut:


Det er mange klassifiserere. Hver av dem fungerer bedre i sine egne oppgaver. Oppgaven med å velge en klassifiserer for en spesifikk oppgave er på mange måter en kunst. Her er noen vakre bilder om temaet.
Enkel sak, endimensjonal separasjon
La oss analysere ved eksempel det enkleste tilfellet av klassifisering, når funksjonsrommet er endimensjonalt, og vi må dele 2 klasser. Situasjonen oppstår oftere enn man kan forestille seg: for eksempel når du trenger å skille mellom to signaler, eller sammenligne et mønster med en prøve. La oss si at vi har en treningsprøve. I dette tilfellet oppnås et bilde, hvor det på X-aksen vil være et mål på likhet, og på Y-aksen - antall hendelser med et slikt mål. Når det søkte objektet ser ut som seg selv, oppnås venstre Gauss. Når ikke liker - riktig. En verdi på X = 0,4 deler prøvene slik at en feilaktig avgjørelse minimerer sannsynligheten for at feil avgjørelse blir tatt. Det er letingen etter en slik separator som er klassifiseringsproblemet.


En liten bemerkning. Kriteriet som minimerer feilen vil ikke alltid være optimalt. Den neste grafen er en graf av et ekte irisgjenkjenningssystem. For et slikt system er kriteriet valgt slik at det minimerer sannsynligheten for en falsk innrømmelse av en uautorisert person til objektet. Denne sannsynligheten kalles "feil av den første typen", "sannsynlighet for falsk alarm", "falsk positiv". I den engelskspråklige litteraturen "False Access Rate".
) AdaBusta er en av de vanligste klassifikatorene. For eksempel er Haar-kaskaden bygget på den. Vanligvis brukes de når en binær klassifisering er nødvendig, men ingenting hindrer deg i å undervise for et større antall klasser.
SVM (,,,) En av de kraftigste klassifikatorene med mange implementeringer. I utgangspunktet, på læringsoppgavene jeg møtte, fungerte det på en lignende måte som adabusta. Den anses som rask nok, men treningen er vanskeligere enn Adabusta, og det kreves valg av riktig kjerne.

Det er også nevrale nettverk og regresjon. Men for å kort klassifisere dem og vise hvordan de skiller seg, trengs en artikkel mye mer enn denne.
________________________________________________
Jeg håper jeg klarte å lage en rask oversikt over metodene som ble brukt uten å dykke ned i matematikk og beskrivelse. Kanskje det vil hjelpe noen. Selv om artikkelen selvfølgelig er ufullstendig og det er ikke et ord om å jobbe med stereobilder, eller om OLS med Kalman-filter, eller om den adaptive Bayesianske tilnærmingen.
Hvis du liker artikkelen, så vil jeg prøve å gjøre den andre delen med et utvalg eksempler på hvordan de eksisterende ImageRecognition-oppgavene løses.

Og endelig

Hva skal man lese?
1) En gang likte jeg veldig godt boken "Digital Image Processing" av B. Yane, som er skrevet enkelt og tydelig, men samtidig er nesten all matematikk presentert. Bra for å gjøre deg kjent med eksisterende metoder.
2) Klassikerne i sjangeren er R. Gonzalez, R. Woods "Digital Image Processing". Av en eller annen grunn var det vanskeligere for meg enn den første. Mye mindre matematikk, men flere metoder og bilder.
3) «Bildebehandling og analyse i maskinsynsoppgaver» – skrevet med utgangspunkt i et kurs undervist ved en av avdelingene til PhysTech. Det er mange metoder og deres detaljerte beskrivelser. Men etter min mening har boken to store ulemper: boken er sterkt fokusert på programvarepakken som følger med, i boken blir en beskrivelse av en enkel metode for ofte til en matematisk jungel, som det er vanskelig å lage en strukturdiagram av metoden. Men forfatterne laget et praktisk nettsted der nesten alt innholdet presenteres - wiki.technicalvision.ru Legg til tagger

Dette prosjektet hevder ikke å være det første stedet i verden og regnes ikke som en konkurrent FineReader, men forhåpentligvis vil ideen om karaktermønstergjenkjenning ved å bruke Euler-karakteristikken være ny.

Bekjentskap med Euler-bildekarakteristikken.

Hovedideen er at et svart-hvitt-bilde tas, og forutsatt at 0 er en hvit piksel og 1 er en svart piksel, så vil hele bildet være en matrise av enere og nuller. I dette tilfellet kan et svart-hvitt bilde representeres som et sett med fragmenter på 2 x 2 piksler, alle mulige kombinasjoner er vist i figuren:

På hvert bilde bilde1, bilde2,... viser en rød firkant av telletrinnet i algoritmen, innenfor hvilket et av fragmentene F fra bildet over. Ved hvert trinn summeres hvert fragment, som et resultat, for bildet Opprinnelig vi får settet:, videre vil det kalles Euler-bildekarakteristikken eller karakteristikken.


KOMMENTAR: i praksis brukes ikke F0-verdien (for originalbildet er denne verdien 8), siden det er bakgrunnen til bildet. Derfor vil 15 verdier bli brukt, fra F1 til F15.

Egenskaper til Euler-karakteristikkene til bildet.

  1. Verdien av karakteristikken er unik, med andre ord er det ikke to bilder med samme Euler-karakteristikk.
  2. Det er ingen algoritme for å konvertere fra det karakteristiske settet til det originale bildet, den eneste måten er brute force.

Hva er tekstgjenkjenningsalgoritmen?

Ideen med å gjenkjenne bokstaver er at vi på forhånd beregner Euler-karakteristikken for alle symboler i språkets alfabet og lagrer den i kunnskapsbasen. Deretter, for delene av det gjenkjente bildet, vil vi beregne Euler-karakteristikken og søke etter den i kunnskapsbasen.

Anerkjennelsesstadier:

  1. Bildet kan være enten svart-hvitt eller farge, derfor er det første trinnet tilnærmingen av bildet, det vil si å oppnå svart-hvitt fra det.
  2. Vi gjør en piksel-for-piksel passerer over hele bildet for å finne de svarte pikslene. Når en skyggelagt piksel blir funnet, startes en rekursiv operasjon for å finne alle skyggelagte piksler ved siden av den funnet og påfølgende. Som et resultat får vi et fragment av bildet, som enten kan være en hel karakter eller en del av det, eller "søppel" som bør kastes.
  3. Etter å ha funnet alle usammenhengende deler av bildet, beregnes Euler-karakteristikken for hver.
  4. Deretter kommer analysatoren i drift, som passerer gjennom hvert fragment og bestemmer om det er en verdi av dens Euler-karakteristikk i kunnskapsbasen. Hvis vi finner verdien, antar vi at dette er et gjenkjent fragment av bildet, ellers lar vi det stå til videre studier.
  5. Ugjenkjente deler av bildet blir utsatt for heuristisk analyse, det vil si at ved verdien av Euler-karakteristikken prøver jeg å finne den mest passende verdien i kunnskapsbasen. Hvis det ikke ble funnet, forsøkes det å "lime" de nærliggende fragmentene, og allerede for dem å søke etter resultatet i kunnskapsbasen. Hvorfor "limes" man? Poenget er at ikke alle bokstaver består av ett sammenhengende bilde, for eksempel "!" Utropstegnet inneholder 2 segmenter (en pinne og en prikk), derfor, før du leter etter det i kunnskapsbasen, er det nødvendig å beregne den totale verdien av Euler-karakteristikken fra begge deler. Hvis det ikke var mulig å finne et akseptabelt resultat selv etter liming med tilstøtende segmenter, blir fragmentet regnet som søppel og hoppet over.

Systemsammensetning:

  1. Kunnskapsbase- en fil eller filer som opprinnelig er laget av meg eller noen andre, som inneholder karakteristiske tegnsett og som kreves for gjenkjenning.
  2. Kjerne- inneholder de grunnleggende funksjonene som utfører gjenkjenning
  3. Generator- en modul for å lage en kunnskapsbase.

ClearType og kantutjevnelse.

Så ved inngangen har vi et gjenkjennelig bilde, og målet er å lage svart-hvitt fra det, egnet for å starte gjenkjenningsprosessen. Det ser ut til at det som kan være enklere, alle hvite piksler regnes som 0, og alle resten er 1, men ikke alt er så enkelt. Teksten på bildet kan være kantutjevnet og ikke kantutjevnet. Kantutjevnede tegn ser jevne ut og uten hjørner, og ikke-kantutjevnede tegn vil se ut på moderne skjermer med synlige piksler langs omrisset. Med bruken av LCD-skjermer (liquid crystal) ble ClearType (for Windows) og andre typer kantutjevnelse skapt som utnytter funksjonene til skjermmatrisen. Pikslene i tekstbildet endrer farger, hvoretter det ser mye "mykere ut". For å se resultatet av kantutjevning, kan du skrive inn en bokstav (eller tekst), for eksempel i mspaint, zoom inn, og teksten din blir til en slags flerfarget mosaikk.

Hva er i veien? Hvorfor ser vi et vanlig symbol i liten skala? Bedrar øynene oss? Faktum er at en piksel på en LCD-skjerm ikke består av en enkelt piksel som kan ta ønsket farge, men av 3 underpiksler med 3 farger, som er nok til å oppnå ønsket farge. Derfor er målet med ClearType å få den mest behagelige teksten for øyet ved å bruke en funksjon i LCD-skjermmatrisen, og dette oppnås ved å bruke subpikselgjengivelse. Den som har en "Magnifier" kan, for eksperimentet, forstørre hvilket som helst sted på den påslåtte skjermen og se matrisen som på bildet nedenfor.

Figuren viser et kvadrat på 3x3 piksler av LCD-matrisen.

Merk følgende! Denne funksjonen kompliserer å oppnå et svart-hvitt-bilde og påvirker resultatet i stor grad, siden det ikke alltid gjør det mulig å oppnå det samme bildet, hvis Euler-karakteristika er lagret i kunnskapsbasen. Dermed tvinger forskjellen i bilder til å utføre en heuristisk analyse, som kanskje ikke alltid er vellykket.


Få et svart-hvitt-bilde.

Algoritmene for å konvertere farge til svart-hvitt som finnes på Internett passet ikke meg med kvaliteten. Etter å ha brukt dem, ble bildene av symboler utsatt for sub-piksel-gjengivelse forskjellige i bredde, linjeskift av bokstaver og merkelig rusk dukket opp. Som et resultat bestemte jeg meg for å få et svart-hvitt-bilde ved å analysere lysstyrken til pikselen. Jeg anså alle piksler lysere (større enn verdien) 130 enheter for å være svarte, resten er hvite. Denne metoden er ikke ideell, og fører fortsatt til et utilfredsstillende resultat hvis lysstyrken på teksten endres, men i det minste mottok den bilder som ligner verdiene i kunnskapsbasen. Implementeringen kan sees i LuminosityApproximator-klassen.

Kunnskapsbase.

Den første ideen om å fylle kunnskapsbasen var slik at for hver bokstav i språket ville jeg beregne Euler-karakteristikken til det resulterende bildet av et symbol for 140 fonter som er installert på datamaskinen min (C: \ Windows \ Fonts), Jeg vil legge til alle alternativene for skrifttyper (Normal, Fet, Kursiv) og størrelser fra 8 til 32, dermed vil jeg dekke alle, eller nesten alle, varianter av bokstaver og basen vil bli universell, men dessverre viste det seg ikke så bra som det ser ut til. Med disse betingelsene fikk jeg følgende:

  1. Kunnskapsbasefilen viste seg å være stor nok (ca. 3 megabyte) for russisk og engelsk. Til tross for at Euler-karakteristikken er lagret som en enkel streng på 15 sifre, og selve filen er et komprimert arkiv (DeflateStream), som deretter pakkes ut i minnet.
  2. Det tar meg omtrent 10 sekunder å deserialisere kunnskapsbasen. Samtidig led sammenligningstiden av karakteristiske sett. Vi fant ikke funksjonen for å beregne GetHashCode (), så vi måtte sammenligne bit for bit. Og sammenlignet med en kunnskapsbase på 3-5 fonter, økte analysetiden for en tekst med en base på 140 fonter 30-50 ganger. Samtidig lagres ikke de samme karakteristiske settene i kunnskapsbasen, til tross for at enkelte tegn i forskjellige fonter kan se like ut og være like, selv det er for eksempel 20 og 21 fonter.

Derfor måtte jeg lage en liten kunnskapsbase som går inne i Core-modulen, og gjør det mulig å teste funksjonaliteten. Det er et veldig alvorlig problem med å fylle databasen. Ikke alle skrifter viser små tegn riktig. La oss si at tegnet "e" ved gjengivelse med 8 skriftstørrelser kalt "Franklin Gothic Medium" oppnås som:

Og ikke mye som originalen. Dessuten, hvis du legger det til kunnskapsbasen, så er dette vil i stor grad forverre resultatene av heuristikken, siden det er misvisende å analysere symboler som ligner på denne. D Dette symbolet ble hentet fra forskjellige fonter for forskjellige bokstaver. Prosessen med å fylle selve kunnskapsbasen må kontrolleres slik at hvert bilde av et symbol, før det lagres i kunnskapsbasen, kontrolleres av en person for korrespondanse til bokstaven. Men dessverre har jeg ikke så mye energi og tid.

Algoritme for tegnsøk.

Jeg vil si med en gang at jeg i utgangspunktet undervurderte dette problemet med søk og glemte at symboler kan bestå av flere deler. Det virket for meg at jeg i løpet av en piksel-for-piksel-gjennomgang ville møte et symbol, finne delene, hvis noen, kombinere dem og analysere. Et normalt pass vil se ut som om jeg finner bokstaven "H" (kunnskapsbase) og tror at alle symboler lavere høydepunkt og over lavpunkt er i forhold til gjeldende linje og bør aliseres i en haug:

Men dette er en ideell situasjon, i løpet av gjenkjennelsen måtte jeg forholde meg til demonterte bilder, som i tillegg til alt kunne ha en enorm mengde søppel plassert ved siden av teksten:


I dette bildet vil ordet «ja» forsøke å forklare kompleksiteten i analysen. Vi vil anta at dette er en komplett streng, men b13 og i6 er søppelbiter som følge av tilnærming. Tegnet "y" mangler en prikk, og samtidig er ingen av tegnene til stede i kunnskapsbasen, for å si med sikkerhet at vi har å gjøre med en tekstlinje fra "c" til "i" linje. Og linjehøyden er veldig viktig for oss, siden vi for liming trenger å vite hvor mye de nærmeste fragmentene skal "limes" og analyseres. Tross alt kan det være en situasjon at vi ved et uhell begynner å lime tegn av to strenger, og resultatene av en slik gjenkjennelse vil være langt fra ideelle.

Heuristikk i analyse av bilder.


Hva er bildegjenkjenningsheuristisk?
Dette er prosessen der et karakteristisk sett som ikke er tilstede i kunnskapsbasen gjenkjennes som den riktige bokstaven i alfabetet. Jeg tenkte lenge på hvordan jeg skulle utføre analysen, og som et resultat viste den mest vellykkede algoritmen seg å være denne:

  1. Jeg finner alle karakteristiske sett i kunnskapsbasen med størst antall verdier F-fragmenter samsvarer med det gjenkjente bildet.
  2. Deretter velger jeg bare de karakteristiske settene der forskjellen med et gjenkjennelig bilde med ulik F-verdi av fragmentet ikke er mer enn + - 1 enhet: -1< F < 1. И это все подсчитывается для каждой буквы алфавита.
  3. Så finner jeg den karakteren som har flest forekomster. Ser på det som resultatet av en heuristisk analyse.
Denne algoritmen gir ikke de beste resultatene på små bilder av tegn (7 - 12 skriftstørrelser) . Men det kan skyldes at kunnskapsbasen inneholder karakteristiske sett for like bilder av ulike symboler.

Et eksempel på bruk i C #.

Et eksempel på et startbilde for bildegjenkjenning. Resultatvariabelen vil inneholde teksten:

var gjenkjenner = ny TextRecognizer (beholder); var rapport = gjenkjenner. Gjenkjenne (bilde); // Rå tekst. var resultat = report.RawText (); // Liste over alle fragmenter og gjenkjenningstilstand for hver. var fragmenter = rapport.Symboler;

Demoprosjekt.

For en visuell demonstrasjon av arbeidet skrev jeg WPF applikasjon. Den er lansert fra et prosjekt kalt " Qocr.Application.Wpf". Et eksempel på et vindu med resultatet av gjenkjenning er nedenfor:

For å gjenkjenne bildet trenger du:

  • Presser "Nytt bilde" velger et bilde for gjenkjenning
  • Bruker " Svart og hvit"du kan se hvilket bilde som skal analyseres. Hvis du ser et bilde av ekstremt lav kvalitet, så ikke forvent gode resultater. For å forbedre resultatene kan du prøve å skrive en omformer fra et fargebilde til svart-hvitt selv.
  • Velge et språk "Språk".
  • Trykker for å gjenkjenne "Kjenne igjen".
Alle deler av bildet skal merkes med en oransje eller grønn ramme.
Et eksempel på gjenkjennelse av flerspråklig tekst:

Ved hjelp av mange animasjoner om eksemplet med problemet med å gjenkjenne tall og perceptronmodellen, gis en visuell introduksjon til læringsprosessen til et nevralt nettverk.

Den første videoen er viet strukturen til komponentene i et nevralt nettverk, den andre til treningen og den tredje til algoritmen til denne prosessen. Som en opplæringsoppgave tok vi det klassiske problemet med å gjenkjenne håndskrevne tall.

Flerlagsperceptronen vurderes i detalj - en grunnleggende (men allerede ganske kompleks) modell for å forstå eventuelle mer moderne versjoner av nevrale nettverk.

1. Komponenter i et nevralt nettverk

Hensikten med den første videoen er å vise hva et nevralt nettverk er. Ved å bruke eksemplet med problemet med å gjenkjenne tall, visualiseres strukturen til komponentene i et nevralt nettverk. Videoen har russiske undertekster.

Uttalelse av problemet med siffergjenkjenning

La oss si at du har tallet 3 gjengitt i en ekstremt lav oppløsning på 28x28 piksler. Hjernen din gjenkjenner enkelt dette nummeret.

Fra et datavitenskapelig synspunkt er det overraskende hvor enkelt hjernen utfører denne operasjonen, med den nøyaktige oppstillingen av piksler som varierer mye fra ett bilde til det neste. Noe i vår visuelle cortex bestemmer at alle trillingene, uansett hvordan de er avbildet, representerer den samme enheten. Derfor oppleves oppgaven med å gjenkjenne tall i en slik sammenheng som enkel.

Men hvis du ble tilbudt å skrive et program som tar inn et bilde av et hvilket som helst siffer i form av en matrise på 28x28 piksler og sender ut selve "enheten" - et siffer fra 0 til 9 - så ville denne oppgaven ikke lenger virke enkel .

Som navnet antyder, er strukturen til det nevrale nettverket noe nær strukturen til det nevrale nettverket i hjernen. For nå, for enkelhets skyld, vil vi forestille oss at i matematisk forstand i nevrale nettverk forstås nevroner som en bestemt beholder som inneholder et tall fra null til en.

Neuronaktivering. Nevrale nettverkslag

Siden rutenettet vårt består av 28x28 = 784 piksler, la det være 784 nevroner som inneholder forskjellige tall fra 0 til 1: jo nærmere en piksel er hvit, jo nærmere er det tilsvarende tallet én. Disse tallene som fyller rutenettet vil bli kalt nevronaktiveringer. Du kan forestille deg dette som om et nevron lyser som en lyspære når det inneholder et tall nær 1 og av når et tall er nær 0.

De beskrevne 784 nevronene danner det første laget av det nevrale nettverket. Det siste laget inneholder 10 nevroner, som hver tilsvarer ett av ti sifre. I disse tallene er aktivering også et tall fra null til én, som gjenspeiler hvor sikker systemet er på at inndatabildet inneholder det tilsvarende sifferet.

Det er også et par mellomlag, kalt skjulte lag, som vi kommer inn på snart. Valget av antall skjulte lag og nevronene de inneholder er vilkårlig (vi valgte 2 lag med 16 nevroner hver), men de velges vanligvis fra visse ideer om oppgaven som løses av det nevrale nettverket.

Prinsippet for det nevrale nettverket er at aktivering i ett lag bestemmer aktivering i det neste. Når de er opphisset, forårsaker en viss gruppe nevroner eksitasjonen av en annen gruppe. Hvis vi overfører aktiveringsverdiene til det første laget til det trente nevrale nettverket i henhold til lysstyrken til hver piksel i bildet, vil kjeden av aktiveringer fra ett lag i det nevrale nettverket til det neste føre til fortrinnsaktivering av en av nevronene i det siste laget som tilsvarer det anerkjente sifferet - valget av det nevrale nettverket.

Formål med skjulte lag

Før vi fordyper oss i matematikken om hvordan ett lag påvirker det neste, hvordan læring skjer og hvordan et nevralt nettverk løser problemet med siffergjenkjenning, la oss diskutere hvorfor en slik lagdelt struktur i det hele tatt kan fungere intelligent. Hva gjør mellomlagene mellom input- og output-lagene?

Form bildelag

I siffergjenkjenningsprosessen samler vi de ulike komponentene. For eksempel består en nier av en sirkel på toppen og en linje til høyre. Figuren 8 har også en sirkel på toppen, men i stedet for en linje til høyre har den en paret sirkel nederst. De fire kan betraktes som tre linjer koblet sammen på en bestemt måte. Etc.

I det idealiserte tilfellet ville man forvente at hver nevron fra det andre laget tilsvarer en av disse komponentene. Og når du for eksempel overfører et bilde med en sirkel på toppen til et nevralt nettverk, er det en viss nevron, hvis aktivering vil bli nærmere en. Dermed tilsvarer overgangen fra det andre skjulte laget til utgangen kunnskapen om hvilket sett med komponenter som tilsvarer hvilken figur.

Lag med bilder av strukturelle enheter

Problemet med å gjenkjenne en sirkel kan også deles inn i deloppgaver. For eksempel for å gjenkjenne de forskjellige små ansiktene som den er dannet av. På samme måte kan en lang vertikal linje betraktes som et mønster for å forbinde flere mindre stykker. Dermed kan det håpes at hver nevron fra det første skjulte laget av det nevrale nettverket utfører operasjonen med å gjenkjenne disse små kantene.

Dermed fører inngangsbildet til aktivering av visse nevroner i det første skjulte laget, og definerer karakteristiske små stykker, disse nevronene aktiverer i sin tur større former, som et resultat av aktivering av nevronet til utgangslaget knyttet til et visst antall.

Hvorvidt et nevralt nettverk vil opptre på denne måten er et annet spørsmål du vil komme tilbake til når du diskuterer prosessen med å trene et nettverk. Dette kan imidlertid tjene som en rettesnor for oss, et slags mål for en slik lagdelt struktur.

På den annen side er en slik definisjon av ansikter og mønstre nyttig ikke bare i problemet med å gjenkjenne tall, men generelt i problemet med å bestemme mønstre.

Og ikke bare for gjenkjenning av tall og bilder, men også for andre intellektuelle oppgaver som kan brytes ned i lag av abstraksjon. For eksempel, for talegjenkjenning, trekkes individuelle lyder, stavelser, ord ut fra rå lyd, deretter fraser, mer abstrakte tanker, etc.

Definere gjenkjenningsområdet

For å være spesifikk, la oss forestille oss nå at formålet med et individuelt nevron i det første skjulte laget er å finne ut om bildet inneholder et ansikt i området som er merket på figuren.

Det første spørsmålet er hvilke innstillinger det nevrale nettverket skal ha for å kunne oppdage dette mønsteret eller et hvilket som helst annet mønster av piksler.

La oss tildele en numerisk vekt w i til hver forbindelse mellom nevronet vårt og nevronet fra inngangslaget. Deretter tar vi alle aktiveringene fra det første laget og beregner deres vektede sum i henhold til disse vektene.

Siden antall vekter er det samme som antall aktiveringer, kan de også tildeles et lignende rutenett. Vi vil betegne positive vekter med grønne piksler, og negative med røde. Lysstyrken til pikselen vil tilsvare den absolutte verdien av vekten.

Nå, hvis vi setter alle vekter til null, bortsett fra pikslene som samsvarer med malen vår, vil den vektede summen reduseres til summen av aktiveringsverdiene til pikslene i området som er av interesse for oss.

Hvis du vil finne ut om en kant er der, kan du legge til røde vektkanter rundt det grønne vektrektangelet, tilsvarende negative vekter. Da vil den vektede summen for dette området være maksimalt når de gjennomsnittlige pikslene i bildet i dette området er lysere og pikslene rundt dem er mørkere.

Skalering av aktivering til intervall

Ved å beregne denne vektede summen kan du få et hvilket som helst tall over et bredt spekter av verdier. For at den skal falle inn i det nødvendige området for aktiveringer fra 0 til 1, er det rimelig å bruke en funksjon som vil "komprimere" hele området til et intervall.

Sigmoid-logistikkfunksjonen brukes ofte til denne skaleringen. Jo større den absolutte verdien av det negative inngangstallet er, desto nærmere er sigmoid-utgangsverdien null. Jo større verdien av det positive inngangstallet er, desto nærmere er funksjonsverdien én.

Dermed er nevronaktivering i hovedsak et mål på hvor positiv den tilsvarende vektede summen er. For å hindre at nevronet aktiveres ved små positive tall, kan du legge til et eller annet negativt tall til den vektede summen – en skjevhet, som bestemmer hvor stor den vektede summen må være for å aktivere nevronen.

Så langt har samtalen kun handlet om ett nevron. Hvert nevron fra det første skjulte laget er koblet til alle 784 pikselnevronene i det første laget. Og hver av disse 784 forbindelsene vil ha en annen vekt knyttet til seg. Hvert av nevronene i det første skjulte laget har også et skift knyttet til seg, lagt til den vektede summen før denne verdien "klemmes" av sigmoiden. Så det er 784x16 vekter og 16 skift for det første skjulte laget.

Forbindelsene mellom andre lag inneholder også vekter og forskyvninger knyttet til dem. Således, for det gitte eksemplet, fungerer omtrent 13 tusen vekter og skift som bestemmer oppførselen til det nevrale nettverket som justerbare parametere.

Å trene et nevralt nettverk til å gjenkjenne tall betyr å tvinge datamaskinen til å finne de riktige verdiene for alle disse tallene slik at den løser oppgaven. Tenk deg å sette alle disse vektene og skifte manuelt. Dette er et av de mest effektive argumentene for å behandle et nevralt nettverk som en svart boks - det er nesten umulig å mentalt spore den felles oppførselen til alle parametere.

Beskrivelse av et nevralt nettverk i form av lineær algebra

La oss diskutere en kompakt måte for matematisk representasjon av nevrale nettverksforbindelser. La oss kombinere alle aktiveringene av det første laget til en kolonnevektor. Vi kombinerer alle vektene til en matrise, der hver rad beskriver forbindelsene mellom nevroner i ett lag med et spesifikt nevron i det neste (i tilfelle vanskeligheter, se kurset beskrevet av oss). Som et resultat av å multiplisere matrisen med vektoren, får vi en vektor som tilsvarer de vektede summene av aktiveringer av det første laget. Legg til matriseproduktet med skiftvektoren og pakk det inn med en sigmoid-funksjon for å skalere verdiområdene. Som et resultat får vi en kolonne med tilsvarende aktiveringer.

I stedet for kolonner og matriser, som vanlig i lineær algebra, kan du åpenbart bruke deres korte notasjon. Dette gjør den tilsvarende programkoden både enklere og raskere, siden maskinlæringsbiblioteker er optimert for vektordatabehandling.

Avklaring av nevronaktivering

Nå er tiden inne for å avklare forenklingen vi startet med. Nevroner tilsvarer ikke bare tall - aktiveringer, men aktiveringsfunksjoner som tar verdier fra alle nevroner i forrige lag og beregner utgangsverdier i området fra 0 til 1.

Faktisk er hele det nevrale nettverket en stor funksjon som kan justeres gjennom trening med 13 tusen parametere, som tar 784 inngangsverdier og gir sannsynligheten for at bildet tilsvarer ett av ti sifre beregnet på gjenkjenning. Til tross for kompleksiteten er dette bare en funksjon, og på en måte er det fornuftig at det ser komplisert ut, siden hvis det var enklere, ville ikke denne funksjonen kunne løse problemet med siffergjenkjenning.

I tillegg vil vi diskutere hvilke aktiveringsfunksjoner som brukes til å programmere nevrale nettverk nå.

Tillegg: litt om aktiveringsfunksjoner. Sammenligning av sigmoid og ReLU

La oss kort berøre temaet funksjoner som brukes til å "komprimere" intervallet av aktiveringsverdier. Sigmoid-funksjonen er et eksempel som etterligner biologiske nevroner og ble brukt i tidlig arbeid med nevrale nettverk, men den enklere ReLU-funksjonen er nå mer vanlig brukt for å gjøre det lettere å trene et nevralt nettverk.

ReLU-funksjonen tilsvarer den biologiske analogien om at nevroner kan være i aktiv tilstand eller ikke. Hvis en viss terskel passeres, utløses funksjonen, og hvis den ikke passeres, forblir nevronet ganske enkelt inaktivt, med aktivering lik null.

Det viste seg at for dype flerlagsnettverk fungerer ReLU-funksjonen veldig bra, og ofte gir det ingen mening å bruke en mer kompleks sigmoid-funksjon for å beregne.

2. Trening av et nevralt nettverk for siffergjenkjenning

Spørsmålet oppstår: hvordan finner nettverket beskrevet i den første leksjonen de tilsvarende vektene og skiftene kun basert på dataene som er oppnådd? Den andre leksjonen forteller om dette.

Generelt sett er algoritmen å vise et nevralt nettverk et sett med treningsdata som representerer par med bilder av håndskrevne sifre og deres abstrakte matematiske representasjoner.

I disposisjon

Som et resultat av trening må det nevrale nettverket skille tall fra tidligere ikke-representerte testdata. Følgelig kan forholdet mellom antall handlinger med korrekt siffergjenkjenning og antall elementer i testprøven brukes som en test for å trene et nevralt nettverk.

Hvor kommer treningsdataene fra? Problemet som vurderes er svært vanlig, og for løsningen er det laget en stor MNIST-database, bestående av 60 tusen taggede data og 10 tusen testbilder.

Kostnadsfunksjon

Konseptuelt er oppgaven med å trene et nevralt nettverk redusert til å finne minimum av en viss funksjon - en kostnadsfunksjon. La oss beskrive hva det er.

Som du husker, er hvert nevron i det neste laget koblet til nevronet i det forrige laget, mens vekten av disse forbindelsene og det generelle skiftet bestemmer aktiveringsfunksjonen. For å komme i gang et sted kan vi initialisere alle disse vektene og skiftet med tilfeldige tall.

Følgelig, i det første øyeblikket, et utrent nevralt nettverk som svar på et bilde av et gitt tall, for eksempel et bilde av en triplett, produserer utgangslaget en fullstendig tilfeldig respons.

For å trene et nevralt nettverk introduserer vi en kostnadsfunksjon, som så å si vil si til datamaskinen i tilfelle et slikt resultat: «Nei, dårlig datamaskin! Aktiveringsverdien skal være null for alle nevroner bortsett fra én riktig ”.

Stille inn en kostnadsfunksjon for siffergjenkjenning

Matematisk representerer denne funksjonen summen av kvadratene av forskjellene mellom de faktiske aktiveringsverdiene til utgangslaget og deres ideelle verdier. For eksempel, i tilfelle av en triplett, må aktiveringen være null for alle nevroner, bortsett fra den tilsvarende tripletten, der den er lik en.

Det viser seg at for ett bilde kan vi bestemme én gjeldende verdi av kostnadsfunksjonen. Hvis det nevrale nettverket er trent, vil denne verdien være liten, ideelt sett ha en tendens til null, og omvendt: jo større verdi av kostnadsfunksjonen, desto dårligere er nevrale nettverk trent.

For deretter å bestemme hvor godt treningen av det nevrale nettverket var, er det derfor nødvendig å bestemme gjennomsnittsverdien av kostnadsfunksjonen for alle bilder av treningssettet.

Dette er en ganske vanskelig oppgave. Hvis vårt nevrale nettverk har 784 piksler ved inngangen, 10 verdier ved utgangen og krever 13 tusen parametere for å beregne dem, så er kostnadsfunksjonen en funksjon av disse 13 tusen parameterne, gir én enkelt kostnadsverdi som vi ønsker å minimere , og samtidig i hele treningssettet brukes som parametere.

Hvordan endrer du alle disse vektene og skiftene for å trene det nevrale nettverket?

Gradient nedstigning

Til å begynne med, i stedet for å representere en funksjon med 13 000 innganger, la oss starte med en funksjon av én variabel C (w). Som du sikkert husker fra kurset i matematisk analyse, må du ta den deriverte for å finne minimum av en funksjon.

Formen til en funksjon kan imidlertid være svært kompleks, og en fleksibel strategi er å starte fra et vilkårlig punkt og ta et skritt mot å redusere verdien av funksjonen. Ved å gjenta denne prosedyren ved hvert neste punkt, kan man gradvis komme til det lokale minimum av funksjonen, slik en ball som ruller ned en bakke gjør.

Som figuren viser kan en funksjon ha mange lokale minima, og det lokale minimum algoritmen vil være i avhenger av valg av utgangspunkt, og det er ingen garanti for at minimum som er funnet er minimum mulig verdi av kostnadsfunksjonen. Dette må man huske på. I tillegg, for ikke å "glippe" verdien av det lokale minimumet, er det nødvendig å endre trinnstørrelsen i forhold til helningen til funksjonen.

Litt komplisert denne oppgaven, i stedet for en funksjon av én variabel, kan du forestille deg en funksjon av to variabler med én utgangsverdi. Den tilsvarende funksjonen for å finne retningen til den raskeste nedstigningen er den negative gradienten -∇C. Gradienten beregnes, det gjøres et trinn i -∇C-retningen, prosedyren gjentas til vi når minimum.

Den beskrevne ideen kalles gradientnedstigning og kan brukes til å finne minimum av ikke bare en funksjon av to variabler, men også 13 tusen, og et hvilket som helst annet antall variabler. Tenk deg at alle vekter og skift danner én stor kolonnevektor w. For denne vektoren kan du beregne den samme gradientvektoren til kostnadsfunksjonen og bevege deg i tilsvarende retning ved å legge til den resulterende vektoren med vektoren w. Og så gjenta denne prosedyren til funksjonen C (w) kommer til et minimum.

Gradient nedstigningskomponenter

For vårt nevrale nettverk vil skritt mot en lavere verdi av kostnadsfunksjonen bety mindre og mindre tilfeldig oppførsel av det nevrale nettverket som svar på treningsdata. Algoritmen for effektiv beregning av denne gradienten kalles tilbakepropageringsmetoden og vil bli diskutert i detalj i neste avsnitt.

For gradientnedstigning er det viktig at utgangsverdiene til kostnadsfunksjonen endres jevnt. Det er derfor aktiveringsverdier ikke bare har binære verdier 0 og 1, men representerer reelle tall og er i intervallet mellom disse verdiene.

Hver gradientkomponent forteller oss to ting. Tegnet til en komponent angir endringsretningen, og den absolutte verdien angir effekten av denne komponenten på det endelige resultatet: noen vekter bidrar mer til kostnadsfunksjonen enn andre.

Testing av antagelsen om hensikten med skjulte lag

La oss diskutere spørsmålet om hvor godt lagene i det nevrale nettverket samsvarer med forventningene våre fra den første leksjonen. Hvis vi visualiserer vektene til nevronene i det første skjulte laget av det trente nevrale nettverket, vil vi ikke se de forventede tallene som vil tilsvare de små bestanddelene i tallene. Vi vil se mye mindre klare mønstre som tilsvarer hvordan det nevrale nettverket minimerte kostnadsfunksjonen.

På den annen side oppstår spørsmålet, hva du kan forvente hvis du overfører et bilde av hvit støy til det nevrale nettverket? Man kan anta at det nevrale nettverket ikke skal produsere noe spesifikt antall og nevronene i utgangslaget skal ikke aktiveres eller, hvis det aktiveres, på en enhetlig måte. I stedet reagerer det nevrale nettverket på et tilfeldig bilde med et veldefinert tall.

Selv om det nevrale nettverket utfører siffergjenkjenningsoperasjoner, har det ingen anelse om hvordan de er skrevet. Faktisk er slike nevrale nettverk en ganske gammel teknologi, utviklet på 80-90-tallet. Det er imidlertid veldig nyttig å forstå driften av denne typen nevrale nettverk før man forstår moderne alternativer som kan løse ulike interessante problemer. Men jo mer du graver i hva de skjulte lagene i et nevralt nettverk gjør, jo mindre intelligent virker det nevrale nettverket.

Opplæring på strukturerte og tilfeldige data

Tenk på et eksempel på et moderne nevralt nettverk for å gjenkjenne ulike objekter i den virkelige verden.

Hva skjer hvis du blander databasen slik at objekt- og bildenavnene ikke lenger samsvarer? Siden dataene er tilfeldig merket, vil åpenbart gjenkjenningsnøyaktigheten på testprøven være ubrukelig. Men i dette tilfellet, på treningssettet, vil du motta gjenkjenningsnøyaktighet på samme nivå som om dataene var merket opp på riktig måte.

Millioner av vekter for dette spesielle moderne nevrale nettverket vil bli innstilt for nøyaktig å matche dataene og dens markører. Tilsvarer minimeringen av kostnadsfunksjonen noen bildemønstre, og skiller trening på tilfeldig merkede data seg fra trening på feilmerkede data?

Hvis du trener et nevralt nettverk i gjenkjenningsprosessen på tilfeldig merkede data, så er treningen veldig sakte, kostnadskurven fra antall trinn som tas oppfører seg nesten lineært. Hvis opplæring utføres på strukturerte data, synker verdien av kostnadsfunksjonen med mye færre iterasjoner.

3. Tilbakeformeringsmetode

Backpropagation er en nøkkellæringsalgoritme for et nevralt nettverk. La oss først diskutere i generelle termer hva metoden er.

Neuron aktiveringskontroll

Hvert trinn i algoritmen bruker i teorien alle eksempler på treningsprøven. Anta at vi har et bilde av to og vi er helt i begynnelsen av treningen: vektene og skiftene justeres tilfeldig, og bildet tilsvarer et tilfeldig bilde av aktiveringene av utgangslaget.

Vi kan ikke endre aktiveringene til det endelige laget direkte, men vi kan påvirke vektene og skiftene for å endre bildet av aktiveringene til utgangslaget: reduser aktiveringsverdiene til alle nevroner, bortsett fra de tilsvarende 2, og øk aktiveringsverdien til det nødvendige nevronet. I dette tilfellet kreves økning og reduksjon jo mer, jo lenger er den nåværende verdien unna den ønskede.

Alternativer for nevrale nettverkskonfigurasjoner

La oss fokusere på ett nevron som tilsvarer aktiveringen av nevronet til to på utgangslaget. Som vi husker, er dens verdi den vektede summen av aktiveringene av nevronene i det forrige laget pluss skiftet, pakket inn i en skaleringsfunksjon (sigmoid eller ReLU).

For å øke verdien av denne aktiveringen kan vi derfor:

  1. Øk offset b.
  2. Øk vektene m i.
  3. Endre aktiveringene av forrige lag a i.

Fra den vektede sumformelen kan man se at vektene som tilsvarer forbindelsene med de mest aktiverte nevronene gir det største bidraget til aktiveringen av nevronet. En strategi nær biologiske nevrale nettverk er å øke vektene w i proporsjonalt med mengden aktiveringer ai av de tilsvarende nevronene i det forrige laget. Det viser seg at de mest aktiverte nevronene forbinder med nevronet som vi kun ønsker å aktivere med de mest "sterke" forbindelsene.

En annen nærme tilnærming er å endre aktiveringene av nevronene i det forrige laget ai i forhold til vektene w i. Vi kan ikke endre aktiveringen av nevroner, men vi kan endre tilsvarende vekter og skift og dermed påvirke aktiveringen av nevroner.

Ryggformidling

Det nest siste laget av nevroner kan sees på samme måte som utgangslaget. Du samler informasjon om hvordan aktiveringen av nevronene i dette laget må endres for at aktiveringen av utgangslaget skal endres.

Det er viktig å forstå at alle disse handlingene ikke bare skjer med nevronet som tilsvarer de to, men også med alle nevronene i utgangslaget, siden hver nevron i det nåværende laget er forbundet med alle nevronene i det forrige.

Etter å ha oppsummert alle disse nødvendige endringene for det nest siste laget, forstår du hvordan det andre laget fra slutten skal endres. Deretter, rekursivt, gjentar du den samme prosessen for å bestemme egenskapene til vektene og forskyvningene til alle lagene.

Klassisk gradientnedstigning

Som et resultat fører hele operasjonen på ett bilde til å finne de nødvendige endringene på 13 tusen vekter og skift. Ved å gjenta operasjonen på alle eksempler på treningsprøven får du endringsverdiene for hvert eksempel, som du deretter kan gjennomsnitt for hver parameter separat.

Resultatet av denne gjennomsnittsberegningen er kolonnevektoren til den negative gradienten til kostnadsfunksjonen.

Stokastisk gradientnedstigning

Tatt i betraktning hele populasjonen av treningsutvalget for å beregne enhetstrinnet, bremser nedstigningsprosessen. Derfor gjøres vanligvis følgende.

Treningsprøvedataene er tilfeldig blandet og delt inn i undergrupper, for eksempel 100 merkede bilder. Deretter beregner algoritmen gradientnedstigningstrinnet for én undergruppe.

Dette er ikke akkurat den sanne gradienten for kostnadsfunksjonen, som krever alle dataene i treningsutvalget, men siden dataene er tilfeldig valgt, gir det en god tilnærming og, viktigere, kan den øke beregningshastigheten betydelig.

Hvis du konstruerer en læringskurve for en slik modernisert gradientnedstigning, vil den ikke se ut som en ensartet, målrettet nedstigning ned en bakke, men som en svingete bane for en beruset, men å ta raskere skritt og også komme til en minimumsfunksjon.

Denne tilnærmingen kalles stokastisk gradientnedstigning.

Addisjon. Tilbakepropagering matematisk komponent

La oss nå se litt mer formelt på den matematiske bakgrunnen til tilbakepropageringsalgoritmen.

Primitiv nevrale nettverksmodell

La oss starte med et ekstremt enkelt nevralt nettverk bestående av fire lag, hvor det kun er ett nevron i hvert lag. Følgelig har nettverket tre vekter og tre skift. La oss se hvor følsom funksjonen er for disse variablene.

La oss starte med forbindelsen mellom de to siste nevronene. La oss betegne det siste laget L, det nest siste L-1, og aktiveringen av nevronene under vurdering som ligger i dem a (L), a (L-1).

Kostnadsfunksjon

Tenk deg at den ønskede aktiveringsverdien til det siste nevronet gitt av treningseksemplene er y, som for eksempel er 0 eller 1. Dermed er kostnadsfunksjonen definert for dette eksemplet som

C 0 = (a (L) - y) 2.

Husk at aktiveringen av dette siste nevronet er satt av den vektede summen, eller snarere av skaleringsfunksjonen til den vektede summen:

a (L) = σ (w (L) a (L-1) + b (L)).

For korthets skyld kan den vektede summen angis med en bokstav med en passende indeks, for eksempel z (L):

a (L) = σ (z (L)).

La oss vurdere hvordan små endringer i vekten w (L) påvirker verdien av kostnadsfunksjonen. Eller i matematiske termer, hva er vektderiverten av kostnadsfunksjonen ∂C 0 / ∂w (L)?

Man kan se at endringen i C 0 avhenger av endringen i a (L), som igjen avhenger av endringen i z (L), som også avhenger av w (L). I henhold til regelen om å ta lignende derivater, bestemmes ønsket verdi av produktet av følgende partielle derivater:

∂C 0 / ∂w (L) = ∂z (L) / ∂w (L) ∂a (L) / ∂z (L) ∂C 0 / ∂a (L).

Definisjon av derivater

La oss beregne de tilsvarende derivatene:

∂C 0 / ∂a (L) = 2 (a (L) - y)

Det vil si at den deriverte er proporsjonal med forskjellen mellom gjeldende aktiveringsverdi og den ønskede.

Den gjennomsnittlige derivatet i kjeden er ganske enkelt derivatet av skaleringsfunksjonen:

∂a (L) / ∂z (L) = σ "(z (L))

Til slutt er den siste faktoren den deriverte av den vektede summen:

∂z (L) / ∂w (L) = a (L-1)

Dermed bestemmes den tilsvarende endringen av hvor mye det forrige nevronet er aktivert. Dette korrelerer med ideen nevnt ovenfor om at det dannes en sterkere forbindelse mellom nevroner som lyser opp sammen.

Sluttuttrykk:

∂C 0 / ∂w (L) = 2 (a (L) - y) σ "(z (L)) a (L-1)

Ryggformidling

Husk at en viss derivat kun er for kostnaden av et separat eksempel på treningsprøven C 0. For kostnadsfunksjonen C, som vi husker, er det nødvendig å gjennomsnitt over alle eksempler på treningsutvalget:

∂C / ∂w (L) = 1 / n Σ ∂C k / ∂w (L)

Den resulterende gjennomsnittsverdien for en bestemt w (L) er en av komponentene i gradienten til kostnadsfunksjonen. Hensynet til skift er identiske med hensynet til vekter.

Etter å ha fått de tilsvarende derivatene, kan vi fortsette vurderingen for de foregående lagene.

Modell med mange nevroner per lag

Men hvordan gjøre overgangen fra lag som inneholder ett nevron til det opprinnelig betraktede nevrale nettverket. Alt vil se likt ut, bare et ekstra subskript vil bli lagt til, som gjenspeiler nummeret på nevronet inne i laget, og vektene vil ha doble abonnenter, for eksempel jk, som gjenspeiler forbindelsen til nevron j fra ett lag L med et annet nevron k i lag L-1.

De endelige derivatene gir de nødvendige komponentene for å bestemme komponentene i ∇C-gradienten.

Du kan øve på den beskrevne siffergjenkjenningsoppgaven ved å bruke treningsrepositoriet på GitHub og det nevnte MNIST-siffergjenkjenningsdatasettet.