Los transformadores de oraciones son poderosos modelos de aprendizaje profundo que convierten oraciones en incrustaciones de alta calidad y longitud fija, capturando su significado semántico. Estas incorporaciones son útiles para diversas tareas de procesamiento del lenguaje natural (NLP), como clasificación de texto, agrupación, búsqueda semántica y recuperación de información.
En esta publicación, mostramos cómo ajustar un transformador de oraciones específicamente para clasificar un producto de Amazon en su categoría de producto (como juguetes o artículos deportivos). Mostramos dos transformadores de oraciones diferentes, paráfrasis-MiniLM-L6-v2 y un modelo de lenguaje grande (LLM) patentado por Amazon llamado M5_ASIN_SMALL_V2.0
y comparar sus resultados. M5 LLMS son LLM basados en BERT ajustados a los datos internos del catálogo de productos de Amazon utilizando el título del producto, viñetas, descripción y más. Actualmente se utilizan para casos de uso como clasificación automatizada de productos y recomendaciones de productos similares. Nuestra hipótesis es que M5_ASIN_SMALL_V2.0
funcionará mejor para el caso de uso de clasificación de categorías de productos de Amazon debido a que está ajustado con los datos de productos de Amazon. Probamos esta hipótesis en el siguiente experimento ilustrado en esta publicación.
Descripción general de la solución
En esta publicación, demostramos cómo ajustar un transformador de oraciones con datos de productos de Amazon y cómo usar el transformador de oraciones resultante para mejorar la precisión de la clasificación de las categorías de productos utilizando un árbol de decisión XGBoost. Para esta demostración, utilizamos un conjunto de datos públicos de productos de Amazon llamado Conjunto de datos de productos de Amazon 2020 de un competencia kaggle. Este conjunto de datos contiene los siguientes atributos y campos:
- Nombre de dominio – amazon.com
- Rango de fechas – 1 de enero de 2020, hasta el 31 de enero de 2020
- Extensión de archivo – CSV
- Campos disponibles – ID Uniq, nombre del producto, nombre de la marca, ASIN, categoría, código UPC Ean, precio de lista, precio de venta, cantidad, número de modelo, acerca del producto, especificación del producto, detalles técnicos, peso de envío, dimensiones del producto, imagen, variantes, SKU, URL del producto, existencias, detalles del producto, dimensiones, color, ingredientes, dirección de uso, vendedor de Amazon, tamaño, cantidad, variante y descripción del producto.
- Campo de etiqueta – Categoría
Requisitos previos
Antes de comenzar, instale los siguientes paquetes. Puedes hacer esto en un Amazon SageMaker notebook o su notebook Jupyter local ejecutando los siguientes comandos:
!pip install sentencepiece --quiet
!pip install sentence_transformers --quiet
!pip install xgboost –-quiet
!pip install scikit-learn –-quiet/
Preprocesar los datos
El primer paso necesario para ajustar un transformador de oraciones es preprocesar los datos del producto de Amazon para que el transformador de oraciones pueda consumir los datos y ajustarlos de manera efectiva. Implica normalizar los datos del texto, definir la categoría principal del producto extrayendo la primera categoría del campo Categoría y seleccionar los campos más importantes del conjunto de datos que contribuyen a clasificar con precisión la categoría principal del producto. Usamos el siguiente código para el preprocesamiento:
import pandas as pd
from sklearn.preprocessing import LabelEncoder
data = pd.read_csv('marketing_sample_for_amazon_com-ecommerce__20200101_20200131__10k_data.csv')
data.columns = data.columns.str.lower().str.replace(' ', '_')
data['main_category'] = data['category'].str.split("|").str[0]
data["all_text"] = data.apply(
lambda r: " ".join(
[
str(r["product_name"]) if pd.notnull(r["product_name"]) else "",
str(r["about_product"]) if pd.notnull(r["about_product"]) else "",
str(r["product_specification"]) if pd.notnull(r["product_specification"]) else "",
str(r["technical_details"]) if pd.notnull(r["technical_details"]) else ""
]
),
axis=1
)
label_encoder = LabelEncoder()
labels_transform = label_encoder.fit_transform(data['main_category'])
data['label']=labels_transform
data[['all_text','label']]
La siguiente captura de pantalla muestra un ejemplo de cómo se ve nuestro conjunto de datos después de haber sido preprocesado.
Afinar la paráfrasis del transformador de oraciones-MiniLM-L6-v2
El primer transformador de oración que afinamos se llama paráfrasis-MiniLM-L6-v2. Utiliza el popular BERT modelo como su arquitectura subyacente para transformar el texto de descripción del producto en una incrustación vectorial densa de 384 dimensiones que será consumida por nuestro clasificador XGBoost para la clasificación de categorías de productos. Usamos el siguiente código para ajustar parafrase-MiniLM-L6-v2 utilizando los datos de productos de Amazon preprocesados:
from sentence_transformers import SentenceTransformer
model_name="paraphrase-MiniLM-L6-v2"
model = SentenceTransformer(model_name)
El primer paso es definir un encabezado de clasificación que represente las 24 categorías de productos en las que se puede clasificar un producto de Amazon. Este encabezado de clasificación se utilizará para entrenar al transformador de oraciones específicamente para que sea más efectivo en la transformación de descripciones de productos de acuerdo con las 24 categorías de productos. La idea es que todas las descripciones de productos que están dentro de la misma categoría deben transformarse en una incrustación vectorial que esté más cerca en comparación con las descripciones de productos que pertenecen a diferentes categorías.
El siguiente código es para ajustar el transformador de oración 1:
import torch.nn as nn
# Define classification head
class ClassificationHead(nn.Module):
def __init__(self, embedding_dim, num_classes):
super(ClassificationHead, self).__init__()
self.linear = nn.Linear(embedding_dim, num_classes)
def forward(self, features):
x = features['sentence_embedding']
x = self.linear(x)
return x
# Define the number of classes for a classification task.
num_classes = 24
print('class number:', num_classes)
classification_head = ClassificationHead(model.get_sentence_embedding_dimension(), num_classes)
# Combine SentenceTransformer model and classification head."
class SentenceTransformerWithHead(nn.Module):
def __init__(self, transformer, head):
super(SentenceTransformerWithHead, self).__init__()
self.transformer = transformer
self.head = head
def forward(self, input):
features = self.transformer(input)
logits = self.head(features)
return logits
model_with_head = SentenceTransformerWithHead(model, classification_head)
Luego configuramos los parámetros de ajuste fino. Para esta publicación, entrenamos en cinco épocas, optimizamos para pérdida de entropía cruzaday utilizar el Optimización AdamW método. Elegimos la época 5 porque, después de probar varios valores de época, observamos que la pérdida se minimizó en la época 5. Esto lo convirtió en el número óptimo de iteraciones de entrenamiento para lograr los mejores resultados de clasificación.
El siguiente código es para ajustar el transformador de oraciones 2:
import os
os.environ["TORCH_USE_CUDA_DSA"] = "1"
os.environ["CUDA_LAUNCH_BLOCKING"] = "1"
from sentence_transformers import SentenceTransformer, InputExample, LoggingHandler
import torch
from torch.utils.data import DataLoader
from transformers import AdamW, get_linear_schedule_with_warmup
train_sentences = data['all_text']
train_labels = data['label']
# training parameters
num_epochs = 5
batch_size = 2
learning_rate = 2e-5
# Convert the dataset to PyTorch tensors.
train_examples = [InputExample(texts=[s], label=l) for s, l in zip(train_sentences, train_labels)]
# Customize collate_fn to convert InputExample objects into tensors.
def collate_fn(batch):
texts = [example.texts[0] for example in batch]
labels = torch.tensor([example.label for example in batch])
return texts, labels
train_dataloader = DataLoader(train_examples, shuffle=True, batch_size=batch_size, collate_fn=collate_fn)
# Define the loss function, optimizer, and learning rate scheduler.
criterion = nn.CrossEntropyLoss()
optimizer = AdamW(model_with_head.parameters(), lr=learning_rate)
total_steps = len(train_dataloader) * num_epochs
scheduler = get_linear_schedule_with_warmup(optimizer, num_warmup_steps=0, num_training_steps=total_steps)
# Training loop
loss_list=[]
for epoch in range(num_epochs):
model_with_head.train()
for step, (texts, labels) in enumerate(train_dataloader):
labels = labels.to(model.device)
optimizer.zero_grad()
# Encode text and pass through classification head.
inputs = model.tokenize(texts)
input_ids = inputs['input_ids'].to(model.device)
input_attention_mask = inputs['attention_mask'].to(model.device)
inputs_final = {'input_ids': input_ids, 'attention_mask': input_attention_mask}
# move model_with_head to the same device
model_with_head = model_with_head.to(model.device)
logits = model_with_head(inputs_final)
loss = criterion(logits, labels)
loss.backward()
optimizer.step()
scheduler.step()
if step % 100 == 0:
print(f"Epoch {epoch}, Step {step}, Loss: {loss.item()}")
print(f'Epoch {epoch+1}/{num_epochs}, Loss: {loss.item()}')
model_save_path = f'./intermediate-output/epoch-{epoch}'
model.save(model_save_path)
loss_list.append(loss.item())
# Save the final model
model_final_save_path="st_ft_epoch_5"
model.save(model_final_save_path)
Para observar si nuestro transformador de oraciones afinado resultante mejora la precisión de nuestra clasificación de categorías de productos, lo usamos como nuestro incrustador de texto en el clasificador XGBoost en el siguiente paso.
Clasificación XGBoost
XGBoost (aumento de gradiente extremo) La clasificación es una técnica de aprendizaje automático que se utiliza para tareas de clasificación. Es una implementación del marco de aumento de gradiente diseñado para ser eficiente, flexible y portátil. Para esta publicación, hacemos que XGBoost consuma el texto de descripción del producto que incrusta la salida de nuestros transformadores de oraciones y observe la precisión de la clasificación de la categoría de producto. Usamos el siguiente código para usar el estándar. paraphrase-MiniLM-L6-v2
Transformador de oraciones antes de que fuera perfeccionado para clasificar los productos de Amazon en sus respectivas categorías:
from sklearn.model_selection import train_test_split
import xgboost as xgb
from sklearn.metrics import accuracy_score
model = SentenceTransformer('paraphrase-MiniLM-L6-v2')
data['text_embedding'] = data['all_text'].apply(lambda x: model.encode(str(x)))
text_embeddings = pd.DataFrame(data['text_embedding'].tolist(), index=data.index, dtype=float)
# Convert numeric columns stored as strings to floats
numeric_columns = ['selling_price', 'shipping_weight', 'product_dimensions'] # Add more columns as needed
for col in numeric_columns:
data[col] = pd.to_numeric(data[col], errors="coerce")
# Convert categorical columns to category type
categorical_columns = ['model_number', 'is_amazon_seller'] # Add more columns as needed
for col in categorical_columns:
data[col] = data[col].astype('category')
X_0 = data[['selling_price','model_number','is_amazon_seller']]
X = pd.concat([X_0, text_embeddings], axis=1)
label_encoder = LabelEncoder()
data['main_category_encoded'] = label_encoder.fit_transform(data['main_category'])
y = data['main_category_encoded']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Re-encode the labels to ensure they are consecutive integers starting from 0
unique_labels = sorted(set(y_train) | set(y_test))
label_mapping = {label: idx for idx, label in enumerate(unique_labels)}
y_train = y_train.map(label_mapping)
y_test = y_test.map(label_mapping)
# Enable categorical support for XGBoost
dtrain = xgb.DMatrix(X_train, label=y_train, enable_categorical=True)
dtest = xgb.DMatrix(X_test, label=y_test, enable_categorical=True)
param = {
'max_depth': 6,
'eta': 0.3,
'objective': 'multi:softmax',
'num_class': len(label_mapping),
'eval_metric': 'mlogloss'
}
num_round = 100
bst = xgb.train(param, dtrain, num_round)
# Evaluate the model
y_pred = bst.predict(dtest)
accuracy = accuracy_score(y_test, y_pred)
print(f'Accuracy: {accuracy:.2f}')
Accuracy: 0.78
Observamos una precisión del 78% utilizando la acción. paraphrase-MiniLM-L6-v2
transformador de oraciones. Para observar los resultados del ajuste paraphrase-MiniLM-L6-v2
Transformador de oraciones, necesitamos actualizar el comienzo del código de la siguiente manera. El resto del código sigue siendo el mismo.
model = SentenceTransformer('st_ft_epoch_5')
data['text_embedding_miniLM_ft10'] = data['all_text'].apply(lambda x: model.encode(str(x)))
text_embeddings = pd.DataFrame(data['text_embedding_finetuned'].tolist(), index=data.index, dtype=float)
X_pa_finetuned = pd.concat([X_0, text_embeddings], axis=1)
X_train, X_test, y_train, y_test = train_test_split(X_pa_finetuned, y, test_size=0.2, random_state=42)
# Re-encode the labels to ensure they are consecutive integers starting from 0
unique_labels = sorted(set(y_train) | set(y_test))
label_mapping = {label: idx for idx, label in enumerate(unique_labels)}
y_train = y_train.map(label_mapping)
y_test = y_test.map(label_mapping)
# Build and train the XGBoost model
# Enable categorical support for XGBoost
dtrain = xgb.DMatrix(X_train, label=y_train, enable_categorical=True)
dtest = xgb.DMatrix(X_test, label=y_test, enable_categorical=True)
param = {
'max_depth': 6,
'eta': 0.3,
'objective': 'multi:softmax',
'num_class': len(label_mapping),
'eval_metric': 'mlogloss'
}
num_round = 100
bst = xgb.train(param, dtrain, num_round)
y_pred = bst.predict(dtest)
accuracy = accuracy_score(y_test, y_pred)
print(f'Accuracy: {accuracy:.2f}')
# Optionally, convert the predicted labels back to the original category labels
inverse_label_mapping = {idx: label for label, idx in label_mapping.items()}
y_pred_labels = pd.Series(y_pred).map(inverse_label_mapping)
Accuracy: 0.94
Con el afinado paraphrase-MiniLM-L6-v2
transformador de oraciones, observamos una precisión del 94%, un aumento del 16% desde el punto de referencia del 78% de precisión. De esta observación, concluimos que el ajuste fino paraphrase-MiniLM-L6-v2
es eficaz para clasificar los datos de productos de Amazon en categorías de productos.
Afina el transformador de sentencias M5_ASIN_SMALL_V20
Ahora creamos un transformador de oraciones a partir de un modelo basado en BERT llamado M5_ASIN_SMALL_V2.0
. Es un modelo basado en BERT de 40 millones de parámetros entrenado en M5, un equipo interno de Amazon que se especializa en ajustar los LLM utilizando datos de productos de Amazon. Se destiló de un modelo docente más grande (aproximadamente 5 mil millones de parámetros), que se entrenó previamente con una gran cantidad de datos ASIN sin etiquetar y se ajustó previamente en un conjunto de tareas de aprendizaje supervisadas por Amazon (multitarea predefinida). sintonización). Es un modelo de codificador basado en BERT multitarea, multilingüe, multilocal y multimodal entrenado en entrada de texto y datos estructurados. Los detalles arquitectónicos de su red neuronal son los siguientes:
Columna vertebral del modelo:
Tamaño oculto: 384
Número de capas ocultas: 24
Número de cabezales de atención: 16
Tamaño intermedio: 1536
Tamaño del vocabulario: 256,035
Número de parámetros de backbone: 42.587.904
Número de parámetros de incrustación de palabras (bert.embedding.*): 98.517.504
Número total de parámetros: 141.259.023
Porque M5_ASIN_SMALL_V20
fue entrenado previamente específicamente en datos de productos de Amazon, planteamos la hipótesis de que construir un transformador de oraciones a partir de ellos aumentará la precisión de la clasificación de categorías de productos. Completamos los siguientes pasos para construir un transformador de oraciones a partir de M5_ASIN_SMALL_V20
ajústelo e introdúzcalo en un clasificador XGBoost para observar el impacto en la precisión:
- Cargue un modelo M5 previamente entrenado que desee utilizar como codificador base.
- Utilice el modelo M5 dentro del
SentenceTransformer
marco para crear un transformador de oraciones. - Agregue una capa de agrupación para crear incrustaciones de oraciones de tamaño fijo a partir de la salida de longitud variable del modelo BERT.
- Combine el modelo M5 y la capa de agrupación en un solo modelo.
- Ajuste el modelo en un conjunto de datos relevante.
Consulte el siguiente código para los pasos 1 a 3:
from sentence_transformers import models
from transformers import AutoTokenizer
# Step 1: Load Pre-trained M5 Model
model_path="M5_ASIN_SMALL_V20" # or your custom model path
transformer_model = models.Transformer(model_path)
tokenizer = AutoTokenizer.from_pretrained(model_path)
# Step 2: Define Pooling Layer
pooling_model = models.Pooling(transformer_model.get_word_embedding_dimension(),
pooling_mode_mean_tokens=True)
# Step 3: Create SentenceTransformer Model
model_mean_m5_base = SentenceTransformer(modules=[transformer_model, pooling_model])
El resto del código sigue siendo el mismo que el ajuste fino para el paraphrase-MiniLM-L6-v2
transformador de oraciones, excepto que usamos el transformador de oraciones M5 ajustado en su lugar para crear incrustaciones para los textos en el conjunto de datos:
loaded_model = SentenceTransformer('m5_ft_epoch_5_mean')
data['text_embedding_m5'] = data['all_text'].apply(lambda x: loaded_model.encode(str(x)))
Resultado
Observamos resultados similares a paraphrase-MiniLM-L6-v2
Al observar la precisión antes del ajuste fino, se observa una precisión del 78% para M5_ASIN_SMALL_V20
. Sin embargo, observamos que el ajuste fino M5_ASIN_SMALL_V20
El transformador de oraciones funciona mejor que el fine-tuned paraphrase-MiniLM-L6-v2
. Su precisión es del 98%, en comparación con el 94% del ajuste fino. paraphrase-MiniLM-L6-v2
. Ajustamos los transformadores de oraciones durante 5 épocas, porque los experimentos demostraron que este era el número óptimo para minimizar la pérdida. El siguiente gráfico resume nuestras observaciones de mejora de la precisión con ajustes finos para 5 épocas en un único cuadro comparativo.
Limpiar
Recomendamos utilizar GPU para ajustar los transformadores de oraciones, por ejemplo, ml.g5.4xlarge o ml.g4dn.16xlarge. Asegúrese de limpiar los recursos para evitar incurrir en costos adicionales.
Si está utilizando una instancia de cuaderno de SageMaker, consulte Limpiar los recursos de la instancia del cuaderno de Amazon SageMaker. Si estas usando Amazon SageMaker Estudioconsulte Elimine o detenga su Studio ejecutando instancias, aplicaciones y espacios.
Conclusión
En esta publicación, exploramos los transformadores de oraciones y cómo usarlos de manera efectiva para tareas de clasificación de texto. Nos sumergimos profundamente en el transformador de frases. paraphrase-MiniLM-L6-v2
demostró cómo utilizar un modelo basado en BERT como M5_ASIN_SMALL_V20
Para crear un transformador de oraciones, mostró cómo afinar los transformadores de oraciones y mostró los efectos de precisión del ajuste de los transformadores de oraciones.
El ajuste de los transformadores de oraciones ha demostrado ser muy eficaz para clasificar descripciones de productos en categorías, lo que mejora significativamente la precisión de la predicción. Como siguiente paso, te animamos a explorar diferentes transformadores de frases de Hugging Face.
Por último, si desea explorar M5, tenga en cuenta que es propiedad de Amazon y solo puede acceder a él como socio o cliente de Amazon al momento de esta publicación. Conéctese con su punto de contacto de Amazon si es un socio o cliente de Amazon que desea usar M5, y él lo guiará a través de las ofertas de M5 y cómo puede usarse para su caso de uso.
Acerca de los autores
kara yang es científico de datos en AWS Professional Services en el área de la Bahía de San Francisco, con amplia experiencia en AI/ML. Se especializa en aprovechar la computación en la nube, el aprendizaje automático y la IA generativa para ayudar a los clientes a abordar desafíos comerciales complejos en diversas industrias. A Kara le apasiona la innovación y el aprendizaje continuo.
Farshad Harirchi es científico de datos principal en AWS Professional Services. Ayuda a clientes de todos los sectores, desde el comercio minorista hasta los servicios industriales y financieros, con el diseño y desarrollo de soluciones de aprendizaje automático e inteligencia artificial generativa. Farshad aporta una amplia experiencia en todo el aprendizaje automático y la pila MLOps. Fuera del trabajo, le gusta viajar, practicar deportes al aire libre y explorar juegos de mesa.
James Poquiz es un científico de datos de AWS Professional Services con sede en el condado de Orange, California. Tiene una licenciatura en Ciencias de la Computación de la Universidad de California, Irvine y varios años de experiencia trabajando en el dominio de datos habiendo desempeñado muchos roles diferentes. Hoy trabaja en la implementación e implementación de soluciones de aprendizaje automático escalables para lograr resultados comerciales para los clientes de AWS.