Du er ikke logget inn. Så lenge du ikke er logget inn går du glipp av muligheten for å holde styr på din egen progresjon.

Logg inn

Valgte tags:

Filtrering:

Skriv ut:

Bayes Regel 0: Intro

Bayes' teorem

Bayes' regel, også kalt Bayes' setning eller Bayes' teorem, etter Thomas Bayes, sier noe om hvordan vi kan regne ut en betinget sannsynlighet hvis vi vet den motsatte betingede sannsynligheten.

Det er vanlig å presentere hvordan man kommer fram til Bayes' setning ved å se på en rekke regler for sannsynlighet.

Utledningen

A og B er hendelser.

Sannsynligheten for at både A og B skjer er den samme som at både B og A skjer.
P(A∩B) = P(B∩A)

Sannsynligheten for at A skjer ganget med at B skjer gitt A, er den samme som sannsynligheten for at B skjer ganget med at A skjer gitt B.
P(A)·P(B|A) = P(B)·P(A|B)

Vi kan dele den linjen med P(A) på begge sider, og så kommer vi til Bayes' setning:
P(B|A) = P(B)·P(A|B)/P(A)

Vi kan også bytte ut hver bokstav med den andre, så vi får:
P(A|B) = P(A)·P(B|A)/P(B)

De er ekvivalente.

Her er et klassisk eksempel på bruk av Bayes eksempel , i dette tilfellet tatt fra et hjelpehefte fra MAT3010 (se lenke nederst):

Fargeblindhet

En skole har 840 elever, 360 jenter, 480 gutter.
5 jenter er fargeblinde, 34 gutter er fargeblinde.

Vi trekker en elev fra denne skolen, og den eleven er fargeblind. Hva er sannsynligheten for at eleven i tillegg er jente?

J = eleven er jente
F = eleven er fargeblind

Vi vil finne P(J|F), altså sannsynligheten for at en elev er jente gitt at den er fargeblind.

Vi har at

P(J) = 360/840
(Antall elever som er jenter delt på totalt antall elever)

P(F) = 39/840
(Antall elever som er fargeblinde delt på totalt antall elever)

P(F|J) = 5/360
(Sannsynligheten for at en elev er fargeblind gitt at eleven er jente. Det vet vi fordi vi vet hvor mange jenter som er fargeblinde. Vi kan også finne P(F|G), altså sannsynligheten for at en elev er fargeblind gitt at eleven er en gutt, men det er ikke relevant for regnestykket vårt nå)

Vi kan sette opp Bayes' formel:

P(J|F) = P(J)xP(F|J)/P(F)
(Sannsynligheten for at en elev er jente, gitt at (vi vet at) eleven er fargeblind, er lik sannsynligheten for at eleven er jente, ganget med sannsynligheten for at ei jente er fargeblind, delt på sannsynligheten for å være fargeblind generelt).

Vi setter inn tallene våre:

P(J|F) = ((360/840)x(5/360))/(39/840) = 5/39

Sannsynligheten for at ei jente er fargeblind ved skolen er 5/39. Dette er jo faktisk antall jenter som er fargeblinde delt på antall fargeblinde studenter, men det er ikke alltid vi har mulighet til å finne svaret i dataene våre i tillegg.

Se de andre Bayes-oppgavene for å øve mer.

Eksempler her er tatt fra følgende sted, som også kan være fint å ta en titt på.
https://www.uio.no/studier/emner/matnat/math/MAT4010/v15/Oblig%202015/2015-mat3010-bayes.pdf

Her er en annen forklaring med et lignende eksempel:
https://ndla.no/nn/subject:32/topic:1:165832/resource:1:108221?filters=urn:filter:fbdf693f-58d7-448e-ad5b-5d5c8fb685f3

En kjapp intro til hvordan vi utleder Bayes' setning.
https://www.youtube.com/watch?v=JWtYcsVapsQ&t=79s&ab_channel=lektorthue

Comprehension 6: ordbøker

Gitt følgende liste:

gammel_liste = ["vinter","iskrem","bade","grillings","ski"]

a) Lag ei ordbok hvor hvert ord er nøkkelverdien, og innholdsverdien er hvor mange ganger ordet inneholder bokstaven "i".

b) Lag ei ordbok hvor hvert ord er nøkkelverdien, og innholdsverdien er ei liste av tegnene i ordet (F.eks: "kake" blir {'kake':['k','a','k','e']}).

Gitt følgende liste med tupler:

gammel_liste2 = [('Hvorfor', 'ADV'), ('gidder', 'VT'), ('vi', 'PRON'),
('dette', 'PRON'), ('?', 'SYM')]

c) Lag ei ordbok der ordformen er nøkkelverdi og ordklassen er innholdsverdi.

d) Gjør som i c), men utelat alle ord av ordklassen SYM.

Vis løsningsforslag

a)

{x:x.count("i") for x in gammel_liste}

b)

{x:list(x) for x in gammel_liste}

c)

{x[0]:x[1] for x in gammel_liste2}

d)

{x[0]:x[1] for x in gammel_liste2 if x[1] != "SYM"}

Lineær regresjon: Fra bunn av! (Utfordringsoppgave)

I denne oppgaven skal du implementere en least square error regresjonslinje matematisk. Å regne ut regresjonslinjer for hånd eller å implementere dem fra bunn av er strengt tatt ikke pensum, men kan være nyttig for å lære litt mer om lineær regresjon

