Allereerst leuk dat je mijn tweede blog in de reeks van blogs over Natural Language Processing (NLP) leest! In dit artikel ga ik in op het “Document Similarity” probleem.
In juli 2013 kreeg Patrick Juola een e-mail van een journalist van de Londense Sunday Times met de vraag of hij kon helpen bij het oplossen van een mysterie: het leek erop dat een auteur onder de naam Robert Galbraith de misdaadroman The Cuckoo’s Calling had gepubliceerd en dat de echte schrijver erachter de beroemde auteur van Harry Potter, J.K. Rowling, was. In Natural Language Processing (NLP-) termen valt het werk van Juola onder de taak van Authorship Attribution (AA), welke zich richt op het identificeren van de auteur van een document gegeven andere teksten van bekend auteurschap.
Wanneer men bijvoorbeeld wetenschappelijke of technische papers bekijkt, kan men, afhankelijk van de use-case, eerder naar de inhoud dan naar de auteur ervan kijken. Bijvoorbeeld een student milieuwetenschappen die een artikel over klimaatverandering leest en geïnteresseerd is in het vinden van soortgelijke publicaties over hetzelfde onderwerp. Of een advocaat die een rechtszaak onderzoekt en geïnteresseerd is in vergelijkbare zaken uit het verleden. Of tot slot iemand die op zoek is naar een bepaalde baan en op zoek is naar vergelijkbare functies.
De uitdaging die ik vandaag behandel in dit blog: Hoe kunnen we, gegeven een reeks documenten, automatisch de meest vergelijkbare vinden?
Dit is het Document Similarity probleem.
Neem de volgende drie zinnen als voorbeeld:
- How are you? (Hoe gaat het met je?)
- How old are you? (Hoe oud ben je?)
- What is your age? (Wat is je leeftijd?)
Als we kijken naar woordoverlap in deze drie zinnen, zien we dat drie van de vier woorden in de tweede zin ook voorkomen in de eerste zin. Daarom kunnen ze als gelijkaardige zinnen worden beschouwd. Maar vanuit betekenisperspectief kunnen we gerust concluderen dat de twee zinnen niet hetzelfde betekenen. Anderzijds hebben zin 2 en zin 3 geen woorden gemeen, maar zijn ze qua betekenis wel gelijkwaardig.
Het eerste noemen we lexicale gelijkenis, het tweede semantische gelijkenis. In het eerste geval baseren wij ons op woordoverlapping: hoe meer woorden de zinnen gemeen hebben, hoe groter de mate van gelijkenis. Maar om rechtszaken uit het verleden, functiebeschrijvingen of soortgelijke stukken over hetzelfde onderwerp te vinden, willen we eigenlijk kijken naar de semantische gelijkenis.

Als je JoinSeven kent, heb je al kennis gemaakt met Codi, onze virtuele beleidsassistent (zo niet, check dan zeker deze link!). We ontwikkelen Codi om beleidsmedewerkers onder meer te helpen bij het beantwoorden van kamervragen. Eén van de doelen van Codi is om gelijksoortige documenten aan elkaar te koppelen, zodat wanneer een medewerker zoekt naar een specifiek document over bijvoorbeeld energietransitie, Codi ook documenten toont die relevant zouden kunnen zijn voor de betreffende zaak. Bijvoorbeeld eerder gestelde kamervragen over hetzelfde onderwerp, misschien over een andere Gemeente. Hoewel deze functionaliteit specifiek is bedacht om de gelijkenis tussen kamervragen te bepalen, zijn wij van plan deze ook uit te breiden naar toezeggingen, moties, rapporten en andere openbare informatie.
Een andere belangrijke toepassing van het Document Similarity probleem binnen JoinSeven is het identificeren van wanneer hetzelfde document is gepubliceerd op verschillende officiële websites. In dit geval kunnen de bron en misschien de publicatiedatum verschillen, maar de tekst blijft hetzelfde: hier verwachten we hoge similariteitsscores.
Semantische gelijkenis is dus een van de belangrijkste aandachtsgebieden in onze oplossingen.Voor iemand met een basiskennis van de Engelse taal is het natuurlijk vrij gemakkelijk om te zeggen dat “How old are you?” (Hoe oud ben je?) en “What is your age?” (Wat is je leeftijd?) semantisch op elkaar lijken. De reden daarvoor is dat wij, mensen, de betekenis achter woorden begrijpen: we weten bijvoorbeeld dat “veroudering” te maken heeft met “ouder worden”, en daarom lijkt het verband tussen de twee zinnen nog duidelijker. Niet alleen herkennen we dat de twee zinnen semantisch op elkaar lijken, maar we hebben ook een gevoel voor de sociale context waarin ze kunnen worden gebruikt: de eerste is meer informeel, terwijl de tweede meer in formele contexten wordt gebruikt.
Maar hoe weet een computer dat het woord “age” niet gewoon de som is van drie tekens (a+g+e) die in een opeenvolgende volgorde zijn geschreven? Hoe herkent hij dat “Hoe oud ben je?” en “Wat is je leeftijd?”, ook al hebben ze geen woorden gemeen, toch dezelfde betekenis hebben?
Zoals ik beschreef in mijn vorige blog, moeten we woorden (en dus zinnen) omzetten in een taal die de computer kan begrijpen: nummers, en meer specifiek vectoren. Vervolgens kunnen we die vectoren vergelijken met een vergelijkingsalgoritme, wat niets anders is dan een wiskundige berekening.

De gedachte hierachter is dat hoe dichter de vectoren bij elkaar liggen, hoe meer de zinnen op elkaar lijken.
Om te bepalen hoeveel twee zinnen op elkaar lijken, kunnen we de “cosine” berekenen van de hoek die wordt gevormd door de vectoren van de twee zinnen: hoe kleiner de hoek, hoe groter de cosinus tussen de vectoren, hoe meer de twee zinnen op elkaar lijken. Zoals u kunt zien in de figuur hierboven, is, wanneer gevisualiseerd in de vectorruimte, de hoek α kleiner dan de hoek β, wat bevestigt dat “Hoe oud ben je?” en “Wat is je leeftijd?” meer op elkaar lijken dan “Hoe oud ben je?” en “Hoe ben je?”.
Natuurlijk wordt deze berekening niet met de hand gemaakt. Er zijn specifieke methoden die dit voor ons berekenen: de zojuist beschreven methode, die ook de meest gebruikte is, heet Cosine Similarity.
Tegenwoordig is er een familie van krachtige hulpmiddelen (Transformers genoemd) die potentieel elke NLP-taak met een hoge mate van preciezie kunnen uitvoeren, waaronder Document Similarity. GPT3, bijvoorbeeld, is een model dat ongeveer 175 miljard parameters voor machine learning heeft geleerd, en statistische voorspellingen kan doen over nieuwe gegevens. Transformers laten gebruikers echter niet zien wat er in hen gebeurt, en zijn daarom nauwelijks aanpasbaar.
Bij JoinSeven willen we controle hebben over de bewerkingen die we op de gegevens uitvoeren. We willen niet alleen weten wat er in een model gebeurt, maar ook waarom, en wat we kunnen doen om het te verbeteren. Daarom experimenteren we ook met meer klassieke methoden, zoals Doc2vec, of Top2vec.