Vorige | Home | Slides | Volgende

 

PTT Python 2011: Opdracht 5


Deze opdrachten zijn onderdeel van een programmeercursus gegeven in de opleiding Informatiekunde van de Rijksuniversiteit Groningen.

Achtergrondinformatie bij deze opdracht is te vinden in de secties 5.4.1, 5.9, 7.1.3, 7.4, 10.3 van het boek van Zelle en in de online-Pythonhandleiding, in de secties over Unicode, pipes en de pakketten os en doctest,

Bij deze opdrachten gebruiken we een verzameling van 2,7 miljoen Nederlandstalige Twitterberichten van zaterdag 21 mei 2011. De berichten zijn verdeeld over 24 uurbestanden (zip). Gebruik bij het testen van je programma's maar 1 van deze bestanden want anders kost het testen te veel tijd.

Opdracht 5.1

Het programma hieronder telt hoeveel unieke tokens in een verzameling met gecomprimeerde bestanden met Twitterinformatie zitten: zien van de standaardinvoer samen met hun relatieve frequentie:

from sys import argv
from re  import sub
import pipes

# functie voor tokenisatie: in: regel; uit: lijst met tokens
def tokenize(regel):
   regel = sub("([^a-zA-Z0-9 ]+)",r" \1 ",regel) 
   return(regel.split()) 

# hoofdroutine
def main(bestanden):
   # dictionary voor gevonden types
   types = {}
   # behandel alle invoerbestanden
   for bestandsnaam in bestanden:
      # open bestand
      c = "gunzip -c "+bestandsnaam    # pipe-commando 
      p = pipes.Template()             # maak een pipe-object 
      p.prepend(c,".-")                # plaats commando in object 
      bestand = p.open("","r")         # open de pipe 
      for regel in bestand:            # lees regel uit pipe 
         regel = regel.rstrip()        # verwijder newline 
         regel = regel.lower()         # zet regel om naar kleine letters
         regelTokens = tokenize(regel) # tokeniseer regel
         for token in regelTokens[1:]: # hou aantal types bij 
            if token in types:         # als token eerder is gezien
               types[token] += 1       # verhoog aantal
            else:                      # anders (nieuw token)
               types[token] = 1        # aantal = 1
      bestand.close()                  # sluit pipe 
   aantal = 0                          # aantal types
   aantal1 = 0                         # aantal types dat 1x voorkomt
   for type in types:                  # voor elke type
      aantal += 1                      # hou bij hoeveel types er zijn
      if types[type] == 1:             # idem voor types met 1 voorkomen
         aantal1 += 1
   print("van de",aantal,"types komen",aantal1,"1x voor")

# hoofdroutine
if __name__ == "__main__": main(argv[1:])

Lees het programma en kijk of je begrijpt hoe het werkt. Vergelijk het eventueel met de collegeslides voor week 5 (PDF).

Pas daarna het programma aan zodanig dat het ook bijhoudt hoeveel tokens 2 tot 10 keer voorkomen, hoeveel 11 tot 100 keer voorkomen en hoeveel vaker dan 100 keer voorkomen. Pas het programma toe op een grotere verzameling bestanden (zip). Test het wel eerst met 1 bestand (anders duurt het testen zo lang).

Hier zijn twee voorbeelden van de interactie met een aangepaste versie van het programma:

$ python3 51.py pt11/2011052100.out.gz 
van de 130399 types komen 76813 1x voor
van de 130399 types komen 43750 2 tot 10x voor
van de 130399 types komen 8373 11 tot 100x voor
van de 130399 types komen 1463 vaker dan 100x voor
$ python3 51.py pt11/20110521*.out.gz 
van de 1058137 types komen 606282 1x voor
van de 1058137 types komen 355919 2 tot 10x voor
van de 1058137 types komen 81715 11 tot 100x voor
van de 1058137 types komen 14221 vaker dan 100x voor

Het programma wordt aangeroepen met 1 of meer namen van gecomprimeerde bestanden als argument en laat vervolgens zien hoe vaak types in de bestanden voorkomen.

Opdracht 5.2

