Clasificación de texto con Python y Scikit-Learn

    Introducción

    La clasificación de texto es una de las tareas más importantes en el procesamiento del lenguaje natural. Es el proceso de clasificar cadenas de texto o documentos en diferentes categorías, según el contenido de las cadenas. La clasificación de texto tiene una variedad de aplicaciones, como detectar la opinión del usuario a partir de un tweet, clasificar un correo electrónico como spam o ham, clasificar publicaciones de blog en diferentes categorías, etiquetar automáticamente las consultas de los clientes, etc.

    En este artículo, veremos un ejemplo del mundo real de clasificación de texto. Entrenaremos un modelo de Machine Learning capaz de predecir si una crítica de película determinada es positiva o negativa. Este es un ejemplo clásico de análisis sentimental en el que los sentimientos de las personas hacia una entidad en particular se clasifican en diferentes categorías.

    Conjunto de datos

    El conjunto de datos que vamos a utilizar para este artículo se puede descargar del Grupo de procesamiento del lenguaje natural de Cornell. El conjunto de datos consta de un total de 2000 documentos. La mitad de los documentos contienen críticas positivas sobre una película, mientras que la mitad restante contiene críticas negativas. Se pueden encontrar más detalles sobre el conjunto de datos en este enlace.

    Descomprima o extraiga el conjunto de datos una vez que lo descargue. Abra la carpeta “txt_sentoken”. La carpeta contiene dos subcarpetas: “neg” y “pos”. Si abre estas carpetas, puede ver los documentos de texto que contienen reseñas de películas.

    Análisis de sentimiento con Scikit-Learn

    Ahora que hemos descargado los datos, es hora de ver alguna acción. En esta sección, realizaremos una serie de pasos necesarios para predecir los sentimientos de las reseñas de diferentes películas. Estos pasos se pueden utilizar para cualquier tarea de clasificación de texto. Usaremos la biblioteca Scikit-Learn de Python para el Machine Learning para entrenar un modelo de clasificación de texto.

    Los siguientes son los pasos necesarios para crear un modelo de clasificación de texto en Python:

    • Importación de bibliotecas
    • Importando el conjunto de datos
    • Preprocesamiento de texto
    • Convertir texto en números
    • Conjuntos de entrenamiento y prueba
    • Entrenamiento del modelo de clasificación de texto y predicción del sentimiento
    • Evaluación del modelo
    • Guardar y cargar el modelo

    Importación de bibliotecas

    Ejecute el siguiente script para importar las bibliotecas necesarias:

    import numpy as np
    import re
    import nltk
    from sklearn.datasets import load_files
    nltk.download('stopwords')
    import pickle
    from nltk.corpus import stopwords
    

    Importar el conjunto de datos

    Usaremos el load_files función de la sklearn_datasets biblioteca para importar el conjunto de datos a nuestra aplicación. los load_files La función divide automáticamente el conjunto de datos en conjuntos de datos y de destino. Por ejemplo, en nuestro caso, le pasaremos la ruta al directorio “txt_sentoken”. los load_files tratará cada carpeta dentro de la carpeta “txt_sentoken” como una categoría ya todos los documentos dentro de esa carpeta se les asignará su categoría correspondiente.

    Ejecute el siguiente script para ver load_files función en acción:

    movie_data = load_files(r"D:txt_sentoken")
    X, y = movie_data.data, movie_data.target
    

    En el guión de arriba, el load_files La función carga los datos de las carpetas “neg” y “pos” en el X variable, mientras que las categorías de destino se almacenan en y. Aquí X es una lista de 2000 elementos de tipo cadena donde cada elemento corresponde a la revisión de un solo usuario. Similar, y es una matriz numerosa de tamaño 2000. Si imprime y en la pantalla, verá una matriz de 1 y 0. Esto se debe a que, para cada categoría, load_files La función agrega un número a la matriz numérica de destino. Tenemos dos categorías: “neg” y “pos”, por lo tanto, se han agregado 1 y 0 a la matriz de destino.

    Preprocesamiento de texto

    Una vez que se ha importado el conjunto de datos, el siguiente paso es preprocesar el texto. El texto puede contener números, caracteres especiales y espacios no deseados. Dependiendo del problema que enfrentemos, es posible que necesitemos o no eliminar estos números y caracteres especiales del texto. Sin embargo, en aras de la explicación, eliminaremos todos los caracteres especiales, números y espacios no deseados de nuestro texto. Ejecute el siguiente script para preprocesar los datos:

    documents = []
    
    from nltk.stem import WordNetLemmatizer
    
    stemmer = WordNetLemmatizer()
    
    for sen in range(0, len(X)):
        # Remove all the special characters
        document = re.sub(r'W', ' ', str(X[sen]))
        
        # remove all single characters
        document = re.sub(r's+[a-zA-Z]s+', ' ', document)
        
        # Remove single characters from the start
        document = re.sub(r'^[a-zA-Z]s+', ' ', document) 
        
        # Substituting multiple spaces with single space
        document = re.sub(r's+', ' ', document, flags=re.I)
        
        # Removing prefixed 'b'
        document = re.sub(r'^bs+', '', document)
        
        # Converting to Lowercase
        document = document.lower()
        
        # Lemmatization
        document = document.split()
    
        document = [stemmer.lemmatize(word) for word in document]
        document=" ".join(document)
        
        documents.append(document)
    

    En el script anterior usamos expresiones Regex de la biblioteca re de Python para realizar diferentes tareas de preprocesamiento. Comenzamos eliminando todos los caracteres que no sean palabras, como caracteres especiales, números, etc.

    A continuación, eliminamos todos los caracteres individuales. Por ejemplo, cuando quitamos el signo de puntuación de “David” y lo reemplazamos con un espacio, obtenemos “David” y un solo carácter “s”, que no tiene significado. Para eliminar esos caracteres individuales usamos s+[a-zA-Z]s+ expresión regular que sustituye todos los caracteres individuales que tienen espacios a cada lado, con un solo espacio.

    A continuación, usamos el ^[a-zA-Z]s+ expresión regular para reemplazar un solo carácter desde el principio del documento, con un solo espacio. Reemplazar caracteres individuales con un solo espacio puede resultar en múltiples espacios, lo cual no es ideal.

    Usamos nuevamente la expresión regular s+ para reemplazar uno o más espacios con un solo espacio. Cuando tiene un conjunto de datos en formato de bytes, la letra del alfabeto “b” se agrega antes de cada cadena. La expresión regular ^bs+ quita “b” del comienzo de una cadena. El siguiente paso es convertir los datos a minúsculas para que las palabras que son realmente iguales pero que tienen diferentes casos se puedan tratar por igual.

    El último paso de preprocesamiento es el lematización. En la lematización, reducimos la palabra a la raíz del diccionario. Por ejemplo, “gatos” se convierte en “gato”. La lematización se realiza para evitar la creación de características que sean semánticamente similares pero sintácticamente diferentes. Por ejemplo, no queremos dos características diferentes llamadas “gatos” y “gato”, que son semánticamente similares, por lo tanto, realizamos lematización.

    Convertir texto en números

    Las máquinas, a diferencia de los humanos, no pueden comprender el texto en bruto. Las máquinas solo pueden ver números. En particular, las técnicas estadísticas como el Machine Learning solo pueden tratar con números. Por lo tanto, necesitamos convertir nuestro texto en números.

    Existen diferentes enfoques para convertir texto en la forma numérica correspondiente. El modelo de la bolsa de palabras y el Modelo de incrustación de palabras son dos de los enfoques más utilizados. En este artículo, usaremos el modelo de bolsa de palabras para convertir nuestro texto en números.

    Bolsa de palabras

    La siguiente secuencia de comandos usa el modelo de bolsa de palabras para convertir documentos de texto en las características numéricas correspondientes:

    from sklearn.feature_extraction.text import CountVectorizer
    vectorizer = CountVectorizer(max_features=1500, min_df=5, max_df=0.7, stop_words=stopwords.words('english'))
    X = vectorizer.fit_transform(documents).toarray()
    

    El script anterior usa CountVectorizer clase de la sklearn.feature_extraction.text biblioteca. Hay algunos parámetros importantes que deben pasarse al constructor de la clase. El primer parámetro es el max_features , que se establece en 1500. Esto se debe a que cuando convierte palabras en números utilizando el enfoque de bolsa de palabras, todas las palabras únicas en todos los documentos se convierten en características. Todos los documentos pueden contener decenas de miles de palabras únicas. Pero las palabras que tienen una frecuencia muy baja de ocurrencia inusualmente no son un buen parámetro para clasificar documentos. Por lo tanto, establecemos el max_features parámetro a 1500, lo que significa que queremos utilizar 1500 palabras más frecuentes como características para entrenar nuestro clasificador.

    El siguiente parámetro es min_df y se ha establecido en 5. Esto corresponde al número mínimo de documentos que deben contener esta característica. Así que solo incluimos aquellas palabras que aparecen en al menos 5 documentos. Del mismo modo, para el max_df, característica el valor se establece en 0,7; en el que la fracción corresponde a un porcentaje. Aquí 0,7 significa que debemos incluir solo aquellas palabras que aparecen en un máximo del 70% de todos los documentos. Las palabras que aparecen en casi todos los documentos no suelen ser adecuadas para la clasificación porque no proporcionan ninguna información única sobre el documento.

    Finalmente, quitamos el Para las palabras de nuestro texto ya que, en el caso del análisis de sentimiento, las palabras vacías pueden no contener información útil. Para eliminar las palabras vacías pasamos el stopwords objeto del nltk.corpus biblioteca a la stop_wordsparámetro.

    los fit_transform función de la CountVectorizer class convierte documentos de texto en las funciones numéricas correspondientes.

    Encontrar TFIDF

    El enfoque de la bolsa de palabras funciona bien para convertir texto en números. Sin embargo, tiene un inconveniente. Asigna una puntuación a una palabra en función de su aparición en un documento en particular. No tiene en cuenta el hecho de que la palabra también puede aparecer con una frecuencia alta en otros documentos. TFIDF resuelve este problema multiplicando el término frecuencia de una palabra por la frecuencia inversa del documento. TF significa “Frecuencia de término”, mientras que IDF significa “Frecuencia de documento inversa”.

    El término frecuencia se calcula como:

    Term frequency = (Number of Occurrences of a word)/(Total words in the document)
    

    Y la frecuencia inversa del documento se calcula como:

    IDF(word) = Log((Total number of documents)/(Number of documents containing the word))
    

    El valor de TFIDF para una palabra en un documento en particular es mayor si la frecuencia de aparición de esa palabra es mayor en ese documento específico pero menor en todos los demás documentos.

    Para convertir los valores obtenidos usando el modelo de bolsa de palabras en valores TFIDF, ejecute el siguiente script:

    from sklearn.feature_extraction.text import TfidfTransformer
    tfidfconverter = TfidfTransformer()
    X = tfidfconverter.fit_transform(X).toarray()
    
    Nota:

    También puede convertir directamente documentos de texto en valores de funciones TFIDF (sin convertir primero los documentos en funciones de bolsa de palabras) utilizando el siguiente script:

    from sklearn.feature_extraction.text import TfidfVectorizer
    tfidfconverter = TfidfVectorizer(max_features=1500, min_df=5, max_df=0.7, stop_words=stopwords.words('english'))
    X = tfidfconverter.fit_transform(documents).toarray()
    

    Conjuntos de entrenamiento y prueba

    Como cualquier otro problema de Machine Learning supervisado, necesitamos dividir nuestros datos en conjuntos de entrenamiento y prueba. Para hacerlo, usaremos el train_test_split utilidad de la sklearn.model_selection biblioteca. Ejecute el siguiente script:

    from sklearn.model_selection import train_test_split
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
    

    El script anterior divide los datos en un 20% de conjunto de prueba y un 80% de conjunto de entrenamiento.

    Entrenamiento del modelo de clasificación de texto y predicción del sentimiento

    Hemos dividido nuestros datos en conjuntos de entrenamiento y prueba. Ahora es el momento de ver la acción real. Usaremos el algoritmo de bosque aleatorio para entrenar nuestro modelo. Puede utilizar cualquier otro modelo de su elección.

    Para entrenar nuestro modelo de Machine Learning usando el algoritmo de bosque aleatorio usaremos RandomForestClassifier clase de la sklearn.ensemble biblioteca. los fit El método de esta clase se utiliza para entrenar el algoritmo. Necesitamos pasar los datos de entrenamiento y los conjuntos de objetivos de entrenamiento a este método. Eche un vistazo al siguiente guión:

    classifier = RandomForestClassifier(n_estimators=1000, random_state=0)
    classifier.fit(X_train, y_train) 
    

    Finalmente, para predecir el sentimiento de los documentos en nuestro conjunto de prueba, podemos usar el predict método del RandomForestClassifier clase como se muestra a continuación:

    y_pred = classifier.predict(X_test)
    

    Felicitaciones, ha entrenado con éxito su primer modelo de clasificación de texto y ha hecho algunas predicciones. Ahora es el momento de ver el rendimiento del modelo que acaba de crear.

    Evaluación del modelo

    Para evaluar el desempeño de un modelo de clasificación como el que acabamos de entrenar, podemos utilizar métricas como la matriz de confusión, Medida F1y la precisión.

    Para encontrar estos valores, podemos usar classification_report, confusion_matrixy accuracy_score utilidades del sklearn.metrics biblioteca. Ejecute el siguiente script para hacerlo:

    from sklearn.metrics import classification_report, confusion_matrix, accuracy_score
    
    print(confusion_matrix(y_test,y_pred))
    print(classification_report(y_test,y_pred))
    print(accuracy_score(y_test, y_pred))
    

    La salida se ve así:

    [[180  28]
     [ 30 162]]
                 precision    recall  f1-score   support
    
              0       0.86      0.87      0.86       208
              1       0.85      0.84      0.85       192
    
    avg / total       0.85      0.85      0.85       400
    
    0.855
    

    Del resultado, se puede ver que nuestro modelo logró una precisión del 85.5%, lo cual es muy bueno dado que elegimos aleatoriamente todos los parámetros para CountVectorizer así como para nuestro algoritmo de bosque aleatorio.

    Guardar y cargar el modelo

    En el script anterior, nuestro modelo de Machine Learning no tomó mucho tiempo para ejecutarse. Una de las razones del tiempo de entrenamiento rápido es el hecho de que teníamos un conjunto de entrenamiento relativamente más pequeño. Teníamos 2000 documentos, de los cuales usamos el 80% (1600) para capacitación. Sin embargo, en escenarios del mundo real, puede haber millones de documentos. En tales casos, puede llevar horas o incluso días (si tiene máquinas más lentas) entrenar los algoritmos. Por lo tanto, se recomienda guardar el modelo una vez entrenado.

    Podemos guardar nuestro modelo como pickle objeto en Python. Para hacerlo, ejecute el siguiente script:

    with open('text_classifier', 'wb') as picklefile:
        pickle.dump(classifier,picklefile)
    

    Una vez que ejecuta el script anterior, puede ver el text_classifier archivo en su directorio de trabajo. Hemos guardado nuestro modelo entrenado y podemos usarlo más tarde para hacer predicciones directamente, sin entrenamiento.

    Para cargar el modelo, podemos utilizar el siguiente código:

    with open('text_classifier', 'rb') as training_model:
        model = pickle.load(training_model)
    

    Cargamos nuestro modelo entrenado y lo almacenamos en el model variable. Vamos a predecir el sentimiento para el conjunto de prueba usando nuestro modelo cargado y veamos si podemos obtener los mismos resultados. Ejecute el siguiente script:

    y_pred2 = model.predict(X_test)
    
    print(confusion_matrix(y_test, y_pred2))
    print(classification_report(y_test, y_pred2))
    print(accuracy_score(y_test, y_pred2)) 
    

    La salida se ve así:

    [[180  28]
     [ 30 162]]
                 precision    recall  f1-score   support
    
              0       0.86      0.87      0.86       208
              1       0.85      0.84      0.85       192
    
    avg / total       0.85      0.85      0.85       400
    
    0.855
    

    La salida es similar a la que obtuvimos anteriormente, que mostró que guardamos y cargamos con éxito el modelo.

    Conclusión

    La clasificación de texto es una de las tareas de PNL más utilizadas. En este artículo, vimos un ejemplo simple de cómo se puede realizar la clasificación de texto en Python. Realizamos el análisis sentimental de críticas de películas.

    Te aconsejo que cambies algún otro algoritmo de Machine Learning para ver si puedes mejorar el rendimiento. Además, intente cambiar los parámetros del CountVectorizerclase para ver si puede obtener alguna mejora.

     

    Etiquetas:

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *