Kategori Projektuppdatering

Lita på metoden

Du ska kunna lita på metoden, men var lite vaksam på utfallet. Så skulle jag kortfattat vilja beskriva vad konfidensintervall handlar om. Idag är det detta som ligger på bordet.

I måndags skrev jag om centrala gränsvärdessatsen. Den handlade om att fördelningen av medelvärden närmade sig en normalfördelning när man tog tillräckligt stort urval. Det handlar alltså inte specifikt om enskilda värden, utan medelvärdet. I en population med en höger-skev fördelning skulle medelvärdet kunna vara 10. Om vi tar tillräckligt stort urval ur populationen och kontrollerar medelvärdena i den skulle de fördela sig runt 10 på sådant sätt att det är att betrakta som en normalfördelning.

Sedan tidigare kommer vi ihåg sannolikhetsfördelningen runt medelvärdet i en normalkurva som arean under kurvan baserat på standardavvikelse. Det var den kända 68-95-90.7%-regeln som jag skrev om förra gången. Om jag vill säga något om medelvärdet i populationen baserat på mitt urval (det som även kallas statistisk inferens) så säger regeln att jag kan ta medelvärdet och subtrahera och addera standardavvikelse (vilket ger en felmarginal) för att få fram ett intervall. Intervallet ger då en viss felmarginal – som blir större ju större del av befolkningen jag vill täcka. En vanlig andel att vilja täcka är 95%. Detta motsvarar 2 standardavvikelser. Om vi bygger vidare på exemplet ovan så säger vi att vi har en standardavvikelse på 1,5. Vi tar detta värde och multiplicerar med 2 standardavvikelser; detta ger oss en felmarginal på +/-3. Då har vi ett lägre värde på 7 och ett högre värde på 13. Detta är ett intervall som täcker 95% av populationen.

Vi kan nu säga att vi med en konfidensnivå på 95% har ett medelvärde inom 7-13, baserat på vårat urval. Det innebär inte att utfallet med 95% sannolikhet är korrekt; det betyder att metoden i 95% av fallen ger ett medelvärde som faller inom intervallet.

Det om konfidensintervall. På fredag ska jag berätta om vad som händer när vi inte vet standardavvikelsen i populationen utan måste uppskatta den. Det blir ju kul!

Och så vill jag bara säga något om programmering. Igår kväll satt jag och programmerade lite på Bokarenan. Jag höll på att skriva funktioner som motsvarade URI-vägar (typ URL) men det var hela tiden fel funktion som fångade en URI. Jag angav /utforska/bok/ny och en funktion för att skapa en ny bok skulle fånga detta, men istället så var det en funktion för att presentera en enskild bok som fångade anropet. Den funktionen hade till uppgift att fånga /utforska/bok/{id}. Men jag förstod först inte att det var detta som var problemet för det som jag fick till felmeddelande var att applikationen inte kunde hitta något bokobjekt. Jag googlade efter problemet och hittade på stackoverflow att problemet kunde ha att göra med i vilken ordning som funktionerna låg i. Liksom när man har en switch-struktur som avslutar med en generisk defaultcase så ska man tänka på att ha de mer generiska URI:erna längre ned i strukturen. Så jag fixade problemet genom att helt enkelt flytta ena funktionen över den andra!

Vi ses på fredag!


Centrala gränsvärdessatsen

Äntligen en ny vecka! Jag har kommit ut på andra sidan av denna helg där jag mest suttit och slipat på Bokarenan. Jag kände att jag hade den tiden över efter att ha gjort en del plugg under den gångna veckan. Mycket tid har gått åt att slipa på CSS och skapa rimliga views (sidor) för de entiteter jag vill presentera. Jag har upplevt det som enklare att ha koll på vad jag skapar och var jag har det, nu när jag skapar mina views manuellt, istället för att låta Symfony skapa dem åt mig. De views som Symfony skapade var i klass med att sitta med phpMyAdmin, men mer begränsad. Så de färdigbakade sidorna motsvarade inte de syften jag hade med dem. Och jag börjar gilla vart åt det barkar.

