Når vi ser på metoderne til at oprette brugerdefinerede miljøer i MATLAB, som vi tidligere nævnte i sektion 9.6.3, er der tre metoder til rådighed, som tillader brugeren at skabe forskellige typer af tilpassede miljøer. I denne sektion fokuserer vi på at bruge den såkaldte "template class"-metode for at generere et brugerdefineret miljø. Sammenlignet med den første metode, hvor man definerer et brugerdefineret miljø gennem en funktion, giver template class-metoden større fleksibilitet og mulighed for at bygge mere komplekse miljøer.

For at gøre tingene lettere og mere overskuelige, vælger vi at bygge vores miljø omkring et simpelt DC-motor system, som vil blive brugt som mål til at udvikle miljøet via template class-metoden. En template class i MATLAB betyder, at systemet leverer en grundmodel, som brugeren kan tilpasse ved at udfylde de nødvendige felter i skabelonen for at skabe et ønsket miljø. Dette giver brugeren frihed til at definere et brugerdefineret forstærkende læringsmiljø ved at oprette og ændre en template class.

Template class-metoden gør det muligt at:

  • Implementere mere komplekse dynamikker i miljøet.

  • Tilføje brugerdefinerede visualiseringer i miljøet.

  • Skabe grænseflader til tredjepartsbiblioteker defineret i sprog som C++, Java eller Python.

MATLABs standard template class inkluderer en simpel model for en cart-pole balance, som kan ses i sektion 9.6.2.1. Denne template class består af tre hoveddele med foruddefineret kode, der beskriver en cart-pole model:

  1. Miljøets egenskaber

  2. Nødvendige metoder for miljøet

  3. Valgfri metoder for miljøet

Den første del, miljøets egenskaber, bruges til at erklære de fysiske konstanter, variabler, og miljøbegrænsninger. De nødvendige metoder er dem, som brugeren skal definere for at sikre de grundlæggende funktioner, der gør miljøet operationelt. De valgfri metoder er ikke nødvendige, men de anbefales stærkt, da de kan hjælpe med at gøre udviklingsprocessen mere strømlinet.

Tre af de vigtigste nødvendige metoder, nemlig reset(), step() og konstruktøren, er alle obligatoriske. De øvrige metoder er valgfri. MATLAB leverer funktionen rlCreateEnvTemplate(), som gør det muligt at oprette et template objekt baseret på denne klasse. For at oprette et brugerdefineret miljø, skal du først åbne MATLAB og indtaste kommandoen rlCreateEnvTemplate("motor_template_env"). Dette skaber en skabelon, som vi derefter kan tilpasse til vores eget system.

Når vi har oprettet skabelonen og åbnet den, finder vi den oprindelige kode, som vi skal ændre for at tilpasse miljøet til vores specifikationer. I første omgang skal vi kigge på den del, der beskriver miljøets egenskaber.

Miljøets egenskaber

I den oprindelige template vil vi finde en del, der definerer miljøets egenskaber. Her vil vi erstatte de eksisterende værdier med vores egne. For eksempel kan vi definere et system, der styrer en DC-motor:

matlab
classdef motor_template_env < rl.env.MATLABEnvironment %% Egenskaber (definer egenskaber for systemet) properties MaxSpeed = 50; % Maksimal hastighed i RPM Ts = 0.02; % Tidsinterval for sampling (20 ms)
AngleThreshold = 2 * pi / 180; % Tolereret vinkelfejl (2 grader)
RewardNormalMotor =
1; % Belønning for korrekt motorrotation PenaltyErrorMotor = -1; % Straf for fejl i rotation end % Systemets tilstand (motorens vinkel og hastighed) State = zeros(2, 1) IsDone = false end

I denne kode definerer vi blandt andet, at motorens maksimale hastighed er 50 RPM, og at systemet tolererer en rotationsvinkelfejl på 2 grader. Desuden er der belønninger og straffe knyttet til, om motoren kører normalt eller fejler.

