Con el creciente número de modelos de integración disponibles, elegir el adecuado para sus aplicaciones de aprendizaje automático puede resultar un desafío. Afortunadamente, el Tabla de clasificación MTEB proporciona una amplia gama de métricas de clasificación para diversas tareas de procesamiento del lenguaje natural.
Cuando visite el sitio, notará que los cinco principales modelos de integración son Transformadores Generativos Preentrenados (GPT). Esto podría llevarle a pensar que los modelos GPT son los mejores para incrustaciones. ¿Pero es esto realmente cierto? Realicemos un experimento para descubrirlo.
Las incrustaciones son representaciones tensoriales de textos, que convierten ID de tokens de texto y los proyectan en un espacio tensorial.
Al ingresar texto en un modelo de red neuronal y realizar un pase hacia adelante, puede obtener vectores de incrustación. Sin embargo, el proceso real es un poco más complejo. Analicémoslo paso a paso:
- Convierta el texto en ID de token
- Pasar los ID de los tokens a una red neuronal
- Devolver las salidas de la red neuronal.
En el primer paso, usaré un tokenizador para lograrlo. model_inputs es la representación tensorial del contenido del texto, "some questions." .
from transformers import AutoTokenizertokenizer = AutoTokenizer.from_pretrained("mistralai/Mistral-7B-Instruct-v0.1")
messages = [
{
"role": "user",
"content": "some questions.",
},
]
encodeds = tokenizer.apply_chat_template(messages, return_tensors="pt")
model_inputs = encodeds.to("cuda")
El segundo paso es sencillo: pasar hacia adelante el model_inputs en una red neuronal. Se puede acceder a los logits de los tokens generados a través de .logits. torch.no_grad() significa que no quiero que se actualicen los pesos del modelo porque el modelo está en modo de inferencia.
import torchwith torch.no_grad():
return model(model_inputs).logits
El tercer paso es un poco complicado. Los modelos GPT son solo decodificadores y su generación de tokens es autorregresiva. En términos simples, el último token de una oración completa ha visto todos los tokens anteriores en la oración. Por lo tanto, la salida del último token contiene todas las puntuaciones de afinidad (atenciones) de los tokens anteriores.
¡Bingo! Lo que más le interesa es la última ficha debido al mecanismo de atención de los transformadores.
La dimensión de salida de los GPT implementados en Hugging Face es (tamaño del lote, tamaño del token de entrada, cantidad de vocabulario). Para obtener la última salida del token de todos los lotes, puedo realizar un corte tensorial.
import torch
with torch.no_grad():
return model(model_inputs).logits[:, -1, :]
Para medir la calidad de estas incrustaciones GPT, puede utilizar similitud coseno. Cuanto mayor sea la similitud del coseno, más cercano será el significado semántico de las oraciones.
import torch
def compute_cosine_similarity(vec1, vec2):
cos = torch.nn.CosineSimilarity(dim=1, eps=1e-6)
return cos(vec1, vec2)
Creemos algunas funciones útiles que nos permitan recorrer la lista de pares de preguntas y respuestas y ver el resultado. Instrucciones Mistral 7b v0.1 uno de los grandes modelos de código abierto, se utiliza para este experimento.
import torch
from termcolor import colored
from transformers import AutoModelForCausalLM, AutoTokenizermodel = AutoModelForCausalLM.from_pretrained(
"mistralai/Mistral-7B-Instruct-v0.1"
)
tokenizer = AutoTokenizer.from_pretrained("mistralai/Mistral-7B-Instruct-v0.1")
def generate_last_token_embeddings(question, max_new_tokens=30):
messages = [
{
"role": "user",
"content": question,
},
]
encodeds = tokenizer.apply_chat_template(messages, return_tensors="pt")
model_inputs = encodeds.to("cuda")
with torch.no_grad():
return model(model_inputs).logits[:, -1, :]
def get_similarities(questions, answers):
for question in questions:
for answer in answers:
q_embedding, a_embedding = (
generate_last_token_embeddings(question),
generate_last_token_embeddings(answer),
)
similarity = compute_cosine_similarity(q_embedding, a_embedding)
print(colored(f"question: {question} and ans: {answer}", "green"))
print(colored(f"result: {similarity}", "blue"))
questions = ["Where is the headquarter of OpenAI?", "What is GPU?"]
answers = [
"OpenAI is based at San Francisco.",
"A graphics processing unit (GPU) is an electronic circuit that can perform mathematical calculations quickly",
]
Para el primer par de preguntas y respuestas:
- Pregunta: “¿Cuál es la sede de OpenAI?”
- Respuesta: “OpenAI tiene su sede en San Francisco”.
- Similitud del coseno: 0,96
Para el segundo par de preguntas y respuestas:
- Pregunta: “¿Qué es GPU?”
- Respuesta: “Una unidad de procesamiento de gráficos (GPU) es un circuito electrónico que puede realizar cálculos matemáticos rápidamente”.
- Similitud del coseno: 0,94
Para un par irrelevante:
- Pregunta: “¿Dónde está la sede de OpenAI?”
- Respuesta: “Una unidad de procesamiento de gráficos (GPU) es un circuito electrónico que puede realizar cálculos matemáticos rápidamente”.
- Similitud del coseno: 0,90
Para el peor par:
- Pregunta: “¿Qué es GPU?”
- Respuesta: “OpenAI tiene su sede en San Francisco”.
- Similitud del coseno: 0,93
Estos resultados sugieren que el uso de modelos GPT, en este caso, la instrucción mistral 7b v0.1, ya que los modelos de integración pueden no producir grandes resultados en términos de distinguir entre pares relevantes e irrelevantes. Pero, ¿por qué los modelos GPT siguen entre los cinco mejores modelos integrados?
tokenizer = AutoTokenizer.from_pretrained("intfloat/e5-mistral-7b-instruct")
model = AutoModelForCausalLM.from_pretrained(
"intfloat/e5-mistral-7b-instruct"
)
e5-mistral-7b-instruct (Image by the author)Repitiendo el mismo procedimiento de evaluación con un modelo diferente, e5-mistral-7b-instruct, que es uno de los mejores modelos de código abierto de la tabla de clasificación MTEB y ajustado desde la instrucción mistral 7b, descubrí que la similitud del coseno para la pregunta y los pares relevantes son 0,88 y 0,84 para las preguntas de OpenAI y GPU, respectivamente. Para los pares de preguntas y respuestas irrelevantes, la similitud cae a 0,56 y 0,67. Estos hallazgos sugieren e5-mistral-7b-instruct es un modelo muy mejorado para incrustaciones. ¿Qué hace tal mejora?
Profundizando en el papel detrás e5-mistral-7b-instructla clave es el uso de pérdida contrastiva para afinar aún más el modelo mistral.
A diferencia de los GPT que se entrenan o se ajustan aún más utilizando pérdida de entropía cruzada de tokens predichos y tokens etiquetados, la pérdida contrastiva tiene como objetivo maximizar la distancia entre pares negativos y minimizar la distancia entre los pares positivos.
Este entrada en el blog cubre este concepto con mayor detalle. El sim La función calcula la distancia del coseno entre dos vectores. Para la pérdida contrastiva, los denominadores representan la distancia del coseno entre ejemplos positivos y ejemplos negativos. La razón detrás de la pérdida contrastiva es que queremos que vectores similares estén lo más cerca posible de 1, ya que log(1) = 0 representa la pérdida óptima.
En esta publicación, he resaltado un error común al usar GPT como modelos integrados sin realizar ajustes. Mi evaluación sugiere que al ajustar los GPT con pérdida de contraste, las incrustaciones pueden ser más significativas y discriminativas. Al comprender las fortalezas y limitaciones de los modelos GPT y aprovechar la pérdida personalizada, como la pérdida contrastiva, puede tomar decisiones más informadas al seleccionar y utilizar modelos integrados para sus proyectos de aprendizaje automático. Espero que esta publicación le ayude a elegir sabiamente los modelos GPT para sus aplicaciones y espero escuchar sus comentarios. 🙂