Een woordenwolk kan gebruikt worden om een (lange) tekst in een
beperkt aantal steekwoorden samen te ballen.
Een woordenwolk bestaat uit een aantal woorden van verschillende
grootte.
De maat van de letters in een woord is meestal een aanduiding voor het
belang van dat woord in de tekst.
Op tagcrowd.com kan je zelf
woordenwolken maken van een tekst.
In deze opdracht maken we een vergelijkbare site, maar met andere
mogelijkheden voor de gebruiker.
We maken de site in een aantal stappen waarbij in elke stap een
bepaald aspect van programmeren in PHP aan de orde komt.
Stap Analyse Ga naar tagcrowd.com en experimenteer met
alle mogelijkheden.
Lees het Wikipedia artikel over tagclouds op http://en.wikipedia.org/wiki/Tagcloud.
Opdracht
- In het Wikipedia artikel worden allerlei soorten tagclouds behandeld. Hoe worden de tagclouds in dat artikel genoemd die gemaakt worden op tagcrowd.com?
- Bekijk de prachtige tagcloud op deze pagina. Dat is een woordenwolk van deze pagina. Toch staan er vreemde woorden (of misschien beter gezegd "tokens") op. Waar komen die vandaan? Wat is hier mis gegaan? Leg je antwoord uit, en geef voorbeelden van tokens die niet in de wolk thuishoren.
Stap HTML formulier en PHP antwoord
Om een website te maken waar een gebruiker iets kan doen is er interactie nodig. Die interactie programmeren we met behulp van HTML formulieren.
Techniek De volgende literatuur behandelt deze stof.
Specifiek over het uploaden van files gaat dit stuk in de php.net tutorial. Hier leer je hoe je een file lokaal kan opslaan. De tekst uit een file opslaan als 1 string gaat heel eenvoudig met de file_get_contents() functie.
Opdracht
-
Maak een invoerscherm voor jouw woordenwolk
site. Maak een formulier waarmee de gebruiker
- een stuk tekst kan intypen of plakken, en
- een (tekst) file kan uploaden.
- We willen ook dat de gebruiker een antwoord krijgt, en weet dat het
opgestuurde goed is aangekomen.
Schrijf een PHP script dat reageert als de gebruiker
op submit heeft gedrukt en dan als antwoord het volgende laat
zien:
- (mits dit gebeurt is natuurlijk) de naam van de opgestuurde file, en
- de opgestuurde tekst geplaatst in een apart blok op de webpagina
met een gele achtergrond.
Stap Van een tekst naar een rijtje woorden. Stel je
tekst is via een het invoerveld ingevoerd en opgeslagen in de
variabele $InvoerTekst.
Nu willen we de losse woorden uit die tekst halen.
Dit proces wordt tokenization genoemd: een tekst opsplitsen in
tokens.
In de meeste Westerse landen wordt de spatie gebruikt op woorden te
scheiden. Dus als we de tekst splisen op spaties zijn we
waarschijnlijk al een mooi eind op weg.
Techniek
Het Wikipedia artikel over taal analyse bevat een sectie over tokenization.
We hebben de notie van een rijtje (een
array) nodig om alle woorden in de tekst in de volgorde waarin
ze in die tekst staan op te slaan.
$InvoerTekst = "Hello World.";
$woorderijtje = array("Hello",
"World.");
(NB. Waarom zit die punt nou nog aan het laatste token
geplakt?)
We hebben een functie nodig waarin we een string
stoppen en een patroon wat dient als scheider en die dan een
array met de tokens in die string gescheiden door die
scheider teruggeeft. PHP heeft zo'n functie: preg-split().
Een simpelere functie waarin je alleen scheiders als strings kunt opgeven is explode().
Literatuur
Opdracht
- Splits je tekst op spaties met explode() en/of preg-split(). Begin met een zin bestaande uit zo'n
10 woorden. Dit is een mooie oefen zin:
$str = "Mary Had A Little Lamb and She LOVED It So. SO! Lets see what
happened to mary!";
- Oefen met een aantal array functies. Maak een PHP script waarin
je steeds in een h2 tag de opdracht zet, en meteen daaronder
jouw uitvoer programmeert, met een groene achtergrond.
- Print dat array uit.
- Sorteer het array en print het uit.
- Gebruik de PHP commandos foreach en echo om elk woord uit
het array op een nieuwe regel uit te printen, zonder kommas.
- Print de woorden in omgekeerde volgorde uit.
- Print de woorden in willekeurige volgorde uit.
- Vertel hoeveel woorden er in de zin zitten.
- Print elk woord slechts 1 keer uit. Dus dubbelen mogen
niet in je print zitten. Hoeveel unieke woorden zitten er in
je invoerstring?
- Neem nu een wat langere tekst als invoer en tel weer de
woorden. Plak die tekst ook in Word en tel daar ook de
woorden. Is er een verschil? Kan je dat verklaren?
Experimenteer net zo lang tot je een verschil krijgt.
- Er zitten vast ook allerlei leestekens in je lijst of aan
woorden geplakt. Kan je dat verklaren?
- Is er een verschil tussen deze teksten? Zou je
dezelfde lijst woorden eruit willen hebben, of juist niet?
Motiveer je antwoord en kijk wat er in jouw programma gebeurt.
* Hello World.
* Hello World.
* Hello
World.
* Hello World .
- Laat de gebruiker een getal n opgeven, en print
alleen het n-de woord uit. Zorg dat er iets intelligents
gebeurt als n te hoog wordt gekozen.
- Laat de gebruiker twee getallen n,m geven waarbij m
groter dan n. Laat nu alle woorden vanaf het n-de en tot en
met het m-de woord zien. Test eerst of inderdaad n kleiner dan
m, en zo nee geef een foutmelding.
-
Stap Op jacht naar patronen In de vorige opdracht zagen we
dat tokenization op spatie alleen niet voldoende is. We zullen een
meer ingewikkeld patroon moeten schrijven. Het efficient opschrijven
en opzoeken
van patronen gaat heel goed met zogenaamde reguliere expressies.
Techniek Reguliere expressies
Opdracht
- Wat betekent de reguliere expressie \W? Geef een beschrijving in woorden, en geef een preciese formele definitie in termen van een andere reguliere expressie. (Dat kan je als volgt doen: Stel je moet een definitie van a+ geven zonder + te gebruiken. Dan kan je zeggen dat a+ = aa*. Andersom kan ook a* = (a+)?.
- Maak een reguliere expressie die beter split dan alleen
spatie. Een Google search op 'tokenization' of 'tokenize text
regular expression' kan je goed helpen. Wikipedia ook trouwens.
- Splits je tekst opnieuw, maar nu met deze reguliere
expressie. Beschrijf de verschillen die je ziet in de verschillende
deelopdrachten van de vorige Stap.
-
Stap Woordjes tellen en een histogram maken
Eindelijk gaan we woordjes tellen en kunnen we dus beginnen met het
maken van een woordenwolk. Het eerste idee is dat hoe vaker een woord
voorkomt, hoe belangrijker het is, en dus hoe groter we het maken in
onze wolk.
Een hele handige en veel gebruikte data-structuur is de
dictionary, ook wel associative array of hash
array genoemd. Een dictionary, of kortweg dict, is een
verzameling van sleutel-waarde paren. Dicts zijn voor van alles te
gebruiken, maar ze danken hun naam aan het gebruik dat wij van ze gaan
maken: opslaan hoe vaak een woord in een tekst voorkomt. Het idee is
dat elk woord in een tekst een sleutel wordt met als waarde hoe vaak
dat woord in de tekst voorkomt.
Voorbeeld In onderstaand voorbeeld is de eerste variable een
tekst-string, de tweede een lijst (gewoon array), en de derde een dict
(associatief array).
$tekst = "Wie ben ik? Ik ben ik!";
$woordenlijst = array("Wie", "ben", "ik", "?", "Ik", "ben", "ik", "!");
$histogram = array("Wie => 1,
"ben" => 2,
"ik" => 2,
"?" => 1,
"Ik" => 1,
"!" => 1);
Opdracht
- Maak een dict zoals boven voor jouw lijst met woorden. Hint: gebruik foreach.
- Print die eerst uit als array, en daarna mooi met foreach en echo.
- Loop nu door het array en print die mooi uit als een HTML tabel,
als volgt:
- Doe hetzelfde als in de vorige vraag maar orden de woorden nu op
"populariteit", met het meest voorkomende woord eerst. Als meerdere
woorden even vaak voorkomen orden je die alfabetisch.
- Loop weer door de array en print het nu uit als een comma
separated value (csv) file, met ";" als scheider. Dus zo
"Wie";1
"ben";2
"ik";2
...
Zo'n file kan
je inladen in Excel met het commando import. Doe dat en maak er in
Excel een mooi histogram van. Maak nog een histogram maar nu met de
ordening uit de vorige vraag.
- Google kan je ook helpen om mooie plaatjes te maken. Zoek uit
hoe je een histogram maakt met Google charts, en maak zo'n
histogram.
- Maak nu je eerste woordenwolk door alle woorden 1-voor-1 binnen
een center HTML tag af te drukken. Zet om ieder woord een
span tag en plaats binnen die span tag (CSS) style
informatie over de font-size. Die font-size laat je natuurlijk
bepalen door het aantal keer dat een woord voorkwam. Voor de
leesbaarheid zal je de fontsize waarschijnlijk een functie moeten
laten zijn van de waarde van een woord. Hint: kijk eens hoe andere sites dit doen. Dit kan heel makkelijk op http://www.tag-cloud.de/. Onderaan geven ze gewoon de HTML code van hun woordenwolk. Als ze dat niet doen, kan je natuurlijk altijd met view page source in je browser de HTML code van een webpagina bekijken.
- Print die wolk nu ook eens alfabetisch geordend uit. Daarvoor
haal je de sleutels uit de dict met de keys() methode. Dat
levert je een lijst met alle sleutels op. Orden die
alfabetisch. Loop nu met foreach door die gesorteerde
lijst en druk voor elke sleutel (= woord) dat woord af.
- Experimenteer met kleuren.
- Orden nu eens de woorden in je woordenwolk op lengte van het woord.
- Maak ook een random ordening.
Stap Keuzes door de gebruiker. Voor de ene tekst wil je
de instellingen zus hebben en voor de andere zo. Je wilt de gebruiker
dus wat mogelijkheden geven om de gemaakte woordenwolk te
controleren.
Opdracht
Maak een formulier waarmee je de volgende dingen kan
instellen:
- Het maximaal aantal woorden in de wolk.
- Het minimale aantal keer dat een woord voorkomt in de tekst
voordat het in de wolk komt.
- Het lettertype waarin de woorden staan.
- De kleur waarin de woorden staan, de achtergrond kleur.
- Verschillende volgordes van de woorden
Stap Visueel aantrekkelijk maken. Bestudeer de
woordenwolken gemaakt op wordle.net. Wow, dat is nog eens
andere koek dan onze woordewolkjes.
Opdracht
Voeg toeters en bellen toe aan je woordenwolk applicatie. Het leukste
is als de gebruiker zelf dingen in kan stellen. Ook is het gebruik van
random dingen natuurlijk leuk. Een interresant iets is het varieren van
de functie die aantallen afbeeldt op lettergroottes.
Stap Linguistische verfijning Experimenteer met
verschillende teksten met je woordenwolken. Je zal zien dat ze er
nog niet zo goed uitzien als woordewolken die je gewend bent. Er
vallen je vast de volgende dingen op:
- alle leestekens kunnen wel weg
- Hetzelfde woord komt twee of meer keer voor door hoofdletters
(bijvoorbeeld "Ik" en "ik"). Dat hoeft niet.
- Allerlei woordjes die eigenlijk niks zeggen kunnen wel weg
(stopwoorden als "de", "het", "als",....)
- Verschillende vormen van hetzelfde woord zouden niet los in de
wolk moeten voorkomen , maar liever bij elkaar opgeteld. Voorbeeld:
"Nederland (5), Nederlands (7), Nederlanders (3), Nederlander(2)"
wordt "Nederlands(17)".
- Misschien willen we een feitelijk woordenwolk maken met alleen
zelfstandige naamwoorden. Of juist een subjectieve, met alleen de
bijvoegelijke naamwoorden erin. Zou dat kunnen? Dan moeten we de
computer de zinnetjes laten ontleden.
Opdracht
- Breidt het HTML-formulier uit een eerdere opdracht voor elke van de komende verbeteringen uit met een knop waarmee je ze aan en uit kan zetten, zodat je in stapjes kan laten
zien hoeveel beter je woordenwolk applicatie geworden is.
- Haal leestekens weg met preg\_replace().
- Vervang in alle woorden hoofdletters door kleine letters. Maak
nu een nieuwe woordenwolk. Voor deze taak zal PHP toch wel een functie op
strings hebben?
- Google op "Nederlands stopwoordenlijst". Vind een lijst die je
betrouwbaar acht. Download hem. Maak er een array van en schrijf een
php programmatje dat alle woorden in jouw lijst verwijdert die ook in
de stopwoorden lijst staan. Kijk eens goed rond in de lijst met
array-functies. Dit is zo'n gebruikelijke operatie, zou daar niet al
een PHP functie voor bestaan.....
- Bekijk de pagina over stemming in
Wikipedia. Dit is een brute manier om verschillende woorden die
komen van dezelfde stam terug te brengen tot 1 woord. Op die manier
kunnen we natuurlijk mooi dat probleem met Nederland van boven
oplossen.
- (1) Verzin een aantal voor de hand liggende regels om te
stemmen.
- (2) Verzin voor elke regel een
tegenvoorbeeld. (Bijvoorbeeld: ouders en ouderen stemmen allebei
naar ouder, maar ze kunnen heel wat anders betekenen. Voor een mooi
voorbeeld van Wilders, naar wilder, naar wild, zie deze
blogpost.
- (3) Implementeer je regels, en zorg dat je goed de waardes
bij elkaar optelt. Let op, je moet de regels wellicht een heleboel
keer toepassen! Hoe doe je dat? (Recursie! (Pas ze net zo lang toe
tot er niks meer veranderd.).
- (4) Bij stemming kan het zijn dat je
gekke woorden terugkrijgt die geen Nederlands meer zijn. Dat wil je
niet! Kies daarom voor elke groep van woorden die op elkaar gestemd
worden 1 woord uit dat je gebruikt om te laten zien. Op basis
waarvan kies je die? Argumenteer dat dit een goede keuze
is. Implementeer het.
- Lees dit Wikipedia artikel over Automatisch zins
ontleden (of part-of-speech tagging). Leg uit wat je hiermee kan
in je woordenwolk applicatie.