Nødvendige metoder

De nødvendige metoder omfatter primært reset(), step(), og konstruktøren, som definerer, hvordan miljøet initieres og hvordan det opfører sig over tid. For eksempel skal step()-metoden beskrive, hvordan miljøet reagerer på en given handling, mens reset() sørger for at nulstille miljøet til sin oprindelige tilstand.

I vores eksempel skal vi definere en metode, som opretter miljøets observationer og handlinger:

matlab
methods
function this = motor_template_env() % Initialiser observationer ObservationInfo = rlNumericSpec([2 1]); ObsInfo.Name = "Motor States"; ObsInfo.Description = 'theta, dtheta'; % Motorens vinkel og hastighed % Initialiser handlinger ActInfo = rlFiniteSetSpec([-50 50]); ActInfo.Name = "Motor Action"; % Kalder den overordnede MATLABEnvironment konstruktor this = [email protected](ObservationInfo, ActInfo); end end

Her opretter vi specifikationer for både observationer og handlinger. Observationerne beskriver motorens vinkel (theta) og hastigheden (dtheta), mens handlingerne er defineret som en endelig mængde af værdier (fra -50 til 50 RPM).

Hvad er vigtigt at forstå?

Det er vigtigt at forstå, at den tilpassede template class-metode giver en omfattende fleksibilitet, men kræver, at brugeren har en god forståelse af både den underliggende systemdynamik og de metoder, der er nødvendige for at få miljøet til at fungere korrekt. Dette betyder, at man skal være opmærksom på de fysiske egenskaber, der påvirker motorens adfærd, som eksempelvis maksimal hastighed og tolererede fejl. Desuden skal man være klar til at implementere yderligere metoder for at skabe et effektivt læringsmiljø.

For at udnytte template class-metoden fuldt ud, er det også vigtigt at forstå, hvordan de forskellige MATLAB-funktioner, som rlNumericSpec() og rlFiniteSetSpec(), arbejder sammen for at definere et miljø, der både kan observere og reagere på motorens tilstande og handlinger.

Ved at bruge denne metode kan man skabe et fleksibelt og tilpasset forstærkende læringsmiljø, som gør det muligt at eksperimentere med og optimere forskellige aspekter af systemet. Det åbner op for mange muligheder, men det kræver, at man sætter sig grundigt ind i de tekniske detaljer.

Hvordan kan vi teste og sammenligne klassifikationsmodeller ved hjælp af Diabetes-datasæt?

For at vurdere effektiviteten af forskellige klassifikationsalgoritmer skal de trænede modeller testes med testdata. Dette indebærer at sammenligne de virkelige etiketter med de forudsagte etiketter. Lad os kigge nærmere på, hvordan dette kan gøres ved hjælp af et Diabetes-datasæt og en række forskellige algoritmer.

Først skal vi hente Diabetes-datasættet og oprette det som en tabel T. Herefter opdeler vi datasættet i to dele: de første 668 rækker bruges som træningsdata (repræsenteret ved M), og de sidste 100 rækker bruges som testdata (repræsenteret ved N). På dette stadie separeres de første otte kolonner i datasættet som prædiktordata, som derefter tildeles den lokale variabel X. Den sidste kolonne, der repræsenterer udfaldet (Outcome), bliver tildelt variablen Y, som en vektor på 688×1.

Testdataene for output eller svarvariablen tildeles variablen TLabel, og denne vektor anvendes senere til testformål. På dette tidspunkt er det muligt at bruge flere klassifikationsmetoder for at analysere og forudsige resultaterne baseret på træningsdataene.

Ved at benytte funktionen fitclinear() kan vi træne en binær lineær model, mdl_1. Når modellen er trænet, kan vi derefter anvende testdataene (XX) til at forudsige labels (label1), som er en binær vektor med værdierne 0 og 1. For at visualisere resultaterne kan vi anvende en forvirringsgraf, som kan hjælpe os med at vurdere modellens præstation ved at sammenligne de forudsagte labels med de faktiske testlabels. Funktionen plotConfChart() bruges til at generere disse grafikker.

