Obligatorisk innlevering uke 3, alternativt oblig-l?p
Frist for innlevering: 12.09. kl 23:59
Sp?rsm?l eller kommentarer til oppgaveteksten sendes til ivargry@ifi.uio.no.
L?ringsm?l
- Du skal ha forst?tt hvordan du kan holde styr p? mange verdier ved hjelp av forskjellige samlinger (lister, mengder og ordb?ker).
- Du skal vite at samlingene representeres av objekter som tilbyr tjenester i programmet.
- I tillegg skal du vise at du kan skrive litt mer komplekse programmer med kunnskapene du har tilegnet deg de siste ukene.
Introduksjon
I denne oppgaven skal vi fors?ke ? avgj?re hvorvidt en person kommer til ? klare ? nedbetale et l?n eller ikke. Dette skal vi gj?re basert p? enkel informasjon om personen, slik som alder, kj?nn, utdanningsniv?, hvor mye gjeld personen har og historikk over tidligere gjeld. Vi skal se at vi enklere kan holde orden p? informasjon om disse personene ved hjelp av lister, og at ordb?ker kan gj?re oppslag av informasjon enklere.
Basert p? informasjon om en person er det selvsagt ikke mulig ? vite helt sikkert om en person kommer til ? betale gjelden sin eller ikke, men vi kan forutsi det med en viss n?yaktighet. Dersom du ?nsker kan du delta i en valgfri konkurranser der programmet du leverer blir kj?rt p? 30 000 tilfeller, hvor du f?r feedback p? hvor h?y treffsikkerhet det hadde p? dette datasettet. Blant de som deltar k?rer vi en vinner blant de som hadde h?yest treffsikkerhet. H?y treffsikkerhet er ikke noe krav for ? best? innleveringen.
Innleveringen er delt inn i flere deloppgaver, og for hver oppgave vil du gradvis forbedre prediksjonen. Den valgfrie oppgaven der du lager en egen prediksjon som blir kj?rt p? 30 000 individer kommer helt til slutt.
Oppgave 1: Hente inn alder, kj?nn, sivilstatus og gjeld.
Filnavn: enkel_prediksjon.py
Lag en prosedyre enkel_prediksjon
som henter inn alder, kj?nn, sivilstatus og mengde gjeld (i kroner) til en person (ved hjelp av input
).
Lagre denne informasjonen i passende variabler.
- Kj?nn vil v?re enten tekststrengen “mann” eller “kvinne”, og alder vil v?re et tall.
- Sivilstatus er for enkelhets skyld enten “gift” eller “singel”.
Print en setning som beskriver personen basert p? denne informasjonen. Eksempel: "Du er en singel mann p? 30 ?r med 100 000 kr i gjeld".
Kall prosedyren en gang og test at den fungerer, dvs. at den skriver ut informasjonen som brukeren gir p? rett m?te.
Oppgave 2: Enkel prediksjon basert p? alder, kj?nn sivilstatus og gjeld
Filnavn: enkel_prediksjon.py
Vi ?nsker n? ? skrive et lite program som pr?ver ? predikere om personen vil betale gjelde sin eller ikke.
Vi antar f?lgende:
- Alle single menn under 30 ?r med mer enn 100 000 kroner i gjeld vil ikke betale gjelden sin
- Menn under 25 ?r med mer enn 200 000 kroner i gjeld vil ikke betale gjelden sin, uavhengig av sivilstatus.
- Single kvinner under 28 ?r med mer enn 300 000 kroner i gjeld vil ikke betale gjelden sin
- Alle andre vil betale gjelden sin
Fortsett i prodsedyren enkel_prediksjon
som du skrev i forrige oppgave. Skriv if-setninger som basert p? antakelsene over vurderer om personen vil betale gjelden sin eller ikke. Basert p? dette skal det printes enten “vil betale” eller “vil ikke betale”.
Test programmet ditt med ulike verdier. Sjekk for eksempel at det printes “vil ikke betale” hvis du kj?rer programmet med singel mann p? 21 ?r med 120 000 kroner i gjeld.
Oppgave 3: Prediksjon basert p? tidligere betalingshistorikk
Filnavn: prediksjon_med_historikk.py
Lag en ny prosedyre prediksjon_med_betalingshistorikk
. Hent inn alder, kj?nn, sivilstatus og mengde gjeld p? samme m?te som i oppgave 1
(du kan kopiere de linjene med kode).
Vi ?nsker n? ogs? ? hente inn betalingshistorikken fra de tre forrige m?nedene og legge denne informasjonen i en liste.
- Lag en tom liste som du skal fylle med betalingshistorikken
- Hent inn betalingshistorikken for de forrige m?ned ved hjelp av
input
(én input for hver mnd, start med forrige mnd, deretter m?neden f?r, til slutt 2 mnd siden) - Forventet input hver gang er enten tekststrengen
betalt
ellerikke_betalt
- For hver gang du leser inn betalingshistorikken for en gitt m?ned legger du denne i listen
- Print til slutt innholdet i listen slik at du kan se at den har blitt fyllt opp som forventet.
Implementer den samme prediksjonen som du skrev i oppgave 2 (du kan kopiere koden fra den prosedyren), men gj?r én endring: Prediker alltid at personen ikke vil betale hvis personen ikke har betalt minst 2 av de 3 forrige m?nedene.
Oppgave 4: Prediksjon basert p? utdanningsniv?
Filnavn: prediksjon_med_historikk.py (fortsett p? samme kode som i forrige oppgave)
Utvid prosedyren du skrev i oppgave 3 til ? ogs? hente inn utdanningsniv?. Utdanningsniv? skal v?re en streng som enten er “ukjent”, “grunnskole”, “hoeyskole” eller “universitet”.
Vi ?nsker ? anta et inntektsniv? basert utdanningsniv?et til personen. Vi antar at gjennomsnittlig ?rsinntekt for de ulike utdanningsniv?ene er:
- Ukjent: 300 000 kr
- Grunnskole: 260 000 kr
- H?yskole: 500 000 kr
- Universitet: 700 000 kr
Denne informasjonen kan vi representere i en ordbok der n?kkel er utdanningsniv? og verdiene er inntekten.
Opprett en slik ordbok ?verst i prosedyren prediksjon_med_betalingshistorikk
.
La n?klene v?re sm? bokstaver og bytt ut ?-en i h?yskole med oe (hoeyskole).
Skriv kode for ? lese inn utdanningsniv?et ved hjelp av input
, og hent ut forventet inntekt ved ? gj?re et oppslag i ordboken.
Utvid deretter reglene dine slik at du alltid sp?r “vil betale” hvis personen er mann og har forventet inntekt som er h?yere enn 3 ganger gjelden.
Oppgave 5: Svartelistede personer
Filnavn: svartelisting.py
I noen tilfeller er ikke prediksjon n?dvendig, fordi vi allerede er ganske sikre p? hvem vi f. eks ?nsker ? tilby et l?n eller ikke.
For eksempel har banker typisk tilgang til lister over personer som ikke skal f? l?n, basert p? tidligere historikk (en slags svarteliste).
Lag en ny prosedyre bestem_laan
hvor du kun leser inn kunde-ID til en person ved hjelp av input
(kunde-ID vil v?re et tall og m? konverteres til int).
Anta at du vet at f?lgende personer personer (identifsert med kunde-ID) mest sannsynlig aldri vil betale gjelden sin, og at disse ikke b?r f? l?n:
23894, 29741, 10961, 22768, 22803, 11993, 24409, 9312, 29405, 6638, 738, 29964, 11967, 13443, 11534, 26228, 6867, 23027, 29137, 14084, 452, 15594, 22765, 25487
Basert p? denne informasjon kunne du ved hjelp av if-setninger sjekket om kunde-ID-en som tastes inn er lik en av de svartelistede ID-ene, men dette vil kreve veldig mange if-else-setninger.
I stedet ?nsker vi ? lage en en mengde (set) som representerer kundene som er svartelistet.
Dette kan du gj?re ved ? kopiere linjen over og legge til {
og }
p? hver side
(se p? forelesningsslidene dersom du har glemt hvordan du lager en mengde).
Sjekk deretter i prosedyren bestem_laan
om kunde-ID-en som sendes inn matcher en av de svartelistede ID-ene
(ved ? sjekke om den finnes i mengden), og print i s? fall "kan ikke f? l?n". Hvis den matcher, print "kan f? l?n".
Skriv en kommentar nederst i denne filen hvor du svarer p? f?lgende sp?rsm?l: Hvorfor passer det fint ? bruke en mengde for ? representere svartelistede kunder? Kunne man evt brukt en liste eller en ordbok?
Oppgave 6: Din egen prediksjon (valgfri oppgave) som kj?rer p? tusenvis av individer
Filnavn: DELTAKERNAVN.py
Denne oppgaven er valgfri og gir ikke poeng p? obligen. Hvis du gj?r den, vil prediksjonen din bli kj?rt p? 30 000 individer n?r du leverer oppgaven, og du vil f? tilbakemelding p? hvor bra den gj?r det. Neste gruppetime vil vi k?re en vinner.
For ? f? til ? kj?re koden p? s? mange individer p? en enkel m?te, er vi n?dt til ? ta i bruk noen av konseptene som blir gjennomg?tt i l?pet av de neste ukene. Dette blir derfor en smakebit p? noe av det som kommer, og man trenger ikke ? v?re bekymret om man ikke f?r til dette eller ikke skj?nner hva som skjer her.
Endre prosedyren til ? v?re en funksjon som tar parametere
Til n? har vi skrevet prosedyrer som henter input fra brukeren ved hjelp av input
.
Dette krever interaksjon med den som kj?rer programmet (via kommandolinjen), noe som er tungvindt hvis
man skal skrive st?rre programmer eller programmer
der input-en kommer fra andre kilder enn fra kommandolinjen (f. eks hvis input er et resultat fra andre prosedyrer eller
blir generert av andre deler av programmet).
De neste ukene skal vi se at funksjoner l?ser dette problemet. En funksjon er enkelt forklart en prosedyre som kan ta input via parametere, og returnere en verdi.
F?lgende kode definerer en funksjon min_prediksjon
som tar en rekke parametere, som blir tilgjengelig inne i funksjonen.
I stedet for ? m?tte oppgi disse parameterene via kommandolinjen, kan vi kalle funksjonen med parameterene (se linjen etter funksjonen):
def min_prediksjon(alder, kjonn, sivilstatus, gjeld, betalingshistorikk, utdanningsnivo):
# if alder < 28 and gjeld < 10000 ... osv
return "vil ikke betale"
resultat = min_prediksjon(50, "mann", "singel", 100000, ["betalt", "ikke_betalt", "betalt"], "hoeyskole")
print("Resultatet er:", resultat)
Ta utgangspunkt i koden over og fyll inn funksjonen slik at den fungerer p? samme m?te som koden du skrev i oppgave 4 (men ikke bruk input
).
Merk at funksjonen n? tar inn en liste betalingshistorikk
som vi forventer er laget p? utsiden av funksjonen. Du trenger derfor ikke ? opprette
denne listen inne i funksjonen.
Kj?r prediksjonen p? 1000 personer
Senere i faget skal vi l?re hvordan vi kan kj?re kode mange ganger ved hjelp av l?kker. Det er for eksempel veldig praktisk ? kunne gj?re hvis man skal predikere hvorvidt 1000 personer vil betale eller ikke, og ikke bare én person (slik vi har gjort til n?).
N? kan du bruke koden under for ? evaulere din egen prediksjon. Lag en fil DELTAKERNAVN.py
der du bytter ut DELTAKERNAVN
med et valgfritt navn du vil bruke i konkurransen (dette kan v?re brukernavnet ditt, eller noe helt annet om du ?nsker ? v?re anonym). Kopier f?lgende kode inn i filen DELTAKERNAVN.py
.
Denne koden leser 1000 individer fra fil og kj?rer din funksjon for hvert individ og sjekker om det du predikerer er rett eller ikke. Du trenger ikke ? sette deg inn i denne koden eller forst? hvordan den fungerer.
# Her er din funksjon med din egen prediksjon
def min_prediksjon(alder, kjonn, sivilstatus, gjeld, betalingshistorikk, utdanningsnivo):
# ...
# Dette limer du inn under
def test_min_prediksjon():
antall_predikert = 0
antall_riktig_predikert = 0
true_positive = 0
true_negative = 0
false_positive = 0
false_negative = 0
filnavn = "individer1000.txt"
fil = open(filnavn)
for linje in fil:
data = linje.strip().split(",")
alder = int(data[1])
kjonn = data[2]
sivilstatus = data[3]
gjeld = int(data[4])
betalingshistorikk = []
for i in range(0, 3):
betalingshistorikk.append(data[5+i])
utdanningsnivo = data[8]
fasit = data[9]
prediksjon = min_prediksjon(alder, kjonn, sivilstatus, gjeld, betalingshistorikk, utdanningsnivo)
if prediksjon == fasit:
antall_riktig_predikert += 1
if fasit == "vil betale":
if prediksjon == fasit:
true_positive += 1
else:
false_negative += 1
else:
if prediksjon == fasit:
true_negative += 1
else:
false_positive += 1
antall_predikert += 1
precision = true_positive / (true_positive + false_positive)
recall = true_positive / (true_positive + false_negative)
f1_score = 2 * (precision*recall) / (precision + recall)
print(antall_riktig_predikert, "av", antall_predikert, "ble riktig predikert")
print("Recall:", recall)
print("Precision:", precision)
print("F1 score:", f1_score)
Du m? i tillegg laste ned denne filen, og lagre den som individer1000.txt i samme mappe som du skriver programmet ditt.
Hvis du har gjort alt rett og kj?rer dette programmet, vil det til slutt printes hvor mange riktig predikeringer du har p? 1000 individer. N?r du leverer obligen vil programmet ditt bli kj?rt p? 30 000 individer. Vinner blir k?ret basert p? hvem som har h?yest F1 score p? 30 000 individer. Du "trener" alts? programmet ditt p? et mindre antall individer enn det programmet vil bli brukt p? senere.
Ekstra informasjon
Du kan implementere din egen prediksjon akkurat slik du vil. Du kan ha nytte av denne informasjonen n?r du skal implementere dine egne regler. Disse tallene gjelder for datasettet du vil bli vurdert p? til slutt:
- 22% betalte ikke gjelden sin. 24.2% av menn betalte ikke gjelden sin og 20.7 % av kvinner betalte ikke.
- Den h?yeste gjelden var p? 330 000 kr, og den laveste p? 3300 kroner. Gjennomsnittsgjelden er 55 600 kr.
- Blant single menn var det 26% som ikke betalte gjelden sin.
- Blant single menn under 25 ?r var det 65% som ikke betalte gjelden sin
- Blant de som ikke betalte de to forrige m?nedene, var det 50% som endte med ? ikke betalte gjelden sin.
Krav til innlevering
- Kun .py-filene skal leveres inn.
- Sp?rsm?lene til innleveringen (nedenfor) skal besvares i kommentarfeltet.
- Koden skal inneholde gode kommentarer som forklarer hva programmet gj?r.
- Programmet skal inneholde gode utskriftssetninger som gj?r det enkelt for bruker ? forst?.
Hvordan levere oppgaven
Kommenter p? f?lgende sp?rsm?l i kommentarfeltet i Devilry. Sp?rsm?lene skal besvares.
- Hvordan synes du innleveringen var? Hva var enkelt og hva var vanskelig?
- Hvor lang tid (ca) brukte du p? innleveringen?
- Var det noen oppgaver du ikke fikk til? Hvis ja: i. Hvilke(n) oppave(r) er det som ikke fungerer i innleveringen? ii. Hvorfor tror du at oppgaven ikke fungerer? iii. Hva ville du gjort for ? f? oppgaven til ? fungere hvis du hadde mer tid?
For ? levere:
- Logg inn p? Devilry.
- Lever alle .py-filene , og husk ? svare p? sp?rsm?lene i kommentarfeltet.
- Husk ? trykke lever/add delivery og sjekk deretter at innleveringen din er komplett. Du kan levere flere ganger, men alle filer m? v?re med i hver innlevering.
- Den obligatoriske innleveringen er minimum av hva du b?r ha programmert i l?pet av en uke. Du finner flere oppgaver for denne uken p? semestersiden.