Du kan lese mer her

OBS! I lenka over bruker de litt annen notasjon. De skriver "b" for vektene, og "a" for skjæringspunktet.

Selv om lineær regresjon kan estimeres, så kan også linær regresjon, i motsetning til logistisk regresjon, lett estimeres matematisk. For å gjøre det må vi utnytte to ting vi vet om regresjonslinja:

1) Formelen y = w1x1 + w2x2 + .... + b
2) Faktum at regresjonslinjen alltid går gjennom gjennomsnittet for y og alle x-variablene.

Vi kan derfor dele opp oppgaven i to deler:

1) Finne vektene og gjennomsnittene for alle klassene
2) Sette den ukjente b først, og finne b = y-gjennomsnitt - w1x2-gjennomsnitt + w2x2-gjennomsnitt etc.

Oppgave 1
Skriv en funksjon som takler et vilkårlig antall forklaringsvariabler (x) og som returnerer en funksjon som tar inn forklaringsvariablene og returnerer y-verdien. Den bør starte som noe som dette:

def regresjon(y,x_liste):
    ...
    ...
    return lambda x1,x2,xn... : 

Formelen for å finne en vekt w gitt en rekke verdier finner du på siden over, men gjentas her i noe dårligere skrevet form:

w = sum((x - avg(x)) × (y - avg(y))) / sum(x - x)2

...hvor avg(x) er gjennomsnittet for den x-variabelen, og avg(y) er gjennomsnittet for responsvariabelen y.

Oppgave 2
Denne deloppgaven mangler løsningsforslag enn så lenge, men kan være morsom å gjøre.

Bruk funksjonen fra oppgave 1 og lag en klasse Linear_regression som har to metoder: fit() og predict(). Fit skal ta inn samme type variabler som i oppgave 1, eller eventuelt en Pandas-dataramme på samme måte som sklearn. Husk å skille mellom responsvariablene (y) og forklaringsvariablene(x). Predict skal ta inn en liste med x-argumenter og returnere en predikert y-verdi.

Vis løsningsforslag
# eksempler til bruk
X = [6,10,2,4,6,7,0,1,8,5,3]
Y = [82,88,56,64,77,92,23,41,80,59,47]

def w_b(X_list,Y):
    # x er ei liste med lister med forklaringsvariabler
    # y er ei liste responsvariabler
    x_bars = []
    weights = []
    for li in X_list:
        x_bar = sum(li)/len(li)
        x_bars.append(x_bar)

    y_bar = sum(Y)/len(Y)
    #regner ut vektene
    for num,li in enumerate(X_list):
        teller = 0
        for x,y in zip(li,Y):
            teller += (x - x_bar) * (y - y_bar)    
        nevner = sum([(x - x_bar)**2 for x in li])
        w = teller/nevner
        weights.append(w)
    print("weights=",weights)
    #calculate the intercept
    #y_bar = b + w * x_bar
    #several explanatory variables:
    #y_bar = b + w1x_bar1 + w2x_bar2 ....
    b = y_bar - sum(w*x_bar for w,x_bar in zip(weights,x_bars))
    print("b=",b)
    #return teller/nevner
    #return lambda x:x*w + b

print(w_b([X,X,X],Y))

List comprehension 0: Introduksjon

Du har så langt lært å bruke for-løkker til å iterere gjennom ting, for å for eksempel fylle ei tom liste med nye elementer. I Python finnes det også noe som heter comprehension, som er en mer kompakt og mer effektiv måte å lage lister, ordbøker, og lignende på.

Les om detaljene rundt comprehension i dette dokumentet. Oppgavene fra dokumentet er gjengitt her på trix med minimale endringer.

Oppgavene ligger også på Trix for IN1140, men er enda mer relevante for IN2110.

Et eksempel på list-comprehension:

Si at vi har ei liste:

liste = ['a','b','c','d','e']

Og vi vil lage ei liste med alle bokstavene ganget tre ganger etter hverandre. Vi kan gjøre følgende:

trippel = []
for bokstav in liste:
    trippel.append(bokstav * 3)

Men med list-comprehension kan vi også skrive dette:

trippel = [b * 3 for b in liste]

I begge tilfeller får vi:

['aaa', 'bbb', 'ccc', 'ddd', 'eee']

List comprehension 1: Enkle lister

Gitt følgende liste, lag ei liste som ...

liste = [1, 4, 6, 8, 9, 14, 17]

a) ...er hvert tall ganget med 3.

b) ...er hvert tall delt på 1

c) ...er hvert tall + 10

d) ...er hvert tall opphøyd i 3.

Vis løsningsforslag

Løsningsforslag:

liste = [1, 4, 6, 8, 9, 14, 17]
#a
liste_a = [t * 3 for t in liste]

#b
liste_b = [t / 2 for t in liste]

#c
liste_c = [t + 10 for t in liste]

#d
liste_d = [t ** 3 for t in liste]
[3, 12, 18, 24, 27, 42, 51] #a
[0.5, 2.0, 3.0, 4.0, 4.5, 7.0, 8.5] #b
[11, 14, 16, 18, 19, 24, 27] #c
[1, 64, 216, 512, 729, 2744, 4913] #d

List comprehension 3: Lister med tupler