Derudover kan vi bruge andre klassifikationsmetoder som Kernel-kalssifikatoren (fitckernel()), SVM (fitcsvm()) og KNN (fitcknn()). Hver af disse funktioner bruges til at træne modeller baseret på prædiktordata og derefter forudsige output ved hjælp af testdataene. For hver metode skabes en forvirringsgraf, der giver et visuelt billede af klassifikationen, og giver mulighed for at sammenligne præstationen af de forskellige modeller.

Ved at implementere fitckernel() trænes en Kernel-baseret model mdl_2, mens SVM-algoritmen anvender fitcsvm() for at skabe en model mdl_3. KNN-algoritmen anvender fitcknn() til at skabe mdl_4. Efter at have trænet hver af modellerne kan vi igen bruge testdataene til at forudsige labels og analysere resultaterne ved hjælp af forvirringsgrafer.

Når resultaterne af de forskellige klassifikationsmodeller er visualiseret, vil det typisk vise, at SVM-algoritmen giver den bedste præstation, mens KNN-algoritmen har de dårligste resultater. De lineære og kernel-baserede klassifikatorer ligger et sted imellem, men den lineære model præsterer ofte bedre.

Det er også vigtigt at forstå, at mens forvirringsgrafer giver et nyttigt værktøj til at vurdere præcisionen af forskellige modeller, er der andre metoder og metrikker, der kan bruges til at analysere klassifikationsresultater. Blandt disse metoder findes præcisions- og tilbagekaldelsesmål, F1-score og ROC-kurver. Forvirringsgrafer er kun én dimension af evalueringen, og det er ofte nyttigt at supplere denne analyse med yderligere metrikker for at få et mere fuldstændigt billede af modellens præstation.

Endelig, når du arbejder med datasæt som Diabetes-datasættet, skal du altid overveje mulighederne for at justere modellerne og finjustere hyperparametre for at opnå bedre resultater. Dette kan indebære at prøve forskellige klyngealgoritmer, ændre dataforbehandlingsteknikker eller justere læringsparametre i algoritmerne. Selv små justeringer kan have en stor indvirkning på den endelige præstation af modellen.

Hvordan bruge fitglm() og TreeBagger() til binær klassifikation med diabetesdata

For at udføre en binær klassifikation med diabetesdata kan man benytte sig af forskellige maskinlæringsmetoder. To sådanne metoder er fitglm()-funktionen og TreeBagger()-funktionen, som begge anvender henholdsvis generaliserede lineære modeller og random forest-algoritmer. I denne sektion gennemgår vi, hvordan disse funktioner fungerer og hvordan de kan anvendes på et diabetes-datasæt for at forudsige, om en person er diabetiker eller ej.

Først starter vi med at se på hvordan fitglm() kan anvendes til at træne en model. Opret en ny scriptfil og indtast koden vist i Fig. 6.15 i filen, der gemmes som Diabetes_fitglm_Func.m.

Først importeres diabetesdataene fra en CSV-fil. Herefter opdeles dataene i træningsdata (668 prøver) og testdata (100 prøver). De relevante funktioner, såsom graviditeter, glukose, blodtryk, hudtykkelse, insulin, BMI, diabetes-pedigreefunktion og alder, udtrækkes som prediktorer, mens udgangen (diabetes-status) fungerer som målvariabel. Derefter anvendes fitglm()-funktionen til at træne modellen med disse data.

Efter træning af modellen anvendes predict()-funktionen til at lave forudsigelser for testdataene. Forudsigelserne omdannes til binære værdier, hvor værdier over eller lig med 0,5 tildeles label 1 (diabetes), og værdier under 0,5 tildeles label 0 (ikke-diabetes). Resultaterne sammenlignes med de faktiske testværdier, og en forvirringsmatrix vises for at visualisere præstationen af modellen.

