angle-uparrow-clockwisearrow-counterclockwisearrow-down-uparrow-leftatcalendarcard-listchatcheckenvelopefolderhouseinfo-circlepencilpeoplepersonperson-fillperson-plusphoneplusquestion-circlesearchtagtrashx

Politician Translator con Spacy y Negate

Averigua qué quieren decir realmente los políticos cambiando su texto por el contrario.

11 enero 2023
post main image
https://www.pexels.com/nl-nl/@pixabay

Este es un post corto. Todo el tiempo oímos hablar a los políticos, pero la mayoría de las veces quieren decir lo contrario. Por ejemplo, si un político dice que va a bajar los impuestos, los impuestos subirán. Si un político dice que no una relación con esa mujer, entonces ... Etc.

Así que pensé, ¿por qué no hacer un Politician Translator en Python? En este post, empiezo con los resultados. El código está al final.

El Politician Translator en acción

Joe Biden el 9 de enero de 2023 (Twitter):

Los dos primeros años de mi presidencia han sido los dos años de mayor crecimiento del empleo jamás registrados.
Estos avances históricos en empleo y desempleo están dando más poder a los trabajadores y más respiro a las familias estadounidenses.

Politician Translator:

Los dos primeros años de mi presidencia no fueron los dos años de mayor crecimiento del empleo jamás registrados.
Estos aumentos históricos del empleo y el desempleo no están dando más poder a los trabajadores ni más respiro a las familias estadounidenses.

Bill Clinton hace 15 años:

No tuve relaciones sexuales con esa mujer, la Srta. Lewinsky.

Politician Translator:

Tuve relaciones sexuales con esa mujer, la señorita Lewinsky.

Joe Biden el 6 de enero de 2023 (Twitter):

Mi plan económico siempre ha sido hacer crecer nuestra economía de abajo arriba y de la mitad hacia afuera.
Hoy hemos sabido que el desempleo está en el nivel más bajo de los últimos 50 años tras los dos años de mayor crecimiento del empleo de la historia.
Estamos creando empleo. Estamos reduciendo costes. Nuestro plan funciona.

Politician Translator:

Mi plan económico no siempre ha consistido en hacer crecer nuestra economía de abajo arriba y de la mitad hacia fuera.
Hoy no nos hemos enterado de que el desempleo no está en su nivel más bajo en 50 años tras los dos años de mayor crecimiento del empleo de la historia.
No estamos creando empleo. No estamos reduciendo los costes. Nuestro plan no funciona.

¿No os encanta?

El Politician Translator también puede utilizarse para formar a los políticos.

Por ejemplo, deben decir:

Me gusta la mantequilla de cacahuete y la como todos los días.

Cuando en realidad quieren decir:

No me gusta la mantequilla de cacahuete y no la como todos los días.

Otro ejemplo. Deben decir:

Mi primer cumpleaños fue genial. Mi 2. fue aún mejor.

Cuando quieren decir:

Mi primer cumpleaños no fue genial. Mi 2 . no fue aún mejor.

Algunas details sobre el código

Tuve esta idea y primero estaba mirando a usar antonymes. Demasiado complejo para un proyecto corto, tal vez en una próxima versión. Entonces encontré el paquete Python 'Negate'. Muy bonito, pero no puede manejar frases compuestas.

Así que busqué una forma de dividir las frases en partes. Para ello utilizamos el POS-tags de una frase. Aunque es muy primitivo, funcionará en muchos casos.

Una vez tenemos las partes de una frase, ejecutamos 'Negate' sobre ellas, y las volvemos a pegar. Luego algo de arreglo, y listo.

Politician Translator: El código

# 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))

Resumen

Podría decir que no he disfrutado con este corto proyecto, pero entonces usarías el Politician Translator y sabrías lo que realmente quiero decir... ;-)

Enlaces / créditos

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

Deje un comentario

Comente de forma anónima o inicie sesión para comentar.

Comentarios

Deje una respuesta.

Responda de forma anónima o inicie sesión para responder.