Bij het bestuderen van relaties tussen hersenfunctie en taal ontdekten psychologen van de universiteit van Alberta (Canada) samen met taalkundigen van de universiteit van Tübingen (Duitsland) dat mensen het vrijwel unaniem eens zijn over de grappigheid van onzinnige woorden. Een overzicht van enkele onzinnige woorden die in dit onderzoek als extreem humoristisch voorspeld werden:

woord 1-grammen 2-grammen 3-grammen
howaymb 1.06771 0.09682 0.00699
proffic 1.33591 0.19497 0.03164
subvick 1.21500 0.14689 0.02015
quarban 1.38082 0.19559 0.02078
supplic 1.50944 0.20794 0.02595
octeste 2.00986 0.44417 0.06772
tatinse 2.06316 0.47488 0.10412

De studie toont aan dat hoe kleiner de kans dat een willekeurige opeenvolging van letters een bestaand (Engels) woord vormt, hoe grappiger die combinatie van letters overkomt op mensen. Hoe zou dat komen? Misschien signaleert humor onszelf en anderen wel dat er vermoedelijk iets niet klopt, maar dat er geen gevaar dreigt voor onze veiligheid.

Opgave

In de studie wordt de mate van grappigheid van een reeks letters als volgt gekwantificeerd. Neem een corpus van bestaande woorden (bijvoorbeeld woorden.txt1) en tel hoe vaak elk $$n$$-gram voorkomt (een $$n$$-gram is een opeenvolging van $$n$$ letters). Zo heeft het woord banaan bijvoorbeeld de volgende bigrammen (2-grammen): ba, an, na, aa en an. Merk op dat het bigram an tweemaal in dit woord voorkomt en de bigrammen ba, na en aa slechts eenmaal. Het aantal voorkomens van een $$n$$-gram $$\text{x}$$ in een gegeven corpus wordt voorgesteld als $$O(\text{x})$$. Zo tellen we bijvoorbeeld 118845 voorkomens van de letter (1-gram) a in het corpus uit het bestand woorden.txt2 waardoor $$O(\text{a}) = 118845$$, 2506 voorkomens van het bigram qu waardoor $$O(\text{qu}) = 2506$$ en 722 voorkomens van het trigram (3-gram) que waardoor $$O(\text{que}) = 722$$.

De waarschijnlijkheid van een $$n$$-gram $$\text{x}$$ (voorgesteld als $$P(\text{x})$$) wordt geschat door $$O(\text{x})$$ te delen door het totaal aantal $$n$$-grammen in het corpus. Op die manier kunnen we voor het corpus uit het bestand woorden.txt3 bijvoorbeeld bepalen dat $$P(\text{a}) = 0.07567$$, $$P(\text{qu}) = 0.001793$$ en $$P(\text{que}) = 0.0005894$$.

De entropie van een $$n$$-gram $$\text{x}$$ (voorgesteld als $$E(\text{x})$$) wordt berekend als \[ E(\text{x}) = - P(\text{x}) \log_2 P(\text{x})\] Hierbij geldt per definitie dat $$E(\text{x}) = 0$$ als $$P(\text{x}) = 0$$, wat consistent is met de limiet \[ \lim_{p \rightarrow 0+} p \log_2 p = 0 \]

Voor een gegeven $$n \in \mathbb{N}_0$$ wordt de grappigheid van een reeks letters $$s_1s_2s_3\ldots s_m$$ (met $$m \geq n$$) dan berekend als de som van de entropie van alle $$n$$-grammen in de reeks letters \[ E(s_1\ldots s_n) + E(s_2\ldots s_{n+1}) + E(s_3\ldots s_{n+2}) + \cdots \]

Gevraagd wordt:

De functies waarschijnlijkheid, entropie en grappigheid mogen geen onderscheid maken tussen hoofdletters en kleine letters.

Voorbeeld

In onderstaande voorbeeldsessie gaan we ervan uit dat het tekstbestand woorden.txt4 zich in de huidige directory bevindt.

>>> letters = ngrammen(1, 'woorden.txt')
>>> letters['a']
118845
>>> letters['q']
2535
>>> letters['z']
7450
>>> bigrammen = ngrammen(2, 'woorden.txt')
>>> bigrammen['ac']
6799
>>> bigrammen['qu']
2506
>>> bigrammen['zx']
Traceback (most recent call last):
KeyError: 'zx'
>>> trigrammen = ngrammen(3, 'woorden.txt')
>>> trigrammen['abc']
2
>>> trigrammen['que']
722
>>> trigrammen['xcz']
Traceback (most recent call last):
KeyError: 'xcz'

>>> waarschijnlijkheid('a', letters)
0.07567142511492862
>>> waarschijnlijkheid('Q', letters)
0.0016140945152622664
>>> waarschijnlijkheid('z', letters)
0.00474359137621455
>>> waarschijnlijkheid('ac', bigrammen)
0.0048643609543276645
>>> waarschijnlijkheid('QU', bigrammen)
0.001792923746366396
>>> waarschijnlijkheid('Zx', bigrammen)
0.0
>>> waarschijnlijkheid('abc', trigrammen)
1.6327943479190852e-06
>>> waarschijnlijkheid('QUE', trigrammen)
0.0005894387595987898
>>> waarschijnlijkheid('XcZ', trigrammen)
0.0

>>> entropie('a', letters)
0.28180852742167367
>>> entropie('Q', letters)
0.014970822223506234
>>> entropie('z', letters)
0.03661959827269034
>>> entropie('ac', bigrammen)
0.03737548277295434
>>> entropie('QU', bigrammen)
0.016357686287373385
>>> entropie('Zx', bigrammen)
0.0
>>> entropie('abc', trigrammen)
3.1389206700115134e-05
>>> entropie('QUE', trigrammen)
0.006323717369962047
>>> entropie('XcZ', trigrammen)
0.0

>>> grappigheid('howaymb', letters)
1.0677136135941063
>>> grappigheid('howaymb', letters, genormaliseerd=False)
1.0677136135941063
>>> grappigheid('howaymb', letters, genormaliseerd=True)
0.15253051622772948
>>> grappigheid('Subvick', letters)
1.2150001024776427
>>> grappigheid('QUARBAN', letters)
1.3808215071539807

>>> grappigheid('howaymb', bigrammen)
0.09682092801393552
>>> grappigheid('howaymb', bigrammen, genormaliseerd=False)
0.09682092801393552
>>> grappigheid('howaymb', bigrammen, genormaliseerd=True)
0.01613682133565592
>>> grappigheid('Subvick', bigrammen)
0.14689473722037735
>>> grappigheid('QUARBAN', bigrammen)
0.19558791736702053

>>> grappigheid('howaymb', trigrammen)
0.006989174063509218
>>> grappigheid('howaymb', trigrammen, genormaliseerd=False)
0.006989174063509218
>>> grappigheid('howaymb', trigrammen, genormaliseerd=True)
0.0013978348127018435
>>> grappigheid('Subvick', trigrammen)
0.020151762537186854
>>> grappigheid('QUARBAN', trigrammen)
0.020777229925614614

Bronnen