Como obter os Embeddings Vectoriais corretos
Este artigo foi publicado originalmente no The New Stack e é republicado aqui com permissão.
Uma introdução abrangente aos embeddings vetoriais e como gerá-los com modelos populares de código aberto.
Imagem por Денис Марчук do Pixabay
Os embeddings vetoriais são críticos quando se trabalha com similaridade semântica. No entanto, um vetor é simplesmente uma série de números; uma incorporação de vetor é uma série de números que representam dados de entrada. Com a utilização de vetor embeddings, podemos estruturar dados não estruturados ou trabalhar com qualquer tipo de dados, convertendo-os numa série de números. Esta abordagem permite-nos efetuar operações matemáticas sobre os dados de entrada, em vez de nos basearmos em comparações qualitativas.
Os embeddings vectoriais são influentes em muitas tarefas, nomeadamente na pesquisa semântica. No entanto, é crucial obter as incorporações vectoriais adequadas antes de as utilizar. Por exemplo, se utilizar um modelo de imagem para vetorizar texto, ou vice-versa, provavelmente obterá maus resultados.
Nesta publicação, vamos aprender o que significam as incorporações vectoriais, como gerar as incorporações vectoriais corretas para as suas aplicações utilizando diferentes modelos e como tirar o melhor partido das incorporações vectoriais com bases de dados vectoriais como Milvus e Zilliz Cloud.
Como são criados os embeddings vectoriais?
Agora que compreendemos a importância dos embeddings vectoriais, vamos aprender como funcionam. Uma incorporação de vetor é a representação interna dos dados de entrada num modelo de aprendizagem profunda, também conhecido como modelos de incorporação ou uma rede neural profunda. Então, como é que extraímos esta informação?
Obtemos vectores removendo a última camada e obtendo a saída da penúltima camada. A última camada de uma rede neural produz normalmente a previsão do modelo, pelo que utilizamos a saída da penúltima camada. A incorporação do vetor é o dado que alimenta a camada de previsão de uma rede neuronal.
A dimensionalidade de uma incorporação vetorial é equivalente ao tamanho da penúltima camada do modelo e, por conseguinte, permutável com o tamanho ou comprimento do vetor. As dimensionalidades comuns dos vectores incluem 384 (geradas por Sentence Transformers Mini-LM), 768 (por Sentence Transformers MPNet), 1.536 (por OpenAI) e 2.048 (por ResNet-50).
O que significa uma incorporação vetorial?
Uma vez perguntaram-me qual o significado de cada dimensão numa integração vetorial. A resposta curta é "nada". Uma única dimensão de uma integração vetorial não significa nada, pois é demasiado abstrata para determinar o seu significado. No entanto, quando consideramos todas as dimensões em conjunto, estas fornecem o significado semântico dos dados de entrada.
As dimensões do vetor são representações abstractas de alto nível de diferentes atributos. Os atributos representados dependem dos dados de treino e do próprio modelo. Os modelos de texto e de imagem geram diferentes embeddings porque são treinados para tipos de dados fundamentalmente diferentes. Até mesmo modelos de texto diferentes geram embeddings diferentes. Por vezes, diferem no tamanho; outras vezes, diferem nos atributos que representam. Por exemplo, um modelo treinado em dados jurídicos aprenderá coisas diferentes de um modelo treinado em dados de cuidados de saúde. Explorei este tópico no meu post comparando embeddings vetoriais.
Gerar as incorporações vectoriais corretas
Como é que se obtêm as incorporações vectoriais adequadas? Tudo começa com a identificação do tipo de dados que deseja incorporar. Esta secção aborda a incorporação de cinco tipos diferentes de dados: imagens, texto, áudio, vídeos e dados multimodais. Todos os modelos que apresentamos aqui são de código aberto e provêm do Hugging Face ou do PyTorch.
Incorporação de imagens
O reconhecimento de imagens arrancou em 2012, quando o AlexNet entrou em cena. Desde então, o campo da visão computacional tem testemunhado inúmeros avanços. O último modelo de reconhecimento de imagem notável é o ResNet-50, uma rede residual profunda de 50 camadas baseada na antiga arquitetura ResNet-34.
As redes neurais residuais (ResNet) resolvem o problema do gradiente de desaparecimento nas redes neurais convolucionais profundas utilizando ligações de atalho. Estas ligações permitem que a saída das camadas anteriores vá diretamente para as camadas posteriores sem passar por todas as camadas intermédias, evitando assim o problema do gradiente de fuga. Esta conceção torna a ResNet menos complexa do que a VGGNet (Visual Geometry Group), uma rede neural convolucional com um desempenho anteriormente superior.
Recomendo duas implementações da ResNet-50 como exemplos: ResNet 50 em Hugging Face e ResNet 50 em PyTorch Hub. Embora as redes sejam as mesmas, o processo de obtenção de embeddings é diferente.
O exemplo de código abaixo demonstra como usar o PyTorch para obter embeddings de vetor. Primeiro, carregamos o modelo do PyTorch Hub. Em seguida, removemos a última camada e chamamos .eval()
para instruir o modelo a comportar-se como se estivesse a ser executado para inferência. Depois, a função embed
gera a incorporação do vetor.
# Load the embedding model with the last layer removed
model = torch.hub.load('pytorch/vision:v0.10.0', 'resnet50', pretrained=True) model = torch.nn.Sequential(*(list(model.children())[:-1]))
model.eval()
def embed(data):
with torch.no_grad():
output = model(torch.stack(data[0])).squeeze()
return output
HuggingFace usa uma configuração ligeiramente diferente. O código abaixo demonstra como obter uma incorporação de vetor da Hugging Face. Primeiro, precisamos de um extrator de caraterísticas e de um modelo da biblioteca transformers
. Utilizaremos o extrator de caraterísticas para obter entradas para o modelo e utilizaremos o modelo para obter saídas e extrair o último estado oculto.
# Load model directly
from transformers import AutoFeatureExtractor, AutoModelForImageClassification
extractor = AutoFeatureExtractor.from_pretrained("microsoft/resnet-50")
model = AutoModelForImageClassification.from_pretrained("microsoft/resnet-50")
from PIL import Image
image = Image.open("<image path>")
# image = Resize(size=(256, 256))(image)
inputs = extractor(images=image, return_tensors="pt")
# print(inputs)
outputs = model(**inputs)
vector_embeddings = outputs[1][-1].squeeze()
Incorporação de texto
Os engenheiros e investigadores têm vindo a fazer experiências com a linguagem natural e a IA desde a invenção da IA. Algumas das primeiras experiências incluem:
- ELIZA, o primeiro chatbot terapeuta de IA.
- O Quarto Chinês de John Searle, uma experiência de pensamento que examina se a capacidade de traduzir entre chinês e inglês requer uma compreensão da língua.
- Traduções baseadas em regras entre inglês e russo.
O funcionamento da IA na linguagem natural evoluiu significativamente a partir das suas incorporações baseadas em regras. Começando com as redes neuronais primárias, acrescentámos relações de recorrência através de RNNs para manter o registo dos passos no tempo. A partir daí, utilizámos transformadores para resolver o problema da transdução de sequências.
Os transformadores são compostos por um codificador, que codifica uma entrada numa matriz que representa o estado, uma matriz de atenção e um descodificador. O descodificador descodifica o estado e a matriz de atenção para prever o próximo token correto para terminar a sequência de saída. O GPT-3, o modelo linguístico mais popular até à data, inclui descodificadores estritos. Codificam a entrada e prevêem a(s) frase(s) seguinte(s) correta(s).
Aqui estão dois modelos da biblioteca sentence-transformers
da Hugging Face que pode utilizar para além dos embeddings da OpenAI:
- MiniLM-L6-v2: um modelo de 384 dimensões
- MPNet-Base-V2: um modelo de 768 dimensões
Pode aceder aos embeddings de ambos os modelos da mesma forma.
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("<model-name>")
vector_embeddings = model.encode(“<input>”)
Embeddings multimodais
Os modelos multimodais estão menos desenvolvidos do que os modelos de imagem ou de texto. Relacionam frequentemente imagens com texto.
O exemplo de código aberto mais útil é o CLIP VIT, um modelo de imagem para texto. Pode aceder aos embeddings do CLIP VIT da mesma forma que acederia a um modelo de imagem, como mostra o código abaixo.
# Load model directly
from transformers import AutoProcessor, AutoModelForZeroShotImageClassification
processor = AutoProcessor.from_pretrained("openai/clip-vit-large-patch14")
model = AutoModelForZeroShotImageClassification.from_pretrained("openai/clip-vit-large-patch14")
from PIL import Image
image = Image.open("<image path>")
# image = Resize(size=(256, 256))(image)
inputs = extractor(images=image, return_tensors="pt")
# print(inputs)
outputs = model(**inputs)
vector_embeddings = outputs[1][-1].squeeze()
Embeddings de áudio
A IA para áudio tem recebido menos atenção do que a IA para texto ou imagens. O caso de utilização mais comum para o áudio é a conversão de voz em texto para sectores como os centros de atendimento telefónico, a tecnologia médica e a acessibilidade. Um modelo de código aberto popular para a conversão de voz em texto é o Whisper da OpenAI. O código abaixo mostra como obter embeddings vetoriais do modelo de fala para texto.
import torch
from transformers import AutoFeatureExtractor, WhisperModel
from datasets import load_dataset
model = WhisperModel.from_pretrained("openai/whisper-base")
feature_extractor = AutoFeatureExtractor.from_pretrained("openai/whisper-base")
ds = load_dataset("hf-internal-testing/librispeech_asr_dummy", "clean", split="validation")
inputs = feature_extractor(ds[0]["audio"]["array"], return_tensors="pt")
input_features = inputs.input_features
decoder_input_ids = torch.tensor([[1, 1]]) * model.config.decoder_start_token_id
vector_embedding = model(input_features, decoder_input_ids=decoder_input_ids).last_hidden_state
Encaixes de vídeo
As incrustações de vídeo são mais complexas do que as incrustações de áudio ou imagem. É necessária uma abordagem multimodal quando se trabalha com vídeos, uma vez que estes incluem áudio e imagens sincronizados. Um modelo de vídeo popular é o percebedor multimodal da DeepMind. Este tutorial do notebook mostra como usar o modelo para classificar um vídeo.
Para obter os embeddings da entrada, use outputs[1][-1].squeeze()
do código mostrado no notebook em vez de excluir as saídas. Eu destaco esse trecho de código na função autoencode
.
def autoencode_video(images, audio):
# only create entire video once as inputs
inputs = {'image': torch.from_numpy(np.moveaxis(images, -1, 2)).float().to(device),
'audio': torch.from_numpy(audio).to(device),
'label': torch.zeros((images.shape[0], 700)).to(device)}
nchunks = 128
reconstruction = {}
for chunk_idx in tqdm(range(nchunks)):
image_chunk_size = np.prod(images.shape[1:-1]) // nchunks
audio_chunk_size = audio.shape[1] // SAMPLES_PER_PATCH // nchunks
subsampling = {
'image': torch.arange(
image_chunk_size * chunk_idx, image_chunk_size * (chunk_idx + 1)),
'audio': torch.arange(
audio_chunk_size * chunk_idx, audio_chunk_size * (chunk_idx + 1)),
'label': None,
}
# forward pass
with torch.no_grad():
outputs = model(inputs=inputs, subsampled_output_points=subsampling)
output = {k:v.cpu() for k,v in outputs.logits.items()}
reconstruction['label'] = output['label']
if 'image' not in reconstruction:
reconstruction['image'] = output['image']
reconstruction['audio'] = output['audio']
else:
reconstruction['image'] = torch.cat(
[reconstruction['image'], output['image']], dim=1)
reconstruction['audio'] = torch.cat(
[reconstruction['audio'], output['audio']], dim=1)
vector_embeddings = outputs[1][-1].squeeze()
# finally, reshape image and audio modalities back to original shape
reconstruction['image'] = torch.reshape(reconstruction['image'], images.shape)
reconstruction['audio'] = torch.reshape(reconstruction['audio'], audio.shape)
return reconstruction
return None
Armazenamento, indexação e pesquisa de embeddings vectoriais com bases de dados vectoriais
Agora que compreendemos o que são embeddings vectoriais e como gerá-los utilizando vários modelos de embedding poderosos, a próxima questão é como armazená-los e tirar partido deles. As bases de dados vectoriais são a resposta.
As bases de dados vectoriais, como a Milvus e a Zilliz Cloud, foram criadas propositadamente para armazenar, indexar e pesquisar em conjuntos de dados maciços de dados não estruturados através de embeddings vectoriais. São também uma das infra-estruturas mais críticas para várias pilhas de IA.
As bases de dados vectoriais utilizam normalmente o algoritmo ANN (Approximate Nearest Neighbor) para calcular a distância espacial entre o vetor de consulta e os vectores armazenados na base de dados. Quanto mais próximos estiverem os dois vectores, mais relevantes são. Em seguida, o algoritmo encontra os k melhores vizinhos mais próximos e apresenta-os ao utilizador.
As bases de dados vectoriais são populares em casos de utilização como a geração aumentada de recuperação LLM (RAG), sistemas de perguntas e respostas, sistemas de recomendação, pesquisas semânticas e pesquisas de semelhança de imagem, vídeo e áudio.
Para saber mais sobre embeddings vetoriais, dados não estruturados e bancos de dados vetoriais, considere começar com a série Banco de dados vetoriais 101.
Resumo
Os vetores são uma ferramenta poderosa para trabalhar com dados não estruturados. Usando vetores, podemos comparar matematicamente diferentes partes de dados não estruturados com base na similaridade semântica. A escolha do modelo correto de incorporação de vetores é fundamental para a criação de um mecanismo de pesquisa de vetores para qualquer aplicativo.
Neste post, aprendemos que as incorporações de vetores são a representação interna dos dados de entrada em uma rede neural. Como resultado, eles dependem muito da arquitetura da rede e dos dados usados para treinar o modelo. Diferentes tipos de dados (como imagens, texto e áudio) exigem modelos específicos. Felizmente, muitos modelos de código aberto pré-treinados estão disponíveis para uso. Neste post, abordámos modelos para os cinco tipos de dados mais comuns: imagens, texto, multimodal, áudio e vídeo. Além disso, se quiser utilizar da melhor forma os embeddings vectoriais, as bases de dados vectoriais são a ferramenta mais popular.
- Como são criados os embeddings vectoriais?
- O que significa uma incorporação vetorial?
- Gerar as incorporações vectoriais corretas
- Armazenamento, indexação e pesquisa de embeddings vectoriais com bases de dados vectoriais
- Resumo
On This Page
Try Managed Milvus for Free
Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.
Get StartedLike the article? Spread the word