Gitt følgende liste med tupler:

gammel_liste = [('Kari', 'PN'), ('jager', 'VT'), ('dyret', 'N'),
('ved', 'P'), ('vannet', 'N'),('.','SYM')]

a) Lag ei liste med alle ordformene fra setningen.
b) Lag ei liste med alle ordklassetaggene fra setningen.
c) Lag ei liste av tupler hvor det første elementet er ordformen med små bokstaver, og den andre med store.

Vis løsningsforslag

a)

[x[0] for x in gammel_liste]

b)

[x[1] for x in gammel_liste]

c)

[(x[0].lower(),x[0].upper()) for x in gammel_liste]

List comprehension 4: List comprehension med if/else

Gitt denne lista (samme som i list comprehension 3):

gammel_liste = [('Kari', 'PN'), ('jager', 'VT'), ('dyret', 'N'),
('ved', 'P'), ('vannet', 'N'),('.','SYM')]

a) Lag ei liste av alle substantivene.
b) Lag ei liste av alle ordene som ikke er preposisjoner.
c) Lag ei liste av alle ordene som er lengre enn tre tegn.

Gitt følgende liste.

tall = [x for x in range(100)]

a) Lag ei liste av alle partallene.
b) Lag ei liste av alle tallene som har et kvadrat mellom 200 og 500.
c) Lag ei liste der alle partall erstattes av 2 og alle oddetall av 3.

Vis løsningsforslag

Løsningsforslag:

gammel_liste = [('Kari', 'PN'), ('jager', 'VT'), ('dyret', 'N'),
('ved', 'P'), ('vannet', 'N'),('.','SYM')]

print([x[0] for x in gammel_liste if x[1] == "N"])
print([x[0] for x in gammel_liste if x[1] != "P"])
print([x[0] for x in gammel_liste if len(x[0]) > 3])



tall = [x for x in range(100)]

print([x for x in tall if x % 2 == 0])
print([x for x in tall if 200 < x ** 2 < 500])
print([2 if x % 2 == 0 else 3for x in tall])

Utskrifter:

['dyret', 'vannet']
['Kari', 'jager', 'dyret', 'vannet', '.']
['Kari', 'jager', 'dyret', 'vannet']
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98]
[15, 16, 17, 18, 19, 20, 21, 22]
[2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3]

List comprehension 5: Nøsting

Gitt følgende tekst:

tekst = [['Kari', 'maler', 'huset', '.'], ['Det', 'er', 'lettere',
'overskyet,', 'men', 'varmt', '.'], ['Spurvene', 'leker',
'i', 'dammen', '.']]

a) Lag ei liste med alle ordene.
b) Lag ei liste med alle ordene som ikke er punktum

Følgende oppgaver krever ikke bruk av lista fra a) og b):

c) Lag en 6x6-matrise fylt med 9-ere.
d) Lag en 5x5-matrise hvor hvert element er rad-indeksen ganger kolonne-indeksen (begynn på 0), med mindre produktet er et partall, da skal det være 0.

Vis løsningsforslag

Løsningsforslag:

tekst = [['Kari', 'maler', 'huset', '.'], ['Det', 'er', 'lettere',
'overskyet,', 'men', 'varmt', '.'], ['Spurvene', 'leker',
'i', 'dammen', '.']]

#a
print([w for s in tekst for w in s])
#b
print([w for s in tekst for w in s if w != "."])
#c
print([[9 for i in range(6)] for j in range(6)])
#d
print([[i*j for i in range(5)] for j in range(5)])

Utskrift:

['Kari', 'maler', 'huset', '.', 'Det', 'er', 'lettere', 'overskyet,', 'men', 'varmt', '.', 'Spurvene', 'leker', 'i', 'dammen', '.']
['Kari', 'maler', 'huset', 'Det', 'er', 'lettere', 'overskyet,', 'men', 'varmt', 'Spurvene', 'leker', 'i', 'dammen']
[[9, 9, 9, 9, 9, 9], [9, 9, 9, 9, 9, 9], [9, 9, 9, 9, 9, 9], [9, 9, 9, 9, 9, 9], [9, 9, 9, 9, 9, 9], [9, 9, 9, 9, 9, 9]]
[[0, 0, 0, 0, 0], [0, 1, 2, 3, 4], [0, 2, 4, 6, 8], [0, 3, 6, 9, 12], [0, 4, 8, 12, 16]]

Matriseregning 0.1: Matrisemultiplikasjon

Vi kan gange to matriser med hverandre, det kalles matrisemultiplikasjon. Vi bruker termen matrise også for vektorer, som bare er matriser med bare én kolonne (kolonnevektor), eller én rad (radvektor).

Intro

Ett krav for at to matriser kan ganges med hverandre, er at antall kolonner i den første er lik antall rader i den andre. Det vil si at matrisemultiplikasjon er udefinert for to matriser der dette ikke er tilfelle. Hvis matrisene er gyldige, tar vi så dottproduktet av hver rad i den første matrisen og hver kolonne i den andre matrisen. Merk at antall kolonner i en matrise tilsvarer lengden på radene, og motsatt. Den resulterende matrisen vil ha like mange rader som den første matrisen, og like mange kolonner som den andre matrisen.

Eksempel: Gitt vektor a og vektor b:

a = [1,2,3]

b = [2,
3,
4]