Som vist i Fig. 6.16a og 6.16b, kan vi konstatere, at resultatet af fitglm()-klassifikationen er meget tæt på det, vi ville få med support vector machine (SVM)-algoritmen. Denne model er effektiv, men der er flere andre tilgange, som også kan være relevante i bestemte sammenhænge.

Den næste metode, vi ser på, er TreeBagger(), som er en implementering af random forest-algoritmen. Denne metode er især nyttig, når man ønsker at bruge en ensemblemetode, hvor flere beslutningstræer trænes og kombineres for at forbedre præcisionen. Denne metode benytter sig af træning med bagging, som skaber flere træer og anvender dem til at lave en samlet forudsigelse.

For at anvende TreeBagger() skal man følge en lignende tilgang som med fitglm(), men denne gang træner vi modellen med et antal beslutningstræer (100 træer i dette eksempel). Dataene indlæses på samme måde som før, og vi anvender TreeBagger()-funktionen til at træne en model, som derefter bruges til at lave forudsigelser for testdataene. Forudsigelserne skal konverteres fra en strengarray til et numerisk array med str2double()-funktionen, da TreeBagger() returnerer strenge, ikke numeriske værdier.

Resultaterne kan derefter vises på en sammenligningsgraf og en forvirringsmatrix, som illustreret i Fig. 6.18a og 6.18b. Det er tydeligt, at resultatet fra TreeBagger() også giver en god præstation, og det kan være et nyttigt alternativ til fitglm() i visse scenarier.

I begge tilfælde er det vigtigt at forstå, at klassifikationer ikke kun handler om at opnå høj nøjagtighed på testdataene, men også om at vurdere, hvordan modellerne fungerer i forhold til virkelige scenarier, som kan indebære variation og støj i dataene. Modeller som fitglm() og TreeBagger() kræver nøje opmærksomhed på forudbehandling af data, valg af relevante funktioner og fortolkning af resultaterne for at sikre, at de leverer meningsfulde og anvendelige forudsigelser.

I betragtning af disse metoder bør læseren være opmærksom på vigtigheden af at forstå de grundlæggende principper bag hver algoritme og hvordan de kan justeres for at håndtere forskellige typer af data og klassifikationsproblemer. Det er også afgørende at være opmærksom på eventuelle overfitting-problemer, især når man bruger modeller som random forest, som kan være tilbøjelige til at tilpasse sig støj i dataene, hvis ikke de er ordentligt reguleret.

Det er også nyttigt at forstå, at selv om binær klassifikation er et kraftfuldt værktøj til at skelne mellem to kategorier (som diabetiker og ikke-diabetiker), kan disse modeller også anvendes til mere komplekse klassifikationsproblemer, hvor der er flere kategorier at overveje.

Hvordan fungerer SURF og andre funktioner til billedklassifikation?

SURF (Speeded-Up Robust Features) er en kraftfuld algoritme, der anvendes til at identificere interessante punkter i billeder. Den anvender en blob-detektor baseret på Hessian-matricen, hvor determinanten af denne matrix bruges som et mål for den lokale ændring omkring et givet punkt. Dette gør det muligt at vælge punkter, hvor denne determinant er maksimal. Hessian-matricen evalueres for et punkt p=(x,y)p = (x, y) i et billede II, og dens værdi på et givet skala σ\sigma kan udtrykkes ved hjælp af følgende formel:

H(p,σ)=(Lxx(p,σ)Lxy(p,σ)Lxy(p,σ)Lyy(p,σ))H(p, \sigma) = \begin{pmatrix} L_{xx}(p, \sigma) & L_{xy}(p, \sigma) \\ L_{xy}(p, \sigma) & L_{yy}(p, \sigma) \end{pmatrix}

