En este artículo, aprenderá cómo crear un canal de análisis de sentimientos de un extremo a otro utilizando Scikit-LLM y modelos de lenguaje grandes de código abierto servidos a través de la API de Groq.
Los temas que cubriremos incluyen:
Cómo Scikit-LLM une los canales clásicos de aprendizaje de scikit con llamadas API de modelos de lenguaje grandes modernos. Cómo configurar Scikit-LLM con un backend de Groq y preparar el conjunto de datos de IMDB Movie Reviews para inferencia. Cómo crear, ejecutar y evaluar una canalización de clasificación de sentimientos de disparo cero utilizando una sintaxis compatible con scikit-learn.
Creación de un canal de análisis de sentimiento de un extremo a otro con Scikit-LLM
Introducción
Los canales tradicionales de aprendizaje automático para tareas predictivas como la clasificación de texto generalmente se basan en la extracción de características numéricas estructuradas del texto sin formato (por ejemplo, frecuencias TF-IDF o incrustaciones de tokens) para alimentar modelos clásicos como la regresión logística, conjuntos o máquinas de vectores de soporte.
Con el surgimiento de los grandes modelos de lenguaje (LLM), las reglas del juego han cambiado un poco: ahora es posible aprovechar el razonamiento de cero o pocos intentos en modelos existentes previamente entrenados para tareas de lenguaje como parte de un marco de aprendizaje automático. Scikit-LLM es una biblioteca de Python que aborda esto: cierra la brecha entre el aprendizaje automático clásico y las llamadas API LLM modernas. En este artículo, utilizaremos Scikit-LLM junto con los modelos backend de Groq para crear un canal de extremo a extremo para el análisis de sentimientos (una forma de clasificación de texto específica de un dominio), logrando resultados de inferencia razonablemente rápidos con modelos de código abierto. Desde el preprocesamiento hasta la inferencia, utilizaremos un conjunto de datos grande y de tamaño realista: el conjunto de datos de reseñas de películas de IMDB.
Requisitos previos, configuración y obtención del conjunto de datos
Para que el código que se muestra en este tutorial funcione, deberá haber instalado la biblioteca Scikit-LLM:
Una vez instalado, el primer paso es instalarlo y configurar las credenciales de API. En otras palabras, necesitaremos "conectar" Scikit-LLM a un punto final, es decir, un repositorio API de LLM como Groq. Asegúrese de registrarse en Groq y generar una clave API aquí: deberá copiarla y pegarla en el siguiente código:
from skllm.config import SKLLMConfig
# 1. Pointing to a Groq’s compatible endpoint
SKLLMConfig.set_gpt_url(“https://api.groq.com/openai/v1”)
# 2. Set your free Groq API key
# Get yours at https://console.groq.com/keys
SKLLMConfig.set_openai_key(“YOUR-API-KEY-GOES-HERE”)
from skllm . config import SKLLMConfig
# 1. Pointing to a Groq’s compatible endpoint
SKLLMConfig . set_gpt_url ( “https://api.groq.com/openai/v1” )
# 2. Set your free Groq API key
# Get yours at https://console.groq.com/keys
SKLLMConfig . set_openai_key ( “YOUR-API-KEY-GOES-HERE” )
Scikit-LLM utiliza una función de punto final, set_gpt_url, que es compatible con OpenAI de forma predeterminada; lo hemos enrutado para realizar solicitudes internas a una URL de Groq personalizada: https://api.groq.com/openai/v1.
La siguiente etapa del proceso es importar el conjunto de datos de IMDB Movie Reviews, que tiene alrededor de 50.000 instancias, y prepararlo para el proceso de análisis de sentimiento que crearemos. Las instancias consisten en una reseña de texto etiquetada con un sentimiento, que puede ser positivo o negativo (este es un problema de clasificación binaria, que se puede resolver con modelos como la regresión logística, por ejemplo).
Para mayor comodidad, leemos el conjunto de datos de una versión del repositorio de GitHub disponible públicamente en formato CSV:
import pandas as pd
from sklearn.model_selection import train_test_split
# Fetching a large, realistic-sized dataset (IMDB Movie Reviews – 50,000 rows)
# We will read the data from a public raw CSV for convenience
url = “https://raw.githubusercontent.com/Ankit152/IMDB-sentiment-analysis/master/IMDB-Dataset.csv”
print(“Downloading dataset…”)
df = pd.read_csv(url)
print(f”Total dataset size: {df.shape[0]} filas") # En un proceso de LLM realista que utiliza una API de nivel gratuito, enviar 50 000 solicitudes # probablemente activará límites de cuota. Por lo tanto, usaremos 500 filas para demostrar la ejecución de nuestro proceso. # Siéntase libre de usar más datos si tiene acceso a la API de pago. df_sampled = df.sample(n=500, random_state=42) # El conjunto de datos de IMDB contiene etiquetas HTML y ruido de formato: eso es perfecto para probar nuestro limpiador X = df_sampled["review"] y = df_sampled["sentiment"] # Las etiquetas son 'positivas' o 'negativas' # Dividir en entrenamiento (para inicializar etiquetas de disparo cero) y conjuntos de prueba X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
importar pandas como PD
de sklearn . model_selection importar train_test _ split
# Obteniendo un conjunto de datos grande y de tamaño realista (Reseñas de películas IMDB – 50,000 filas)
# Leeremos los datos de un CSV público sin formato para mayor comodidad.
URL = "https://raw.githubusercontent.com/Ankit152/IMDB-sentiment-analysis/master/IMDB-Dataset.csv"
print ( "Descargando conjunto de datos…" )
df = PD . read_csv ( url )
print ( f "Tamaño total del conjunto de datos: {df.shape[0]} filas" )
# En un proceso de LLM realista que utiliza una API de nivel gratuito y envía 50 000 solicitudes
# probablemente activará límites de cuota. Por lo tanto, usaremos 500 filas para demostrar la ejecución de nuestra canalización.
# Siéntete libre de utilizar más datos si tienes acceso API de pago.
df_muestreado = df . muestra ( n = 500 , estado_aleatorio = 42 )
# El conjunto de datos IMDB contiene etiquetas HTML y ruido de formato: eso es perfecto para probar nuestro limpiador
incógnita = df_sampled [ "revisión" ]
y = df_sampled [ "sentimiento" ] # Las etiquetas son "positivas" o "negativas"
# Dividir en entrenamiento (para inicializar etiquetas de disparo cero) y conjuntos de prueba
X_tren , X_prueba , y_tren , y_prueba = tren_prueba_split ( X , y , tamaño_prueba = 0,2 , estado_aleatorio = 42 )
Tenga en cuenta que obtuvimos 500 filas solo con fines de demostración; de lo contrario, la inferencia puede llevar mucho tiempo sin suficientes recursos informáticos. Puedes cambiar libremente este tamaño de muestra, n=500, para adaptarlo a tus propias necesidades.
Construyendo el proceso de análisis de sentimiento
¡Aquí viene la parte más interesante del proceso! Un proceso de ciencia de datos se reduce a una serie de pasos de preprocesamiento, limpieza y preparación de datos seguidos de la configuración o entrenamiento del modelo, inferencia y evaluación. Para un escenario predictivo basado en texto como el nuestro, el preprocesamiento normalmente implica limpiar y normalizar el texto. Scikit-learn proporciona una clase elegante, FunctionTransformer, para definir y encapsular pasos de preprocesamiento basados en una función personalizada:
from sklearn.preprocessing import FunctionTransformer
def clean_text_data(texts):
“””Cleans raw text inputs by removing HTML tags and stripping whitespace.”””
series = pd.Series(texts).astype(str)
# Remove HTML tags like
cleaned = series.str.replace(r'<[^>]+>’, ‘ ‘, regex=True)
# Remove extra spaces
cleaned = cleaned.str.strip().str.replace(r’s+’, ‘ ‘, regex=True)
return cleaned.tolist()
# Wrapping the cleaning function to enable its use inside a Pipeline object
text_cleaner = FunctionTransformer(clean_text_data)
from sklearn . preprocessing import FunctionTransformer
def clean_text_data ( texts ) :
“” “Cleans raw text inputs by removing HTML tags and stripping whitespace.” “”
series = pd . Series ( texts ) . astype ( str )
# Remove HTML tags like
cleaned = series . str . replace ( r ‘<[^>]+>’ , ‘ ‘ , regex = True )
# Remove extra spaces
cleaned = cleaned . str . strip ( ) . str . replace ( r ‘s+’ , ‘ ‘ , regex = True )
return cleaned . tolist ( )
# Wrapping the cleaning function to enable its use inside a Pipeline object
text_cleaner = FunctionTransformer ( clean_text_data )
Ahora juntamos este objeto de preprocesamiento con una instancia de modelo para crear Pipeline. Una vez definido, este canal organiza todo el proceso de preparación de los datos y su transferencia al modelo en las etapas de entrenamiento e inferencia; aunque usemos el término "entrenamiento", no se producirá ningún entrenamiento real basado en el peso, ya que estamos utilizando un modelo previamente entrenado de Groq para la clasificación de tiro cero. Ajustar el modelo sólo implica pasarle las etiquetas de clasificación a utilizar.
from sklearn.pipeline import Pipeline
from skllm.models.gpt.classification.zero_shot import ZeroShotGPTClassifier
# Define the end-to-end pipeline
sentiment_pipeline = Pipeline([
(“cleaner”, text_cleaner),
# Updated to use Groq’s active Llama 3.1 8B model
(“llm_classifier”, ZeroShotGPTClassifier(model=”custom_url::llama-3.1-8b-instant”))
])
# Fit the pipeline
# Note: For Zero-Shot classification, fit() doesn’t train the LLM.
# It simply registers the unique labels present in ‘y_train’ (positive, negative).
print(“Fitting the pipeline…”)
sentiment_pipeline.fit(X_train, y_train)
from sklearn . pipeline import Pipeline
from skllm . models . gpt . classification . zero_shot import ZeroShotGPTClassifier
# Define the end-to-end pipeline
sentiment_pipeline = Pipeline ( [
( “cleaner” , text_cleaner ) ,
# Updated to use Groq’s active Llama 3.1 8B model
( “llm_classifier” , ZeroShotGPTClassifier ( model = “custom_url::llama-3.1-8b-instant” ) )
] )
# Fit the pipeline
# Note: For Zero-Shot classification, fit() doesn’t train the LLM.
# It simply registers the unique labels present in ‘y_train’ (positive, negative).
print ( "Ajustando la tubería…" )
sentimiento_pipeline . encajar ( X_tren , y_tren )
Una vez que hayamos ejecutado el proceso para "ajustarlo" al modelo, lo usaremos una vez más para realizar inferencias. Ambos pasos utilizan la sintaxis familiar de scikit-learn. Además de evaluar el rendimiento del canal del modelo, también mostramos algunos ejemplos de predicciones:
from sklearn.metrics import classification_report
print(f”Running predictions on {len(X_test)} test samples…”)
# Run predictions through the pipeline
predictions = sentiment_pipeline.predict(X_test)
# Evaluate the pipeline’s performance on the realistic data
print(“n— Classification Report —“)
print(classification_report(y_test, predictions))
# Display a few side-by-side examples
print(“n— Sample Predictions —“)
for review, actual, predicted in zip(X_test[:3], y_test[:3], predictions[:3]):
# Truncate review for display purposes
short_review = review[:100] + “…”
print(f”Review: {short_review}”)
print(f”Actual: {actual} | Predicted: {predicted}n”)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from sklearn . metrics import classification_report
print ( f “Running predictions on {len(X_test)} test samples…” )
# Run predictions through the pipeline
predictions = sentiment_pipeline . predict ( X_test )
# Evaluate the pipeline’s performance on the realistic data
print ( “n— Classification Report —“ )
print ( classification_report ( y_test , predictions ) )
# Display a few side-by-side examples
print ( “n— Sample Predictions —“ )
for review , actual , predicted in zip ( X_test [ : 3 ] , y_test [ : 3 ] , predictions [ : 3 ] ) :
# Truncate review for display purposes
short_review = review [ : 100 ] + “…”
print ( f “Review: {short_review}” )
print ( f “Actual: {actual} | Predicted: {predicted}n” )
Aquí está el resultado detallado: la ejecución del código anterior puede tardar unos minutos en completarse:
— Classification Report —
precision recall f1-score support
negative 0.95 0.97 0.96 60
positive 0.95 0.93 0.94 40
accuracy 0.95 100
macro avg 0.95 0.95 0.95 100
weighted avg 0.95 0.95 0.95 100
— Sample Predictions —
Review: I saw mommy…well, she wasn’t exactly kissing Santa Clause; he has his hand on her thigh and wicked…
Actual: negative | Predicted: negative
Review: This entry is certainly interesting for series fans (like myself), but yet it is mostly incomprehens…
Actual: negative | Predicted: negative
Review: Ingrid Bergman (Cleo Dulaine) has never been so beautiful. Gary Cooper as “Cleent” so perfectly cast…
Actual: positive | Predicted: positive
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
— – Classification Report — –
precision recall f1 – score support
negative 0.95 0.97 0.96 60
positive 0.95 0.93 0.94 40
accuracy 0.95 100
macro avg 0.95 0.95 0.95 100
weighted avg 0.95 0.95 0.95 100
— – Predicciones de muestra — –
Revisar : I vi a mami . . . Bueno , ella no lo era exactamente besar a Papá Noel ; él tiene su mano en su muslo y malvado . . .
Actual : negativo | Predicho : negativo
Revisar : Este la entrada es ciertamente interesante para fanáticos de la serie ( como yo ) , pero aun así lo es en su mayoría no comprende . . .
Actual : negativo | Predicho : negativo
Revisar : Ingrid Bergman ( Cleo Dulaine ) nunca ha sido tan hermoso . Gary Cooper como "Cliente" tan perfectamente emitido . . .
Actual : positivo | Predicho : positivo
Nuestro canal está haciendo un trabajo sólido al clasificar el sentimiento en las reseñas. ¡Bien hecho!
Concluyendo
Este artículo lo guió a través de la definición de una canalización de un extremo a otro para la clasificación de opiniones utilizando Scikit-LLM y LLM previamente capacitados y disponibles gratuitamente desde puntos finales de API como Groq. Este es un enfoque versátil para utilizar la sintaxis clásica de scikit-learn en aplicaciones novedosas de aprendizaje automático impulsadas por LLM.