För närvarande ser sidan ut som nedan. Jag har avvikit lite från hur jag hade skissat den i Adobe XD och gjort den generellt lite ljusare.

Men nog om programmeringen. Denna vecka fortsätter jag med statistik. Denna gång om centrala gränsvärdessatsen.

I förra veckan beskrev jag normalfördelning och hur bra det var att ha en sådan modell. Kortfattat så innebär det att man enkelt kan uppskatta fördelning av befolkning utifrån hur långt från medelvärdet man kollar baserat på standardavvikelse. Denna vecka säger jag att man kommer få en normalfördelning om man tar tillräckligt stora samplar (urval), i princip oavsett hur den verkliga populationen ser ut. Och det är inte helt negativt! Det man vill göra med att ta stora samplar är att komma så nära det verkliga medelvärdet som möjligt med så liten standardavvikelse som möjligt. Om man lyckas med det så har man fått ett urval som har ett medelvärde som ligger där det riktiga medelvärdet ligger, med liten felmarginal.

I sitt urval kommer man ha en standardavvikelse. Och om man vill säga något om 95% av populationen så fångas de inom 2 standardavvikelser från medelvärdet. Detta har jag skrivit om i förra veckan som 68-95-99.7% regeln. Så om standardavvikelsen är stor så kommer det intervall som beskriver 95% av populationen att vara stor. Förhållandet mellan populationens standardavvikelse och urvalets standardavvikelse är s = σ/(√n), där n är urvalsstorlek. Det innebär att man minskar standardavvikelsen med roten ur sampelstorlekens förändring. Vill man halvera standardavvikelsen så får man fyrdubbla urvalsstorleken.

Nästa gång ska jag skriva något om konfidensintervall. Jag misstänker att vi redan har börjat fila på det, men jag får återkomma när jag läst lite om saken.


Standardiserad fredag

Idag ska jag låta avsluta den ”normala veckan” med standardiserade värden. Vad är ett standardiserat värde? Vad är egentligen poängen med att standardisera värden? Hur standardiserar man värden? Detta kommer jag gå igenom idag.

Ett standardiserat värde är egentligen ett mått på hur långt ifrån ett medelvärde en datapunkt är. Som mått används standardavvikelsen. Det standardiserade värdet representeras av z. Och som jag skrev om förra gången så representeras standardavvikelsen av σ [lilla sigma]. I bilden nedan så har jag ritat in σ och ett standardiserat värde med 1,25.

Vad är då poängen med standardiserade värden? Vad jag vet i skrivande stund så finns det två poänger.

För det första så kan man jämföra olika standardiserade mått med varandra. Som jag har fått förklarat för mig så har man i USA två stora antagningsprov till högre studier: ACT och SAT. De har olika skalor men kan vara angelägna att jämföra mellan. Säg att Emily har fått 650 på SAT-provet, och Michael har fått 28 på ACT. Vem av dem har större anspråk på att komma in på samma kurs om man kan anta att ACT och SAT är likvärdiga test på kunskapsnivå. Genom att standardisera värdena så får jag fram att Emilys z-värde är 1 och Michael är 1,67. Michael har alltså högre poäng om man skulle jämföra dem. Vad det innebär är att en mindre andel av alla som skriver proven har fått så höga poäng som Michael jämfört med Emily. Men det innebär inte att Emily har dåliga poäng. Faktum är att hon har bättre poäng än 84% av alla som tar samma prov. Och då kommer vi till den andra poängen.

För det andra så kan man med hjälp av standardiserade värden av en normalfördelning få fram andelar av en population.

Det är svårt att använda ögonmått för att uppskatta andel av befolkningen som har lägre poäng än Emily. Men med hjälp av z-värde och en tabell över standardiserad normal sannolikhet så kan man få fram andelen. Om man skulle kontrollera hur stor andel av befolkningen som fått poäng som varit mindre än det standardiserade värdet av 0, så kan man se att det delar befolkningen i hälften.

