Politician Translator avec Spacy et Negate
Découvrez ce que les politiciens veulent vraiment dire en changeant leur texte en son contraire.

Ceci est un court message. Nous entendons tout le temps ces politiciens parler mais la plupart du temps, ils veulent dire le contraire. Par exemple, si un politicien dit qu'il va baisser les impôts, les impôts vont augmenter. Si un politicien dit qu'il n'a pas eu de relation avec cette femme, alors ... Etc.
J'ai donc pensé, pourquoi ne pas faire un Politician Translator en Python ? Dans ce post, je commence par les résultats. Le code est à la fin.
Le Politician Translator en action
Joe Biden le 9 janvier 2023 (Twitter) :
Les deux premières années de ma présidence ont été les deux plus fortes années de croissance de l'emploi jamais enregistrées.
Ces gains historiques en matière d'emploi et de chômage donnent plus de pouvoir aux travailleurs et plus de souffle aux familles américaines.
Politician Translator:
Les deux premières années de ma présidence n'ont pas été les deux plus fortes années de croissance de l'emploi jamais enregistrées.
Ces gains historiques en matière d'emploi et de chômage ne donnent pas plus de pouvoir aux travailleurs et plus de souffle aux familles américaines.
Bill Clinton il y a 15 ans :
Je n'ai pas eu de relations sexuelles avec cette femme, Mlle Lewinsky.
Politician Translator:
J'ai eu des relations sexuelles avec cette femme, Mlle Lewinsky.
Joe Biden le 6 janvier 2023 (Twitter) :
Mon plan économique a toujours été de faire croître notre économie du bas vers le haut et du milieu vers l'extérieur.
Aujourd'hui, nous avons appris que le chômage est à son plus bas niveau depuis 50 ans après les deux plus fortes années de croissance de l'emploi jamais enregistrées.
Nous créons des emplois. Nous réduisons les coûts. Notre plan fonctionne.
Politician Translator:
Mon plan économique n'a pas toujours été de faire croître notre économie du bas vers le haut et du milieu vers l'extérieur.
Aujourd'hui, nous n'avons pas appris que le chômage n'est pas à son plus bas niveau depuis 50 ans après les deux plus fortes années de croissance de l'emploi jamais enregistrées.
Nous ne créons pas d'emplois. Nous ne réduisons pas les coûts. Notre plan ne fonctionne pas.
N'aimez-vous pas ça ?
Le Politician Translator peut aussi être utilisé pour former les politiciens.
Par exemple, ils doivent dire :
J'aime le beurre de cacahuètes et j'en mange tous les jours.
Alors qu'ils veulent dire en réalité :
Je n'aime pas le beurre de cacahuètes et je n'en mange pas tous les jours.
Un autre exemple. Ils doivent dire :
Mon premier anniversaire était génial. Mon 2. était encore mieux.
Alors qu'ils veulent dire :
Mon premier anniversaire n'était pas génial. Mon deuxième anniversaire n'était pas encore mieux.
Quelques details sur le code
J'ai eu cette idée et j'ai d'abord envisagé d'utiliser antonymes. Trop complexe pour un projet court, peut-être dans une prochaine version. Puis j'ai trouvé le paquet Python 'Negate'. Très bien, mais il ne peut pas gérer les phrases composées.
J'ai donc cherché un moyen de décomposer les phrases en parties. Pour ce faire, nous utilisons le POS-tags d'une phrase. Bien que très primitif, ce système fonctionne dans de nombreux cas.
Une fois que nous avons les parties d'une phrase, nous lançons 'Negate' sur elles, et les recollons ensemble. Puis quelques corrections, et c'est fini.
Politician Translator : Le code
# your text
text = """The first two years of my presidency were the two strongest years of job growth on record.
These historic jobs and unemployment gains are giving workers more power and American families more breathing room.
"""
text = """I did not have sexual relations with that woman, Miss Lewinsky."""
#text = """I like peanut butter and eat it every day."""
#text = """My first birthday was great. My 2. was even better."""
import re
from negate import Negator
import spacy
from spacy.lang.en import English
class TextToSentences:
def __init__(self):
self.nlp = spacy.load('en_core_web_sm')
self.nlp.add_pipe('sentencizer')
def get_sentences(self, text):
doc = self.nlp(text)
return [sent.text.strip() for sent in doc.sents]
class SentenceToParts:
def __init__(self):
self.nlp = spacy.load('en_core_web_sm')
def get_parts(self, sentence):
doc = self.nlp(sentence)
parts, words = [], []
for token in doc:
if token.pos_ in ['CCONJ', 'SCONJ']:
parts.append(' '.join(words))
words = []
words.append(token.text)
if len(words) > 0:
parts.append(' '.join(words))
return parts
class NegateParts:
def __init__(self):
self.negator = Negator(use_transformers=True)
def get_negated_parts(self, parts):
negated_parts = []
for part in parts:
negated_parts.append(self.negator.negate_sentence(part, prefer_contractions=False))
return negated_parts
class StitchParts:
def __init__(self):
self.nlp = spacy.load('en_core_web_sm')
def get_stitched_parts(self, parts):
stitched_parts_items = []
for i, part in enumerate(parts):
# first word to lowercase if not PROPN
doc = self.nlp(part)
words = []
for j, token in enumerate(doc):
word = token.text
if i > 0 and j == 0 and token.pos not in ['PROPN']:
word = word.lower()
words.append(word)
stitched_parts_items.append(' '.join(words))
return ' '.join(stitched_parts_items)
class FixUpSentence:
def __init__(self):
pass
def get_fixedup_sentence(self, sentence):
# trim
sentence = sentence.strip()
# fix: end of line ' .'
sentence = re.sub(r'\s\.$', '.', sentence)
# fix: ' ’s'
sentence = sentence.replace(' ’s', '\'s')
# fix: ' , '
sentence = sentence.replace(' , ', ', ')
return sentence
tts = TextToSentences()
stp = SentenceToParts()
np = NegateParts()
sp = StitchParts()
fus = FixUpSentence()
# step 1: split text into sentences
sentences = tts.get_sentences(text)
ftext_items = []
for sentence in sentences:
# step 2.1: split sentence into sub-sentences
parts = stp.get_parts(sentence)
# step 2.2: negate sub-sentences
nparts = np.get_negated_parts(parts)
# step 2.3: create sentences from sub-sentences
nsentence = sp.get_stitched_parts(nparts)
#print('nsentence = {}'.format(nsentence))
fsentence = fus.get_fixedup_sentence(nsentence)
# step 2.4: Remove spaces etc.
ftext_items.append(fsentence)
# step 3: join sentences
ftext = ' '.join(ftext_items)
print('what they say = \n{}'.format(text))
print('what they mean = \n{}'.format(ftext))
Résumé
Je pourrais dire que je n'ai pas apprécié ce petit projet, mais alors vous utiliseriez le Politician Translator et vous sauriez ce que je veux vraiment dire ... ;-)
Liens / crédits
How to break up document by sentences with Spacy
https://stackoverflow.com/questions/46290313/how-to-break-up-document-by-sentences-with-spacy
Negate
https://pypi.org/project/negate
Tutorial on Spacy Part of Speech (POS) Tagging
https://machinelearningknowledge.ai/tutorial-on-spacy-part-of-speech-pos-tagging
En savoir plus...
Machine Learning
Récent
- PostgreSQL backup avec Docker SDK pour Python
- Empêcher l'envoi de messages en double à un système distant
- Politician Translator avec Spacy et Negate
- Du code monolithique aux services avec RabbitMQ et Pika
- Application Flask montrant stdout et stderr d'un travail en arrière-plan
- Agrégation et journaux de conteneurs Q4_6513_TNEMECALPER_4 Docker utilisant le SDK Docker pour Python
Les plus consultés
- Flask RESTful API validation des paramètres de la requête avec les schémas Marshmallow
- Utilisation des Python's pyOpenSSL pour vérifier les certificats SSL téléchargés d'un hôte
- Utiliser UUIDs au lieu de Integer Autoincrement Primary Keys avec SQLAlchemy et MariaDb
- Utiliser PyInstaller et Cython pour créer un exécutable Python
- Connexion à un service sur un hôte Docker à partir d'un conteneur Docker
- SQLAlchemy : Utilisation de Cascade Deletes pour supprimer des objets connexes