No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

¿Cómo extraer n-gramas de un texto en Python?

11/24
Recursos

Aportes 20

Preguntas 1

Ordenar por:

Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Regístrate o inicia sesión para participar.

Configuración inicial

import nltk 
nltk.download("book")
from nltk.book import *
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import plotly.express as px
from nltk.util import ngrams

md_trigrams = list(ngrams(text1,3))# objeto que va a guardar una lista, el segundo argumento es la cantidad de palabras que quiero extraer
#list es para que lo pueda mostrar 

filtered_trigrams = [trigram for trigram in md_trigrams if len(trigram[0]) > threshold and len(trigram[1]) > threshold and len(trigram[2]) > threshold]

fdist = FreqDist(filtered_trigrams)
print(fdist.most_common(10)) 

fdist.plot(10)

Aquí dejo un ejemplo de como es que quedarían los tri-gramas ya filtrados y ploteados, además dejo el código comentado por si es que te ha surgido una duda de que hace cada paso 😃


from nltk.util import ngrams
# extraemos los trigramas
md_trigrams = list(ngrams(text1, 3))
# obtenemos su distribucion
fdist = FreqDist(md_trigrams)

# AHORA VAMOS A VER LOS MAS COMUNRES Y FILTRARLOS

# minimo de caracteres para las palabras de los bi-gramas
threshold = 2
# hacemos el filtrado
filtered_trigrams = [trigram for trigram in md_trigrams \
                    if len(trigram[0]) > threshold \
                    and len(trigram[1]) > threshold \
                    and len(trigram[2]) > threshold]

# obtenemos las distribuciones 
filtered_dist = FreqDist(filtered_trigrams)
# procedemos directamente al plot de los 20 mas comunes
filtered_dist.plot(20)

Sería interesante saber cual es el tamaño óptimo de un N-Grama para un texto cualquiera, calculo que las estadísticas para las colocaciones varían según el tamaño del n-grama.

por aqui dejo esto :

filtered = [trigram for trigram in trigrama if re.search("[a-z0-9]", trigram[0]) and re.search("[a-z0-9]", trigram[1]) and re.search("[a-z0-9]", trigram[2]) and len(trigram[0]) > 2 and len(trigram[1]) > 2 and len(trigram[2]) > 2]
filtered
fdist = FreqDist(filtered)
fdist.most_common(4)
fdist.plot(4)

Con estas 3 lineas de codigo reducimos la busqueda evitando las palabras sin valor que aparecen tanto en mayuscula como en minuscula

from nltk.corpus import stopwords
stop_words = stopwords.words('english')
c_stopwords = stop_words + [i.upper() for i in stop_words]

aun tenemos un problema y es las mayusculas y las minusculas

from nltk.util import ngrams
tgrams=list(ngrams(text1,3))
fd_tgrams=FreqDist(tgrams)
fd_tgrams.most_common(5)