Det om standardiserade värden!

Jag vill också nämna något om Bokarenan. Projektet har löpt på när jag inte orkat läsa kursboken och tid funnits över. Jag har inte gillat hur svårt det varit för mig att navigera mellan relevanta Controllers och views. Jag har heller inte gillat att jag låtit skapa så många views för varje liten entitet. Det kan finnas poänger för det när man vill underhålla vilka entiteter man har. Men jag tycker att det mest har tagit upp massa plats och inte haft någon rimlig logik till sig. Jag har därför tänkt ta bort dem som inte används, och när jag upptäcker att jag behöver dem så skapar jag dem efter mina behov.

Ytterligare så har jag förfinat layouten, men det har jag skrivit lite om tidigare. Men alla dessa åtgärder har inneburit att ganska mycket kod har flyttats runt. Jag tog en liten bild av hur många förändringar det inneburit i Git:

Och till sist vill jag avsluta med lite fredagskänsla: spel! Den gångna veckan har min dotter upptäckt glädjen med att skjuta upp raketer i Kerbal Space Program, och så har också jag. Jag kommer sitta och bygga små dynamitstycken och hoppas att mina små gröna gubbar kan landa säkert någonstans. Jag har lyckats få mina explosioner att smälla i ungefär rätt riktningar, men ännu så har jag inte lyckats flyga ett varv runt planeten. Vi får se vem som först lyckas; jag eller dottern.

Trevlig helg, allihopa!


Dubbla saker hälften så snabbt

Denna veckan har jag fortsatt med statistik och programmering. Det blir alltså dubbelt upp mot vad jag gör i vanliga fall. Men det har inneburit att det gått lite långsammare på båda hållen.

I helgen kommer jag göra klart den första delen av statistikkursen. Det innebär att jag gör en liten quiz om de huvudsakliga beståndsdelarna i en statistisk undersökning.

Så länge jag inte hoppar över viktiga delar eller ger upp så kan jag bara fortsätta öka mina kunskaper. Det är som med programmeringen. Jag tror att det är sunt (för det är ju roligt också) att jag fortsätter med den när jag har lite tid över. Om jag kan slutföra den initiala och levererbara delen av Bokarenan så kan jag fortsätta lägga till funktioner till den, där ibland hoppas jag kunna göra lite statistiska analyser av underlaget. Till exempel så skulle det vara lite intressant kuriosa att se vilka ord som är vanliga för att beskriva thrillers jämfört med romantikromaner.

Så denna helg kommer jag jonglera begrepp så som normalfördelning, obundet slumpmässig urval, kvartiler, median, standardavvikelse, outlier, lådagram, statistiskt signifikant, och så vidare.

Denna helg kommer jag även ägna No Man’s Sky lite uppmärksamhet. Det är ganska mysigt, men jag vet inte hur mycket längre jag kommer hinna i spelet. Jag har hunnit komma till en anomali och träffat på andra spelare där. Hux flux så började en spelare ge mig en massa saker. Det bara dök upp bland min packning. Och det visade sig vara värt ungefär 20ggr av vad jag hade tjänat så långt. Så det var väldigt roligt att få den extra skjutsen just som jag höll på att visa systersonen vad spelet gick ut på. Men ikväll har jag lovat min äldsta dotter att vi ska skjuta upp lite raketer i spelet Kerbal Space Program. Vi får se om vi lyckas lämna atmosfären.

Trevlig helg, allihopa!


Block 1 och lite annat

Denna vecka kommer jag avsluta första delen på den statistikkurs jag går. Jag kommer då att ha gått igenom grundläggande begrepp vad gäller undersökningsmetodik och deskription.

Ett av de grundläggande koncepten man måste ha koll på är samband. Bara för att där finns ett samband så behöver det inte betyda att en variabel orsakar ett visst utfall. Och finns ett orsakssamband så måste man ha koll på vad som orsakar ett utfall. Ett enkelt exempel på detta är att man skulle kunna se ett samband mellan glassförsäljning och soligt väder. Det är ju inte att glassförsäljningen går bra som orsakar soligt väder! Sedan kan man se att när glassförsäljning går bra är det också många som badar. Men det är inte glassförsäljning som gör att folk badar. Det råkar bara sammanfalla med att det är soligt väder. Så de korrelerar med varandra.