Pas het programmavoorbeeld van opdracht 5.1 zodanig aan dat het niet tokens telt maar bigrammen van tokens in Twitterberichten. Hier zijn twee voorbeelden van de interactie met een aangepaste versie van het programma:

$ python3 52.py pt11/2011052100.out.gz
van de 680987 bigramtypes komen 484357 1x voor
$ python3 52.py pt11/20110521*.out.gz 
van de 6704380 bigramtypes komen 4620518 1x voor
# bovenstaande test hoef je niet uit te voeren als het te lang duurt

Tip: om het vorige of volgende token te bepalen heb je de index van een token nodig. Verander in de for-lus voor regelTokens de variabele voor tokens in ieder geval in eentje voor indices (zoals op slide 7 van week 4, 16 mei: PDF).

Opdracht 5.3

Schrijf een Pythonprogramma dat voor onze Twitterdata de volgende kenmerken telt of uitrekent:

  1. het totale aantal tokens (alle woorden mogen worden omgezet in kleine letters)
  2. het aantal keren dat elk token voorkomt
  3. het totale aantal bigrammen (tokenparen)
  4. het aantal keren dat elk bigram voorkomt
  5. de pointwise mutual informationscore van elk bigram

De pointwise mutual information wordt uitgelegd op de collegeslides (theoriedeel). Hierbij kunnen de volgende opmerkingen worden gemaakt voor deze opdracht:

Het programma moet gecomprimeerde Twitterbestanden kunnen verwerken op dezelfde manier als de programma's van de opdrachten 5.1 en 5.2. De code van deze twee opdrachten mogen worden hergebruikt.

Het programma moet in de uitvoer voor elk gevonden bigram de volgende informatie op het scherm laten zien:

Hier is een voorbeeld van de interactie met het programma:

$ python3 53.py pt11/2011052119.out.gz | grep sint | sort -nr
6.410061434983907 sinterklaastijd ingingen 1 1 1
6.109031439319927 sinto saudades 1 1 2
6.109031439319927 sinterklaasja daahaag 1 1 2
6.109031439319927 sentimentele sinterklaasgek 2 2 2
5.932940180264245 sintpersonage :)... 1 1 3
5.808001443655946 sinterklaascadeautje :? 1 1 4
5.711091430647889 meerde sinterklazen 1 1 5
...

De uitvoer hoeft niet te worden gesorteerd. Het mag wel maar je mag ook het Linuxcommando sort gebruiken om de bigrammen met de hoogste scores bovenin de resultaten te krijgen,

Opdracht 5.4

Als het goed is dan kan jouw oplossingsprogramma voor opdracht 5.3 pointwise-mutual-information-scores uitrekenen maar de woordparen met de hoogste scores in de uitvoer blijken geen goede collocaties te zijn. Voor het voorbeeldcommando van opdracht 5.3 waren betere bigrammen: "dag sinterklaasje" en "nieuwe sint". Sla (een gedeelte van) de uitvoer van het programma op in een bestand en bekijk het bestand. Zoek een paar goede collocaties op en vergelijk hun scores en frequenties met die van de hoogstscorende paren. Zie je verschillen tussen de scores en frequenties?

Bedenk een methode om je programma van opdracht 5.3 te veranderen zodanig dat de betere collocaties ook de hoogste pointwise-mutual-information-scores krijgen toegewezen. Voeg enkele commando's toe aan je programma en test of je ideeën werken. Stuur het aangepaste programma met de testresultaten op en vermeld ook wat jouw ideeën voor verbetering waren en wat jouw verwachtingen daarvoor waren.

Hou er rekening mee dat er geen perfecte oplossing is waarmee alle goede collocaties uit een tekst kunnen worden gehaald. Er zijn verschillende methodes om de uitvoer van het programma voor opdracht 5.3 te verbeteren. Sommige daarvan werken beter dan andere.


Lever jouw programma's, testresultaten en antwoorden op vragen in op Nestor samengevoegd in 1 tekstbestand met naam studentnummer-weeknummer.txt, bijvoorbeeld s1234567-5.txt, voor dinsdag 31 mei 2011, 14:00 woensdag 1 juni 2011, 09:00 AM.
Antwoorden
Last update: June 07, 2011. erikt(at)xs4all.nl