threshold=2
filter_tgrams=[tgram for tgram in tgrams if len(tgram[0])>threshold and len(tgram[1])>threshold and len(tgram[2])>threshold]
fd_tgrams_filter=FreqDist(filter_tgrams)
fd_tgrams_filter.most_common(5)```

[(('the', 'Sperm', 'Whale'), 77),
 (('the', 'White', 'Whale'), 63),
 (('the', 'old', 'man'), 32),
 (('the', 'sperm', 'whale'), 30),
 (('the', 'Right', 'Whale'), 25)]
filtered_bigrams = [bigram for bigram in md_bigrams 
                     if not bigram[0] in stop_words 
                     and bigram[1] not in stop_words 
                     and bigram[0] in str(re.search('[a-zA-Z]{3,}', bigram[0]))
                     and bigram[1] in str(re.search('[a-zA-Z]{3,}', bigram[1]))
                     ]

Obtengo el siguiente error al ejecutar la primera celda del C5 ipynb.
import nltk
nltk.download(‘book’)
from nltk.book import *
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import plotly.express as px
Mi entorno es JupyterLab 1.2.6 dentro de la instalacion de Anaconda Navigator 1.9.7
¿Alguien sabe por qué?


ModuleNotFoundError Traceback (most recent call last)
<ipython-input-1-fde300df6df3> in <module>
5 import numpy as np
6 import pandas as pd
----> 7 import plotly.express as px

ModuleNotFoundError: No module named ‘plotly’

Filtrando los tri-gramas

threshold = 2
filtered_trigrams = (trigram for trigram in md_trigrams if len(trigram[0])>threshold and len(trigram[1])>threshold and len(trigram[2])>threshold)
filtered_trigrams_dist = FreqDist(filtered_trigrams)
filtered_trigrams_dist.most_common(10)
filtered_trigrams_dist.plot(10)

Cuando grafiqué los bigramas pude observar que algunos se repetían, debido a que a la minúscula y mayúscula. Así que después de importar las librerías le añadí las siguientes líneas para transformar las palabras a lowercase:

# stopwords
stop_words = stopwords.words('english')
# Eliminado de stopwords y conversión a lowercase
text1 = [word.lower() for word in text1 if word not in stop_words]

Ojalá más tarde no tenga que darme cuenta que no es correcto hacerlo.

Aquí una pequeña función para graficar n-gramas con un threshold variable

def plot_n_gram_freq(text: book.Text, threshold: int, n: int):
  freq_dist_gram = book.FreqDist(gram for gram in ngrams(text, n) if all(threshold < len(w) for w in gram))
  freq_dist_gram.plot(20)

plot_n_gram_freq(book.text1, 2, 3)

Metodo most_common para encontrar los bigramas mas comunes

  • Bi-gramas

    primero debemos traer las librerías que usaremos

    import nltk
    nltk.download('book')
    from nltk.book import *
    import matplotlib.pyplot as plt
    import numpy as np
    import pandas as pd
    import plotly.express as px  # Graficos para poder interactuar
    

    Después creamos los bi-gramas

    md_bigrams= list(bigrams(text1))
    fdist= FreqDist(md_bigrams)
    
    fdist.most_common(20)
    
    entrega
    
    [((',', 'and'), 2607),
     (('of', 'the'), 1847),
     (("'", 's'), 1737),
     (('in', 'the'), 1120),
     ((',', 'the'), 908),
     ((';', 'and'), 853),
     (('to', 'the'), 712),
     (('.', 'But'), 596),
     ((',', 'that'), 584),
     (('.', '"'), 557),
     ((',', 'as'), 523),
     ((',', 'I'), 461),
     ((',', 'he'), 446),
     (('from', 'the'), 428),
     ((',', 'in'), 402),
     (('of', 'his'), 371),
     (('the', 'whale'), 369),
     (('.', 'The'), 369),
     (('and', 'the'), 357),
     ((';', 'but'), 340)]
    

    fdist.plot(10)

    Filtrado

    threshold = 2
    filtered_dist = [bigram for bigram in md_bigrams if len(bigram[0])>threshold and len(bigram[1])>threshold]
    filtered_dist = FreqDist(filtered_dist)
    filtered_dist.plot(20)
    
  • Tri-gramas

    se importa el paquete ngrams

    from nltk.util import  ngrams
    md_trigrams = list(ngrams(text1, 3))
    fdist = FreqDist(md_trigrams)
    fdist.most_common(10)
    

Si se filtran los trigramas al igual que lo hicimos con los bigramas, queda esto 👀

Para N-grams, es decir una funcion para sacar sus distribucion de frecuencias

def get_ngrams_fdist(text, n, threshold=2):
    md_ngrams = list(ngrams(text, n))
    filtered = [
        ngram for ngram in md_ngrams if all([
            len(word) > threshold for word in ngram]
        )
    ]
    fdist = FreqDist(filtered)
    return fdist

Asi pueden experimentar con diferentes n-grams con diferentes filtros.

Código para el gráfico filtrado de los trigramas:

threshold_3 = 3
filtered_trigrams = [trigram for trigram in md_trigrams if len(trigram[0]) > threshold_3 and len(trigram[1]) > threshold_3 and len(trigram[2]) > threshold_3]
filtered_dist_2 = FreqDist(filtered_trigrams)
filtered_dist_2.plot(20)

Muy buen curso, una muy buena explicación de los n-gramas

(Alguien sabe por qué Google Colab no suele conectar? Me ha apsado dos veces que Google Colab se desconecta y no vuelve a conectar por el resto del día. (Tengo espacio disponible, cookies activadas, uso Chrome…) )

Gran clase, en alguna ocasión vi el concepto de n-grama, no lo había aterrizado, ahora todo mas claro