Jag kommer börja använda ett open-source program denna vecka för att göra statistiska analyser. Det heter Jamovi. Jag kommer använda det för att göra lite övningsuppgifter.

I helgen så har jag inte ägnat någon tid till statistik, så det blir mer av det i veckan. Nej, snarare så har jag ägnat tid till programmering, eller snarare web design. Jag har efter lite fram och tillbaka med css och visat sambon kommit fram till att jag först behöver en målbild innan jag sitter och prövar olika färger och css-funktioner. Så istället har jag suttit med Adobe XD och tagit fram ett koncept. Det tog ett tag men jag gillar färgerna och presentationen som jag fått fram.

Så när jag eventuellt får lite tid över efter bebisar och statistik så kommer jag köra lite CSS med lite grid och flex.


Sökfunktion och DQL

Denna veckan blir antagligen den sista på ett tag med uppdateringar om Bokarenan och programmering. Jag påbörjar en kurs om statistik och kommer använda Femte Arenan för att beskriva de lärdomar jag drar av det. Så jag passar på att beskriva det senaste jag gjort i programmeringsväg över helgen.

Jag lämnade förra veckan med en fundering på om jag skulle hinna få på plats en sökfunktion. När jag gjorde en sökfunktion till den nuvarande Bokarenan så svalde jag efter för mycket. Jag gjorde så att användaren kunde söka efter varje detalj i varje liten entitet. Det gjorde sökfunktionen lite svår att använda. Istället har jag gjort sökfunktionen till ett textfält som alltid finns tillhands i navigationsfältet och det man söker efter är BÖCKER. Jag har för närvarande gjort så att man kan söka efter författare eller boktitel, men sökresultatet är alltid BÖCKER. Inte författare eller något annat. Jag är rätt nöjd med resultatet. Det var också rätt så enkelt att implementera med hjälp av Doctrine och dess queryBuilder.

Så efter att ha fått på plats sökfunktionen så kände jag att jag var på rull. Därnäst så implementerade jag ett navigationsträd för böcker. I navigationsfältet har användaren en länk som heter Böcker. Klickar man på den så kommer man till sida för att välja böcker enligt genrer. Genrer är uppbyggda hierarkiskt, så att till exempel thriller är en underkategori till skönlitteratur. Klickar man på Skönlitteratur så får man upp en ny lista på genrer inom skönlitteratur samt de populäraste böckerna associerade med genren skönlitteratur.

Implementeringen av genrer i kombination med lista på populära böcker innebar att jag hade att hantera tre olika entiteter: Book, BookAnalysis och Genre. Tidigare har jag helt enkelt använt den repository som var lämplig. Jag försökte mig på att använda repository för BookAnalysis med förhoppning att kunna använda den Book-referens som den entiteten har. Book har i sin tur referens till Genre-entitet. Jag vred och vände men fick inte till det. Jag hade några alternativ kvar, som tur var. Nuvarande Bokarena använder sig av SQL-kod som jag skrivit. Nackdelen med att använda det är att jag inte får tillbaka entitets-objekt, utan det är något som jag fått initialisera ”manuellt”. Men jag behöver inte göra på samma sätt här. Jag kan använda DQL (Doctrine Query Language) istället. Det innebär att jag blir lika flexibel som om jag skrev SQL men jag får fördelen med att få tillbaka de rätta entiteterna. Med följande sats så blev det inte så komplicerat trots allt:
"SELECT a FROM App\Entity\BookAnalysis a JOIN a.book b WHERE b.genre = $id ORDER BY a.numReviews DESC, a.avgRate DESC"

Ha en sån trevlig vecka. Nästa gång skriver jag om data i stora mängder.


Aktiveringsfredag