Vektor a har 3 kolonner og 1 rad.

Vektor b har 1 kolonne og 3 rader.

Vi tar prikkproduktet (skalarproduktet) av [1,2,3] og [2,3,4].
Husk at prikkproduktet er summen av tallene i den ene vektoren ganget med tallet på tilsvarende plass i den andre vektoren. Her blir ikke radvektorer og kolonnevektorer noe annerledes, men husk at vi begynner å telle fra venstre i radvektoren, og fra øverst i kolonnevektoren. Her står × for "vanlig" multiplisering.

Altså:
a⋅b = [1,2,3]⋅[2,3,4] = 1×2 + 2×3 + 3×4 = 2 + 6 + 12 = 20

Men hvis vi snur rekkefølgen, og tar b⋅a får vi en annen situasjon. Da stemmer det fortsatt at antall kolonner i den første matrisen er det samme som antall rader i den andre, men siden den resulterende matrisen vil ha like mange rader som den første matrisen, og like mange kolonner som den andre matrisen, får vi en 3x3-matrise, og vi må gjøre utregningen i 9 steg.

b⋅a gir oss altså en 3x3-matrise, vist her som en todimensjonal Python-liste:
[[i1,i2,i3],
[i4,i5,i6],
[i7,i8,i9]]

...hvor utregningen er som følger:

b = [2,
3,
4]

a = [1,2,3]

i1 = 2×1 = 2 (2 fra b, 1 fra a)
i2 = 2×2 = 4 (2 fra b, 2 fra a)
i3 = 2×3 = 6 (2 fra b, 3 fra a)
i4 = 3×1 = 3 (3 fra b, 1 fra a)
i5 = 3×2 = 6 (3 fra b, 2 fra a)
i6 = 3×3 = 9 (3 fra b, 3 fra a)
i7 = 4×1 = 4 (4 fra b, 1 fra a)
i8 = 4×2 = 8 (4 fra b, 2 fra a)
i9 = 4×3 = 9 (4 fra b, 3 fra a)

Vi kan også teste dette i numpy:

np.matrix() kan blant annet ta inn ei liste som representerer en matrise.
np.matmul() er matrisemultiplikasjon som tar to matriser.

import numpy as np

a = np.matrix([1,2,3])
b = np.matrix([[2],[3],[4])

print(np.matmul(a,b))
print(np.matmul(b,a))

Da får vi følgende utskrift:

matrix([[20]])

matrix([[ 2,  4,  6],
        [ 3,  6,  9],
        [ 4,  8, 12]])

Hvis matrisene ikke er gyldige

I noen tilfeller vil man gange sammen matriser som er helt like. Med kriteriene for matrisemultiplikasjon i minne ser vi at det ikke går med mindre de to matrisene er kvadratiske. Men, det finnes et triks! Vi kan transposere den ene matrisen. Dette indikeres med en T øverst til høyre for matrisebetegnelsen, slik: aT. Les introoppgave 0.2 for mer info om transposering. Kort fortalt gjør vi om alle rader til kolonner, så hvis vi har to vektorer med lik dimensjonalitet:

a = [1,2,3,4,5]
b = [3,4,5,6,7]

og vi vil gange dem, så finner vi enten:

aTb, som gir oss en 5x5-matrise.

eller

bTa, som gir oss en 1x1-matrise.

Les mer her:
https://www.mathsisfun.com/algebra/matrix-multiplying.html

Matriseregning 1.1 Matrisemultiplikasjon

Regn ut matriseproduktene under. Du anbefales å gjøre dem både for hånd og med numpy. Se også oppgave 1.2 for å implementere en funksjon til å regne ut matrisemultiplikasjon selv. Vær obs på om matrisemultiplikasjonen er definert for matrisene.

Oppgave 1

a = [3,2,1]
b = [1,
     2,
     3]
c = [2,4,3]
d = [1
     1,
     1]

Regn ut:
a) ab
b) ba
c) aTc
d) acT
e) bd
f) cd
g) dc

Oppgave 2)

a = [2,2,4,
     3,2,1]
b = [1,3,
     2,1,
     4,2]

Regn ut:
a) ab
b) ba
c) baT
d) aaT
e) aTa

Oppgave 3)

a = [3,2,4,
     2,3,4,
     1,2,2]
b = [2,2,2]
c = [4,
     2,
     5]

Regn ut:
a) aa
b) ab
c) ac
d) cc
e) abT
f) acT
g) bb

NoReC-øving 0

Denne oppgaven er ment for å bli kjent med norec-oppsettet som brukes i IN2110. Se oppgave 1 for tester på dokumentnivå, og oppgave 2 for å jobbe litt med metadataene til dokumentene.

NoReC (Norwegian Review Corpus), er en samling anmeldelser som alle har terningkast. Korpuset har vært utangspunkt for mye forskning de siste årene hos LTG. Du kan lese mer om NoReC her.

I IN2110 har vi tilgang til en enkel klasse, kalt "norec", som lar oss lett få tilgang til dokumenter og metadata.

Vi importerer norec-klassen slik:

from in2110.corpora import norec

Det er hovedsaklig sju metoder som er interessante:

1)

norec.get_document(dokumentid)

