Vetor denso
Os vectores densos são representações de dados numéricos amplamente utilizados na aprendizagem automática e na análise de dados. São constituídos por matrizes com números reais, em que a maioria ou todos os elementos são diferentes de zero. Em comparação com os vectores esparsos, os vectores densos contêm mais informações ao mesmo nível dimensional, uma vez que cada dimensão contém valores significativos. Esta representação pode efetivamente captar padrões e relações complexos, facilitando a análise e o processamento de dados em espaços de elevada dimensão. Os vectores densos têm normalmente um número fixo de dimensões, que varia entre algumas dezenas e várias centenas ou mesmo milhares, dependendo da aplicação e dos requisitos específicos.
Os vectores densos são principalmente utilizados em cenários que exigem a compreensão da semântica dos dados, como a pesquisa semântica e os sistemas de recomendação. Na pesquisa semântica, os vectores densos ajudam a capturar as ligações subjacentes entre consultas e documentos, melhorando a relevância dos resultados da pesquisa. Nos sistemas de recomendação, ajudam a identificar semelhanças entre utilizadores e itens, oferecendo sugestões mais personalizadas.
Visão geral
Os vectores densos são normalmente representados como matrizes de números de vírgula flutuante com um comprimento fixo, como [0.2, 0.7, 0.1, 0.8, 0.3, ..., 0.5]
. A dimensionalidade destes vectores varia normalmente entre centenas e milhares, como 128, 256, 768 ou 1024. Cada dimensão capta caraterísticas semânticas específicas de um objeto, tornando-o aplicável a vários cenários através de cálculos de semelhança.
Vectores densos no espaço 2D
A imagem acima ilustra a representação de vectores densos num espaço 2D. Embora os vectores densos em aplicações do mundo real tenham frequentemente dimensões muito superiores, esta ilustração 2D transmite eficazmente vários conceitos-chave.
Representação multidimensional: Cada ponto representa um objeto concetual (como Milvus, base de dados vetorial, sistema de recuperação, etc.), sendo a sua posição determinada pelos valores das suas dimensões.
Relações Semânticas: As distâncias entre os pontos reflectem a semelhança semântica entre os conceitos. Pontos mais próximos indicam conceitos que estão mais relacionados semanticamente.
Efeito de agrupamento: Os conceitos relacionados (como Milvus, base de dados vetorial e sistema de recuperação) são posicionados próximos uns dos outros no espaço, formando um agrupamento semântico.
Segue-se um exemplo de um vetor denso real que representa o texto "Milvus is an efficient vector database"
.
[
-0.013052909,
0.020387933,
-0.007869,
-0.11111383,
-0.030188112,
-0.0053388323,
0.0010654867,
0.072027855,
// ... more dimensions
]
Os vectores densos podem ser gerados utilizando vários modelos de incorporação, tais como modelos CNN (como ResNet, VGG) para imagens e modelos de linguagem (como BERT, Word2Vec) para texto. Estes modelos transformam os dados em bruto em pontos num espaço de elevada dimensão, capturando as caraterísticas semânticas dos dados. Adicionalmente, Milvus oferece métodos convenientes para ajudar os utilizadores a gerar e processar vectores densos, como detalhado em Embeddings.
Uma vez os dados vectorizados, podem ser armazenados no Milvus para gestão e recuperação de vectores. O diagrama abaixo mostra o processo básico.
Utilizar vectores densos em Milvus
Para além dos vectores densos, Milvus também suporta vectores esparsos e vectores binários. Os vectores esparsos são adequados para correspondências precisas com base em termos específicos, como a pesquisa de palavras-chave e a correspondência de termos, enquanto os vectores binários são normalmente utilizados para tratar eficazmente dados binarizados, como a correspondência de padrões de imagem e determinadas aplicações de hashing. Para obter mais informações, consulte Vetor binário e Vetor esparso.
Utilizar vectores densos em Milvus
Adicionar campo vetorial
Para utilizar vectores densos no Milvus, comece por definir um campo vetorial para armazenar vectores densos ao criar uma coleção. Este processo inclui.
Definir
datatype
para um tipo de dados de vetor denso suportado. Para conhecer os tipos de dados de vetor denso suportados, consulte Tipos de dados.Especificar as dimensões do vetor denso usando o parâmetro
dim
.
No exemplo abaixo, adicionamos um campo de vetor chamado dense_vector
para armazenar vetores densos. O tipo de dados do campo é FLOAT_VECTOR
, com uma dimensão de 4
.
from pymilvus import MilvusClient, DataType
client = MilvusClient(uri="http://localhost:19530")
schema = client.create_schema(
auto_id=True,
enable_dynamic_fields=True,
)
schema.add_field(field_name="pk", datatype=DataType.VARCHAR, is_primary=True, max_length=100)
schema.add_field(field_name="dense_vector", datatype=DataType.FLOAT_VECTOR, dim=4)
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.common.DataType;
import io.milvus.v2.service.collection.request.AddFieldReq;
import io.milvus.v2.service.collection.request.CreateCollectionReq;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("http://localhost:19530")
.build());
CreateCollectionReq.CollectionSchema schema = client.createSchema();
schema.setEnableDynamicField(true);
schema.addField(AddFieldReq.builder()
.fieldName("pk")
.dataType(DataType.VarChar)
.isPrimaryKey(true)
.autoID(true)
.maxLength(100)
.build());
schema.addField(AddFieldReq.builder()
.fieldName("dense_vector")
.dataType(DataType.FloatVector)
.dimension(4)
.build());
import { DataType } from "@zilliz/milvus2-sdk-node";
schema.push({
name: "dense_vector",
data_type: DataType.FloatVector,
dim: 128,
});
export primaryField='{
"fieldName": "pk",
"dataType": "VarChar",
"isPrimary": true,
"elementTypeParams": {
"max_length": 100
}
}'
export vectorField='{
"fieldName": "dense_vector",
"dataType": "FloatVector",
"elementTypeParams": {
"dim": 4
}
}'
export schema="{
\"autoID\": true,
\"fields\": [
$primaryField,
$vectorField
]
}"
Tipos de dados suportados para campos vetoriais densos:
Tipo | Descrição |
---|---|
FLOAT_VECTOR | Armazena números de ponto flutuante de 32 bits, normalmente utilizados para representar números reais em cálculos científicos e aprendizagem automática. Ideal para cenários que exigem elevada precisão, como a distinção de vectores semelhantes. |
FLOAT16_VECTOR | Armazena números de vírgula flutuante de meia-precisão de 16 bits, utilizados para aprendizagem profunda e cálculos de GPU. Poupa espaço de armazenamento em cenários em que a precisão é menos crítica, como na fase de recuperação de baixa precisão dos sistemas de recomendação. |
BFLOAT16_VECTOR | Armazena números Brain Floating Point (bfloat16) de 16 bits, oferecendo a mesma gama de expoentes que o Float32, mas com precisão reduzida. Adequado para cenários que necessitam de processar rapidamente grandes volumes de vectores, como a recuperação de imagens em grande escala. |
Definir parâmetros de índice para o campo de vetor
Para acelerar as pesquisas semânticas, deve ser criado um índice para o campo de vetor. A indexação pode melhorar significativamente a eficiência da recuperação de dados vetoriais em grande escala.
index_params = client.prepare_index_params()
index_params.add_index(
field_name="dense_vector",
index_name="dense_vector_index",
index_type="IVF_FLAT",
metric_type="IP",
params={"nlist": 128}
)
import io.milvus.v2.common.IndexParam;
import java.util.*;
List<IndexParam> indexes = new ArrayList<>();
Map<String,Object> extraParams = new HashMap<>();
extraParams.put("nlist",128);
indexes.add(IndexParam.builder()
.fieldName("dense_vector")
.indexType(IndexParam.IndexType.IVF_FLAT)
.metricType(IndexParam.MetricType.IP)
.extraParams(extraParams)
.build());
import { MetricType, IndexType } from "@zilliz/milvus2-sdk-node";
const indexParams = {
index_name: 'dense_vector_index',
field_name: 'dense_vector',
metric_type: MetricType.IP,
index_type: IndexType.IVF_FLAT,
params: {
nlist: 128
},
};
export indexParams='[
{
"fieldName": "dense_vector",
"metricType": "IP",
"indexName": "dense_vector_index",
"indexType": "IVF_FLAT",
"params":{"nlist": 128}
}
]'
No exemplo acima, um índice chamado dense_vector_index
é criado para o campo dense_vector
usando o tipo de índice IVF_FLAT
. O metric_type
é definido como IP
, indicando que o produto interno será utilizado como a métrica de distância.
O Milvus também suporta outros tipos de índices. Para mais detalhes, consulte Índices de vectores flutuantes. Adicionalmente, Milvus suporta outros tipos de métricas. Para obter mais informações, consulte Tipos de métricas.
Criar coleção
Quando as definições do vetor denso e dos parâmetros do índice estiverem concluídas, pode criar uma coleção que contenha vectores densos. O exemplo abaixo usa o método create_collection
para criar uma coleção chamada my_dense_collection
.
client.create_collection(
collection_name="my_dense_collection",
schema=schema,
index_params=index_params
)
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("http://localhost:19530")
.build());
CreateCollectionReq requestCreate = CreateCollectionReq.builder()
.collectionName("my_dense_collection")
.collectionSchema(schema)
.indexParams(indexes)
.build();
client.createCollection(requestCreate);
import { MilvusClient } from "@zilliz/milvus2-sdk-node";
const client = new MilvusClient({
address: 'http://localhost:19530'
});
await client.createCollection({
collection_name: 'my_dense_collection',
schema: schema,
index_params: indexParams
});
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d "{
\"collectionName\": \"my_dense_collection\",
\"schema\": $schema,
\"indexParams\": $indexParams
}"
Inserir dados
Depois de criar a coleção, use o método insert
para adicionar dados contendo vetores densos. Certifique-se de que a dimensionalidade dos vetores densos que estão sendo inseridos corresponde ao valor dim
definido ao adicionar o campo de vetor denso.
data = [
{"dense_vector": [0.1, 0.2, 0.3, 0.7]},
{"dense_vector": [0.2, 0.3, 0.4, 0.8]},
]
client.insert(
collection_name="my_dense_collection",
data=data
)
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import io.milvus.v2.service.vector.request.InsertReq;
import io.milvus.v2.service.vector.response.InsertResp;
List<JsonObject> rows = new ArrayList<>();
Gson gson = new Gson();
rows.add(gson.fromJson("{\"dense_vector\": [0.1, 0.2, 0.3, 0.4]}", JsonObject.class));
rows.add(gson.fromJson("{\"dense_vector\": [0.2, 0.3, 0.4, 0.5]}", JsonObject.class));
InsertResp insertR = client.insert(InsertReq.builder()
.collectionName("my_dense_collection")
.data(rows)
.build());
const data = [
{ dense_vector: [0.1, 0.2, 0.3, 0.7] },
{ dense_vector: [0.2, 0.3, 0.4, 0.8] },
];
client.insert({
collection_name: "my_dense_collection",
data: data,
});
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/insert" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"data": [
{"dense_vector": [0.1, 0.2, 0.3, 0.4]},
{"dense_vector": [0.2, 0.3, 0.4, 0.5]}
],
"collectionName": "my_dense_collection"
}'
## {"code":0,"cost":0,"data":{"insertCount":2,"insertIds":["453577185629572531","453577185629572532"]}}
Realizar pesquisa de similaridade
A pesquisa semântica baseada em vectores densos é uma das principais funcionalidades do Milvus, permitindo-lhe encontrar rapidamente os dados mais semelhantes a um vetor de consulta com base na distância entre vectores. Para realizar uma pesquisa por semelhança, prepare o vetor de consulta e os parâmetros de pesquisa e, em seguida, chame o método search
.
search_params = {
"params": {"nprobe": 10}
}
query_vector = [0.1, 0.2, 0.3, 0.7]
res = client.search(
collection_name="my_dense_collection",
data=[query_vector],
anns_field="dense_vector",
search_params=search_params,
limit=5,
output_fields=["pk"]
)
print(res)
# Output
# data: ["[{'id': '453718927992172271', 'distance': 0.7599999904632568, 'entity': {'pk': '453718927992172271'}}, {'id': '453718927992172270', 'distance': 0.6299999952316284, 'entity': {'pk': '453718927992172270'}}]"]
import io.milvus.v2.service.vector.request.data.FloatVec;
Map<String,Object> searchParams = new HashMap<>();
searchParams.put("nprobe",10);
FloatVec queryVector = new FloatVec(new float[]{0.1f, 0.3f, 0.3f, 0.4f});
SearchResp searchR = client.search(SearchReq.builder()
.collectionName("my_dense_collection")
.data(Collections.singletonList(queryVector))
.annsField("dense_vector")
.searchParams(searchParams)
.topK(5)
.outputFields(Collections.singletonList("pk"))
.build());
System.out.println(searchR.getSearchResults());
// Output
//
// [[SearchResp.SearchResult(entity={pk=453444327741536779}, score=0.65, id=453444327741536779), SearchResp.SearchResult(entity={pk=453444327741536778}, score=0.65, id=453444327741536778)]]
query_vector = [0.1, 0.2, 0.3, 0.7];
client.search({
collection_name: my_dense_collection,
data: query_vector,
limit: 5,
output_fields: ['pk'],
params: {
nprobe: 10
}
});
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/search" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_dense_collection",
"data": [
[0.1, 0.2, 0.3, 0.7]
],
"annsField": "dense_vector",
"limit": 5,
"searchParams":{
"params":{"nprobe":10}
},
"outputFields": ["pk"]
}'
## {"code":0,"cost":0,"data":[{"distance":0.55,"id":"453577185629572532","pk":"453577185629572532"},{"distance":0.42,"id":"453577185629572531","pk":"453577185629572531"}]}
Para obter mais informações sobre os parâmetros de pesquisa de similaridade, consulte Pesquisa ANN básica.