Denna vecka har jag alltså fortsatt med auktoriseringssystem för applikationen (Bokarenan). Framförallt har det handlat om att få till en aktiveringsfunktion, så att man inte kan registrera sig med någon annans epost. Kolla bara alla mina git-meddelanden:

Eftersom aktiveringsfunktionen inte är något som kommer som standard i Symfony så är det något som jag fått lägga till. Första steget var att justera användarentiteten (User) med två nya fält: aktiv, och en aktiveringssträng. Enligt standard så kommer en ny användare att registreras som icke-aktiv. I det andra steget så kontrolleras att den användare som försöker logga in är aktiverad. Om användaren inte är aktiv så kan den inte logga in. För att ändra detta så kommer det tredje steget: applikationen har postat en aktiveringslänk till användarens epost. När användaren klickar på den så skickas två parametrar till applikationen, nämligen användarens epost och aktiveringssträngen. Dessa parametrar jämförs med data från applikationens databas. Om de överensstämmer så aktiveras användaren och denne kan därmed logga in.

Så här långt har det gått helt okej. Nästa uppgift blir att presentera recensioner på ett bra sätt. Jag tänker mig att förstasidan ska innehålla en utvald recension. Ytterligare ska finnas en sida där man kan se olika böcker, samt hur många recensioner de har. Klickar man på boken så kommer recensionerna upp. Detta blir nästa veckas uppgift.

Eftersom det nu är fredag så skulle jag vilja göra en nöjesrekommendation, och detta i form av Playstation 4-spelet Horizon: Zero Dawn. Spelet bjuder på en värld där människor lever som nomader och jagar robot-dinosaurier. Det är fantastiskt vackert och mycket underhållande. Man får vara kreativ i hur man tar ned robotarna. Större bestar kräver att man sätter upp fällor eller skjuter av deras kanoner så att man själv kan använda dem. Mindre bestar kan det räcka med att man smyger sig inpå dem och överfaller (eller omprogrammerar). Liksom det spel jag körde igenom förra veckan så finns en hel uppsjö av bakgrundsstory att hitta. Varför finns alla dessa robotar? Varför lever folk som nomader? Jag har haft väldigt roligt med spelet och ser verkligen fram emot en fortsättning.

En Watcher från Horizon: Zero Dawn

Trevlig helg, allihopa!


Huvudet i kaklet

Visst heter det handen i kaklet, men man kanske inte alltid är så noga när man kör huvudet först mot en vägg. Min vägg är att få till ett smidigt sätt att lägga till en recension för en bok. Mitt dilemma är att jag har en databas som är beroende av att användare lägger till böcker. Så när en användare ska lägga till en recension så behöver användaren också lägga till en bok, och förlag, och förlagets hemvist, samt författare så klart. Det är så mycket som krävs av användaren. Detta kräver jag i den nuvarande versionen av Bokarenan, och kommer också göra det i den kommande versionen. I tredje versionen kan vi hoppas på att jag fått till en bra crawler som kan fixa det åt användarna. Men nu till den version jag för närvarande jobbar på.

Jag använder mig av Symfonys olika finesser för att göra mitt jobb enklare. Och visst har det gått väldigt smidigt att få till funktioner för att skapa, uppdatera och ta bort olika entiteter. Som jag skrev om i fredags så jobbar jag nu med att försöka få till ett enda formulär där användaren kan lägga till samtliga entiteter som är relevanta när en recension skapas. Jag har därför kombinerat olika färdiga formulär som Symfony skapat för respektive entitet. Slutresultatet från det är inte vackert eller särskilt användbart. Jag kommer försöka forma det så att det blir användbart, men jag börjar misstänka att allt mitt hoppande mellan olika guider skapar kunskapsluckor. Risken är att jag börjar förbise viktiga detaljer, eller kanske skapar en applikation som är svår att underhålla.