Denne henter ut teksten til ett dokument gitt en dokument-id. Dokument-id-ene har opprinnelig seks sifre, men id-er som begynner på 0 får disse fjernet. I denne klassen er id-ene etterfulgt av endelsen ".txt". Vi må derfor skrive "335.txt" for dokument 000335.txt".

Eksempel på kjøring:

doc = norec.get_document("335.txt")

print(doc[:500])

Utskrift av de 500 første tegnene:

Frikjent S02 E01 – E04

Dramakrimserien Frikjent tyr til svært billige såpeserietriks for å skru til dramatikken i sin andre sesong.

Stikkordene er hukommelsestap og sjokkerende familieforbindelser, og disse parodisk slitte virkemidlene gjør at jeg ler høyt på steder hvor jeg tror serieskaperne ønsker at jeg egentlig skal bli revet med.

Jeg likte den første sesongen av Frikjent ganske godt. Handlingstrådene som gikk til utlandet led av dårlig dialog og en del overspill, men det var en god nerv

2)

norec.get_metadata(dokumentid)

Denne henter ut metadataene til et dokument gitt dokument-id-en. Se lenger ned for mer info om metadataene.

Eksempel på kjøring:

meta = norec.get_metadata("335.txt")
print(meta)

Utskrift:

{'authors': ['Sigurd Vik'], 'category': 'screen', 'day': 21, 'excerpt': 'Til tider ufrivillig morsomt.', 'id': 335, 'language': 'nb', 'month': 10, 'rating': 3, 'source': 'p3', 'source-category': 'tv', 'source-id': 229912, 'source-tags': [], 'split': 'dev', 'tags': ['tv'], 'title': 'Frikjent S02 E01 – E04', 'url': 'http://p3.no/filmpolitiet/frikjent-s02', 'year': 2016}

Hvis vi for eksempel vil hente ut kategorien til et dokument, kan vi skrive følgende:
OBS! Kategoriene vi bruker er de som ligger under "category". "source-category" (kildekategori) er mer løst definerte kategorier fra de opprinnelige tekstene, og brukes ikke.

meta = norec.get_metadata("335.txt")
print(meta["category"])

Utskrift:

screen

3)

norec.random_document()

Denne metoden henter ut et id-en til et tilfeldig dokument.
Eksempelbruk:

tilfeldig = norec.random_document()
print(tilfeldig)

Utskrift:

702642.txt

4)

norec.document_list()

Eksempel på kjøring. Vi skriver ut id-ene til de ti første dokumentene:

docs = norec.document_list()
print(docs[:10])

Utskrift

['3158.txt', '500607.txt', '500608.txt', '500605.txt', '500606.txt', '3159.txt', '3162.txt', '3163.txt', '110333.txt', '3164.txt']

5-7)

norec.train_set()

norec.dev_set()

norec.test_set()

Tre metoder som henter ut trenings-, evaluerings- og testdatasettene. Disse returnerer en iterator over alle dokumentene i de tre "split"-ene.

Disse returnerer generatorer med Document-objekter. Et document-objekt har to variabler vi kan få tak i, .text og .metadata.

Vi kan bruke .text og .metadata for å få samme info som vi fikk med .get_document() og .get_metadata(). I eksempelet under tar vi det første dokumentet i train-klassen. Her bruker vi next() bare som en kjapp måte å ta ut ett element fra generatoren på.

train = norec.train_set()

doc = next(train)

print(doc.text[:500])
print(doc.metadata)

Utskrift:

Magnolia

Magnolia er en lappeteppe-film i samme klasse som "Short Cuts", "Playing by heart" og "Happiness". Vi møter forskjellige menneskeskjebner i Los Angeles, der kjærlighet, ensomhet og svik er et gjennomgående tema. Og i løpet av filmen knyttes alle skjebnene på en eller annen måte til hverandre.

Mange historier

Tv-produsent Earl Partridge ligger for døden. Hans unge kone sliter med å forberede seg på det kommende tapet. Hans sønn, Frank Mackey, har ikke sett faren på 20 år, men hjelpepl
{'authors': ['Birger Vestmo'], 'category': 'screen', 'day': 19, 'excerpt': 'Tom Cruise imponerer.', 'id': 3158, 'language': 'nb', 'month': 2, 'rating': 5, 'source': 'p3', 'source-category': 'film', 'source-id': 166211, 'source-tags': [], 'split': 'train', 'tags': ['movie'], 'title': 'Magnolia', 'url': 'http://p3.no/filmpolitiet/magnolia', 'year': 1999}

NoReC-dokumentene har flere forskjellige metadataer, som ligger som nøkler i metadata-ordboka. "category" refererer til den grove kategoriinndelingen vi bruker i obligen, og som er nevnt i artikkelen, mens "source-category" er en noe finere inndeling fra de opprinnelige tekstene, som vi ikke skal bruke.

NoReC-øving 1

Les gjennom NoReC-øving 0 og svar på oppgavene under. Bruk de fire første metodene til disse oppgavene.

Oppgave 1)

Hvor mange dokumenter er det i korpuset?

Oppgave 2)

Hvis vi tokeniserer på mellomrom, hva er det gjennomsnittlige antallet ord i korpuset? Hva er medianen? Hvor mange ord har det lengste dokumentet? Hvor mange ord har det minste? Hva tenker du om forskjellen?