Her er Lxx(p,σ)L_{xx}(p, \sigma) og de andre termer convolutioner af den anden afledte af en Gaussisk funktion med billedet I(x,y)I(x, y) ved punktet pp. Brug af en 9x9 boksfilter, som approksimerer en Gaussisk funktion med σ=1.2\sigma = 1.2, udgør det laveste niveau af blob-responskort.

I forbindelse med SURF bruges skalaafhængige punkter til at finde interessepunkter i et billede på forskellige skalaer. For at muliggøre denne skala-afhængighed anvender SURF en skala-rum, der er opdelt i oktaver, hvor et oktav refererer til en serie af responskort, der dækker en fordobling af skalaen. I SURF bliver skala-rummet genereret ved at anvende boksfiltre af forskellige størrelser på billedet.

De første lag i skala-rummet opnås ved at filtrere billedet med en 9x9 filter, og efterfølgende lag opnås ved gradvist at øge filterstørrelsen. For eksempel anvendes filterstørrelserne 9x9, 15x15, 21x21, 27x27 osv. til at generere de næste lag i skala-rummet. I processen anvendes ikke-maksimum undertrykkelse over et 3x3x3-nabolag for at lokalisere de mest markante interessepunkter i både billede- og skala-rummet. Maksima af Hessian-matricens determinant interpoleres derefter i både skala- og billede-rummet for at finde præcise interessepunkter.

En alternativ metode, der anvendes i billedklassifikation, er den lokale binære mønster (LBP) funktion. LBP er en visuelt beskrivende teknik, der skaber en funktionel vektor ved at sammenligne hver pixel med sine naboer i et bestemt mønster. Dette mønster, der består af et binært tal, dannes ved at sammenligne centrumpixelens værdi med dens 8 naboer i en cirkulær struktur. Denne proces giver en 256-dimensional funktionel vektor, som derefter kan bruges i maskinlæringsalgoritmer som f.eks. SVM (Support Vector Machine) til at klassificere billeder baseret på tekstur eller ansigtsgenkendelse.

En anden metode, der bruges i billedklassifikation, er "Bag of Features" (BOF) eller "Bag of Visual Words" (BoVW). Denne metode opdeler et billede i en samling af uafhængige funktioner, kaldet nøgler, der kan repræsentere vigtige træk som farve, intensitet og lysstyrke. Nøglepunkterne i billedet identificeres, og hver af disse punkter får tildelt en beskrivelse via et deskriptør. Disse deskriptorer grupperes ved hjælp af klyngealgoritmer til at skabe et ordforråd, hvorefter histogrammer genereres baseret på antallet af forekomster af hvert "ord" i billedet. Disse histogrammer bruges til at finde lignende billeder eller forudsige kategori-klassifikationen af billedet.

For at træne klassifikatoren kan man anvende en algoritme som ECOC (Error-Correcting Output Codes) i MATLAB, som muliggør flerklasseklassifikation ved hjælp af flere binære klassifikationer. ECOC-rammen gør det muligt at opbygge et system til at klassificere billeder i flere kategorier baseret på de eksterne funktioner, der er ekstraheret fra billederne. Når en model er trænet, kan den bruges til at klassificere billeder i bestemte kategorier som for eksempel forskellige typer frugter.

Det er vigtigt at forstå, at ikke alle billedklassifikationsmetoder er ens, og valget af metode afhænger af problemets art og de krav, man har til hastighed og nøjagtighed. SURF og LBP fungerer godt til detektion af nøglepunkter og mønstre i billeder, men de kræver ofte en betydelig beregningskraft. BOF-metoden giver en mere robust tilgang til billedklassifikation ved at analysere billedet som en samling af funktioner, men dette kan kræve en mere kompleks opbygning af ordforråd og træning af klassifikatoren.

For læseren er det også væsentligt at overveje de teknologiske krav, der stilles for at implementere disse metoder effektivt. Billedklassifikation i realtidsapplikationer kræver ofte optimering af algoritmer og udnyttelse af moderne hardware som GPU'er for at kunne behandle store datamængder hurtigt.