Som jag försökt illustrera ovan, jag har lite svårt att sluta cirkeln, och när jag kommer av mig kan det lätt bli att jag gör en röd räv, eller en egen implementering som ingen annan förstår. Inte ens jag själv om 6 månader. Jag ska försöka använda Symfony och få till formuläret, men jag kommer följa en utökad handledning i Symfony så att min lata hjärna inte hoppar över några viktiga detaljer.


Flerformulärsfredag

Denna vecka har gått på temat flerformlär: det att kombinera flera formulär till ett. Och det har fungerat, på sätt och vis. Jag vill att man ska kunna lägga till alla detaljer när man ska skriva en recension för en bok. Då kommer alla olika entiteter blandas in: författare, förlag, bok och recension. Det är bara det att en bok kan ju ha flera författare, och som formuläret nu renderas kan man bara lägga till en författare. Användaren ska kunna lägga till fler fält om det rör sig om flera författare. I tidigare version av Bokarenan så renderades cirka sju fält, men bara ett fält visades. Användaren kunde klicka på en knapp för att lägga till ett fält (upp till max sju fält). Detta kanske jag kommer använda, men det är inte så stiligt. Fördelen är att detta kan användas utan att åberopa JavaScript. Det hela kan skötas med CSS. Kan bli att jag återvänder till den lösningen, men först ska jag försöka få det hela att fungera med JavaScript, för att på ett dynamiskt sätt kunna lägga till så många författare man själv önskar.

Det jag tycker funkat bra denna veckan är att flytta över logik från controller till en hjälp-klass som jag kallar EntityBasket. Denna klass är uppbyggd för att kunna plocka upp alla entiteter så som de preciserats i en formulärklass jag kallar EntityBasketType. EntyiBasket ges formulärdata när den initialiseras och kommer med följande metoder:

Samtliga metoder hämtar alltså en entitet och varje metod bygger på att de kallar metoden fetchEntity som ser ut såhär:

Det innebär att jag slipper upprepa kod, och det funkar helt okej. Det som återstår efter att jag fått formulär med att lägga till flera författare att funka är att interagera med databasen.

Så vill jag avsluta denna vecka och välkomna helgen med att konstatera att det inte blir många knop i huvudet när jag får så lite sömn. Tvillingarna kommer till ro ganska sent på kvällen och tillbringar gärna halva natten på mitt bröst. Till tröst har jag haft några riktigt läckra upptäckter i Elite Dangerous. Jag har äntligen blivit först att upptäcka en planet, men det finns ju miljarder av solsystem så någon gång skulle det ju ske. Men sen så upptäckte jag en riktigt konstig klippformation på planeten. Det såg ut som en gigantisk blomma och runt omkring den fanns ”organiska mineraler”. Jag verkar ha upptäckt något utomjordiskt. Om jag landsatte min rover och körde nära blomman så slutade viss elektronik i rovern att funka. Det var lite skrämmande och jag stack så snart jag hade tagit några prover. Jag kommer bege mig tillbaka dit igen i helgen och se om jag får fler prover med mig.

Trevlig helg, allihop!


getData funkade!

Från föregående inlägg så undrade jag om det rätta sättet att komma åt rätt värden från formuläret var att använda Request-objektet eller Form-objektet. I andra projekt hade jag använt ”superglobala” variabler för att komma åt formulär-värden. Då hade jag använt $__POST[”book_name”]. I Symfony finns dessa värden i Request-objektet. Eller så var i alla fall min uppfattning. Men jag upptäckte att jag inte fick det resultat jag väntade för jag fick aldrig värdet från book_name. Därför blev det att jag vände mig till googling:

Det blev helt enkelt ganska många fönster när jag försökte hitta svar på mina funderingar. Jag kollade i Symfonys guider, dess github-sida, PHP:s officiella sida, och så klart Stack Overflow. Jag fick inte riktigt svar på varför det inte funkade att använda Request-objektet. Men däremot fann jag lösningen! Jag kunde använda Form-objektet. Genom $form->getData() så kunde jag extrahera ett bok-objekt. Och därmed kunde jag få detta enkla resultat och jag kände mig så lättad:

Book is set. It's title is Testing.