Oppgave 3)
Ved å bruke metoden i oppgave 2, hvor mange ordforekomster (tokens) har vi, og hvor mange ordformer (typer) har vi? Hvilke ord er de 10 vanligste blant alle dokumentene? Er det mange hapax legomena (ord som bare forekommer én gang). Hva tenker du? Er det bare den dårlige tokeniseringen som er skylden her?

Oppgave 4)
Hvis vi bare deler opp på punktum, hvor mange setninger har dokumentene i gjennomsnitt? Hva er medianen? Hvor mange setninger har det lengste dokumentet? Hvor mange setninger har det korteste? Tror du svaret blir helt rett? Hva er det vi eventuelt får med som vi ikke vil ha med, eller motsatt?

Vis løsningsforslag

Løsningsforslag:

Oppgave 1

from in2110.corpora import norec

docs = norec.document_list()
print("Antall dokumenter:",len(docs))

utskrift:

Antall dokumenter: 35188

Oppgave 2

from in2110.corpora import norec
from statistics import mean,median

docs = norec.document_list()

# tokenisering på mellomrom
antall_ord = [len(norec.get_document(doc).split(" ")) for doc in docs]

# gjennomsnitt
print("Gjennomsnitt, ord:", mean(antall_ord))

# median
print("Median, ord:", median(antall_ord))

# det lengste
print("Flest ord:", max(antall_ord))

# det korteste
print("Færrest ord:",min(antall_ord))

Utskrift:

Gjennomsnitt, ord: 361.40707059224735
Median, ord: 314.0
Flest ord: 3819
Færrest ord: 1

Det er noen dokumenter som bare har overskrifter, da blir de veldig korte.

Oppgave 3

from collections import Counter
docs = norec.document_list()

counter = Counter()

for doc in docs:
    for word in norec.get_document(doc).split(" "):
        counter[word] += 1

# antall ordforekomster (tokens)
print("Antall ordforekomster:", sum(counter.values()))

# antall ordformer (types)
print("Antall ordformer:",len(counter))

# de ti vanligste ordene
print("10 most common words: \n\t{}".format("\n\t".join([x[0] for x in counter.most_common(10)])))

# antall hapax legomena
print("Antall hapaxer:",len([x for x in counter.most_common() if x[1] == 1]))

Counter-klassen er en underklasse av ordbøker, derfor kan vi bruke .values() for å få tak i alle tellingene. Det er en veldig praktisk klasse når vi skal gjøre denne typen tellinger.

Utskrift:

Antall ordforekomster: 12717192
Antall ordformer: 1078898
10 most common words:
        og
        er
        i
        som
        en
        på
        det
        å
        av
        med
Antall hapaxer: 792330

Den dårlige tokeniseringen hjelper selvsagt ikke på antall hapaxer, men tekstene i NoReC er kreative, og det er mange sammensetninger og andre ord som ikke forekommer mange ganger. I tilleg har vi en stor mengde engelske ord som forekommer i titler, og veldig mange egennavn, som for eksempel på produktene som anmeldes.

Oppgave 4

from in2110.corpora import norec
from statistics import mean,median

docs = norec.document_list()
# tokenisering på punktum
antall_setninger = [len(norec.get_document(doc).split(".")) for doc in docs]

# gjennomsnitt
print("Gjennomsnitt, setninger:", mean(antall_setninger))

# median
print("Median, setninger:", median(antall_setninger))

# det lengste
print("Flest setninger:", max(antall_setninger))

# det korteste
print("Færrest setninger:",min(antall_setninger))

Utskrift:

Gjennomsnitt, setninger: 21.689013299988634
Median, setninger: 18.0
Flest setninger: 194
Færrest setninger: 1

De dokumentene som bare hadde ett ord i oppgave 2 får selvsagt også bare 1 setning. Generelt sett er gjennomsnittet vi får her litt lavere enn det faktiske gjennomsnittet, siden vi ikke tar hensyn til at overskrifter og underoverskrifter ikke skilles av punktum, men av linjeskift.

NoReC-øving 2

Les gjennom NoReC-øving 0 og svar på oppgavene under. Bruk de fire første metodene til disse oppgavene.

Oppgave 1)

Hvor mange forfattere har skrevet anmeldelser som er med i NoReC? Hvilke ti forfattere har skrevet flest anmeldelser? Hvor mange anmeldelser har den forfatteren som har skrevet flest anmeldelser skrevet? Hvilke antagelser gjør vi eventuelt her?

Oppgave 2)

Skriv en funksjon som returnerer forfatterne til ti tilfeldige dokumenter.

Oppgave 3)

Hvor mange dokumenter som er det som har fått de forskjellige terningkastene ("rating")? Hvilke terningkast er det flest av?

Oppgave 4)

Hvor mange anmeldelser er på nynorsk? Hvor mange forfattere skriver på nynorsk? Hvor mange skriver på bokmål? Er det noen forfattere som skriver på begge målformer? Skriv en ny tabell som i oppgave 2, men fordel antall anmeldelser på nynorsk og bokmål. Er det noen kategorier som er over- eller underrepresenterte på nynorsk eller bokmål?

Vis løsningsforslag

Løsningsforslag:

Oppgave 1

Disse oppgavene baserer seg i stor grad på metadataene vi henter ut fra dokumentene.

author_count = Counter()
for d in docs:
    authors = norec.get_metadata(d)["authors"]
    for author in authors:
        author_count[author] += 1

print("Antall forfattere: ",len(author_count))
print("De ti mest produktive: ")
for auth in author_count.most_common(10):
    print("\t",auth)
mest_prod = author_count.most_common(1)[0]
print("Den mest produktive forfatteren '{}' har skrevet {} anmeldelser".format(mest_prod[0],mest_prod[1]))

utskrift:

Antall forfattere:  478
De ti mest produktive:
         ('Redaksjonen', 8517)
         ('Arild Abrahamsen', 1789)
         ('Birger Vestmo', 1487)
         ('Morten Ståle Nilsen', 1477)
         ('Stein Østbø', 1425)
         ('Jon Selås', 1005)
         ('Kristin Aalen', 874)
         ('Geir Flatøe', 697)
         ('Thomas Talseth', 663)
         ('Tor Martin Bøe', 564)
Den mest produktive forfatteren 'Redaksjonen' har skrevet 8517 anmeldelser

En av antagelsene vi må gjøre er at ingen forfattere har samme navn.

Oppgave 2

Løsningsforslag under utvikling.

Oppgave 3
Løsningsforslag under utvikling.

Pandas 1

Oppgave 1: Kyr og mjølkeproduksjon

I denne oppgava skal vi se på melkeproduksjon hos kyr. Dataene er fiktive.

a) Lag ei Pandas-dataramme med utgangspunkt i dataene under, som skal vise kuas gjennomsnittlige daglige melkeproduksjon (i kg), alder og mengde fôr.

melk = [21.5,22.6,22.4,23.1,23.2,23.1,23.4,23.1,23.2,23.9,24.0,25.0,25.2,25.7]
alder = [3,4,4,4,5,5,5,6,6,7,7,8,8,8]
foret = [1,1,1,1,2,2,2,2,3,3,3,3,4,4]

b)
Bruk .head() og .tail() til å undersøke hvordan starten og slutten av datasettet du har lagd ser ut. Vi kan også skrive ut hele dataramma som den er, for å se hele.

c) Lage ny kolonne basert på en annen kolonne.

Kumelk er litt tyngre enn vann, 1 liter melk kan for eksempel veie ca. 1.032. For å gå fra kilo til liter må vi gange med (ca.) 0.9689. Lag en ny kolonne i datarammen som heter melk_liter. Bruk .head() for å ta en titt på endringene.

d) Endre eksisterende kolonne

Av en eller annen grunn vil vi ha alderen til kyra i måneder istedenfor år. Skriv over kolonnen med alderen med den nye alderen. Bruk .head() for å ta en titt på endringene.

e) Legge til en helt ny kolonne.

Kyr har ofte navn, og det finnes registre over kunavn. Vi ser for oss at vi av en eller annen grunn (ikke fordi det er nyttig til regresjon) legger inn navna på kyra. Lag en ny kolonne med navna.

['Trulte', 'Betty', 'Stjerne', 'Rødlin', 'Golin', 'Litago', 'Bliros', 'Morlik', 'Dokka', 'Fagerlin', 'Rosa', 'Litago', 'Dagros', 'Rosa']

(Navn tatt fritt fra listen fra Tines kukontroll i 2004: https://www.regjeringen.no/globalassets/upload/kilde/ld/prm/2004/0596/ddd/pdfv/215710-ku-navn_2004-ti_pa_topp-pm.pdf)

Hvis du vil gjøre noen regresjonsoppgaver med dette datasettet kan du se på oppgaven Regresjon 1 (under utvikling).

Vis løsningsforslag

a)

import pandas

# Vi har tre lister vi kan bruke
melk = [21.5,22.6,22.4,23.1,23.2,23.1,23.4,23.1,23.2,23.9,24.0,25.0,25.2,25.7]
alder = [3,4,4,4,5,5,5,6,6,7,7,8,8,8]
foret = [1,1,1,1,2,2,2,2,3,3,3,3,4,4]

# Vi kaller variabelen som holder på dataramma for "kyr"
# DataFrame tar ei ordbok. Nøkkelverdiene i ordboka blir navnet på kolonnene (series).

kyr = pandas.DataFrame({"melk":melk,
                       "alder":alder,
                       "fôr":foret})

b)

Head og tail viser oss de fem første eller siste elementene. Det er praktisk hvis vi bare vil ta en kjapp titt på hvordan kolonnene ser ut, eller på noen av dataene.

print(kyr.head())
print(kyr.tail())
print(kyr)
   melk  alder  fôr
0  21.5      3    1
1  22.6      4    1
2  22.4      4    1
3  23.1      4    1
4  23.2      5    2

    melk  alder  fôr
9   23.9      7    3
10  24.0      7    3
11  25.0      8    3
12  25.2      8    4
13  25.7      8    4

    melk  alder  fôr
0   21.5      3    1
1   22.6      4    1
2   22.4      4    1
3   23.1      4    1
4   23.2      5    2
5   23.1      5    2
6   23.4      5    2
7   23.1      6    2
8   23.2      6    3
9   23.9      7    3
10  24.0      7    3
11  25.0      8    3
12  25.2      8    4
13  25.7      8    4

c)
Vi lager en ny kolonne (series) ved å spesifiere et nytt kolonnenavn (her: "melk_liter"), og så

kyr["melk_liter"] = kyr["melk"] * 0.9689

print(kyr.head())

Output:

   melk  alder  fôr  melk_liter
0  21.5      3    1    20.83135
1  22.6      4    1    21.89714
2  22.4      4    1    21.70336
3  23.1      4    1    22.38159
4  23.2      5    2    22.47848

d)
Vi overkjører den eksisterende kolonnen ved å si at samme nøkkelverdi skal ha verdiene til samme kolonne ganga med 12.

kyr["alder"] = kyr["alder"] * 12

print(kyr.head())

Output:

   melk  alder  fôr  melk_liter
0  21.5     36    1    20.83135
1  22.6     48    1    21.89714
2  22.4     48    1    21.70336
3  23.1     48    1    22.38159
4  23.2     60    2    22.47848

e)
For å legge til helt nye kolonner kan vi gjøre som når vi skal legge til en kolonne basert på en tidligere, bare at vi spesifiserer hele lista med verdier.

kyr["navn"] = ['Trulte', 'Betty', 'Stjerne', 'Rødlin', 'Golin', 'Litago', 'Bliros', 'Morlik', 'Dokka', 'Fagerlin', 'Rosa', 'Litago', 'Dagros', 'Rosa']

print(kyr.head())
   melk  alder  fôr  melk_liter     navn
0  21.5     36    1    20.83135   Trulte
1  22.6     48    1    21.89714    Betty
2  22.4     48    1    21.70336  Stjerne
3  23.1     48    1    22.38159   Rødlin
4  23.2     60    2    22.47848    Golin

Vektoroperasjoner 1

I disse oppgavene skal du gjøre deg kjent med noen ulike vektoroperasjoner ved å skrive funksjonene i python. Skriv så mye du kan fra bunn av, men det viktige er matten, så bruk gjerne list comprehension. Kvadratrotsfunksjonen "sqrt" kan du laste inn ved å skrive:

from math import sqrt

Oppgave 1) Prikkprodukt/Skalarprodukt

Skriv en funksjon som returnerer skalarproduktet (prikkproduktet) til en vektor v.

Oppgave 2) Størrelsen til en vektor

Skriv en funksjon som returnerer størrelsen (lengden) til en vektor v.

Vi finner størrelsen av en vektor ved å ta kvadratroten av summen av kvadratene til alle elementene i vektoren.

Oppgave 3) Cosinus-likhet 1

Skriv en funksjon som returnerer cosinus-likheten til to vektorer v1 og v2.

For å regne ut kosinus-likheten tar vi prikkproduktet av vektorne og deler det på størrelsene til de to vektorne ganget med hverandre.

Oppgave 4) Normalisering

Skriv en funksjon som returnerer en normalisert vektor.

For å normalisere en vektor deler vi hvert element i vektoren på størrelsen av vektoren.

Oppgave 5) Cosinus-likhet 2

Skriv en funksjon som returnerer cosinus-likheten til to vektorer v1 og v2, der vi antar at alle vektorne er normaliserte. Hvordan kan vi gjøre denne annerledes fra funksjonen i oppgave 3?

Oppgave 6) Euklidsk avstand

Skriv en funksjon som returnerer den euklidske avstanden mellom to vektorer v1 og v2.

Oppgave 7) Cosinus og euklidsk avstand

a) Bruk vektorne under til å svare på oppgaven. Undersøk den euklidske avstanden mellom de fire u-normaliserte vektorene, og undersøk cosinus-avstanden mellom dem. Hvordan blir resultatene? Skriv en liten tabell.

v1 = [4,6,7,3]
v2 = [4,2,7,0]
v3 = [1,6,7,2]

b) Normaliser deretter vektorne, og gjenta b). Hvordan ser det ut nå? Hvilken effekt har det?

c) Gitt den nye vektoren under, ranger vektorne i a) etter hvor like de er den nye vektoren. Normaliser så vektorene som i b), og gjenta undersøkelsen. Hva ser du?

v4 = [1,5,4,1]
Vis løsningsforslag

Løsningsforslag under utvikling.

Oppgave 1

def skalarprodukt(a,b):
    summen = 0
    for i,j in zip(a,b):
        summen += i*j
    return summen

# alternativ med list comprehension
def skalarprodukt2(a,b):
    return sum([i*j for i,j in zip(a,b)])

Oppgave 2

import math

def stoerrelse(a):
    summen = 0
    for i in a:
        summen += i**2
    return sqrt(summen)

Oppgave 3

def cosinus(a,b):
    return skalarprodukt(a,b)/(stoerrelse(a)*stoerrelse(b))

Oppgave 4

def normalized(a):
    ny = []
    magn = stoerrelse(a)
    for i in a:
        ny.append(i/magn)
    return ny

Oppgave 5

def cosinus(a,b):
    return skalarprodukt(a,b)

Siden lengden av de normaliserte vektorne er 1, så er ||a||*||b|| = 1 * 1 = 1, og når vi deler på 1 så skjer det ikke noe, så da blir det å regne ut cosinus mellom dem redusert til det å regne ut skalarproduktet. Funksjonen blir derfor noe redundant; vi kunne fint brukt skalarprodukt-funksjonen alene.

Oppgave 6

import math

def avstand(a,b):
    summen = 0
    for i,j in zip(a,b):
        summen += (i - j)**2
    return sqrt(summen)

Oppgave 7
Under utvikling.