🚀 جرب Zilliz Cloud، الـ Milvus المدارة بالكامل، مجاناً — تجربة أداء أسرع بـ 10 أضعاف! جرب الآن>>

milvus-logo
LFAI
الصفحة الرئيسية
  • دليل المستخدم
  • Home
  • Docs
  • دليل المستخدم

  • المخطط وحقول البيانات

  • متجه ثنائي

المتجهات الثنائية

المتجهات الثنائية هي شكل خاص من أشكال تمثيل البيانات التي تحول متجهات الفاصلة العائمة التقليدية عالية الأبعاد إلى متجهات ثنائية تحتوي على 0 و1 فقط. لا يؤدي هذا التحويل إلى ضغط حجم المتجه فحسب، بل يقلل أيضًا من تكاليف التخزين والتكاليف الحسابية مع الاحتفاظ بالمعلومات الدلالية. عندما لا تكون الدقة للخصائص غير الحرجة ضرورية، يمكن للمتجهات الثنائية أن تحافظ بشكل فعال على معظم سلامة وفائدة متجهات الفاصلة العائمة الأصلية.

تتمتع المتجهات الثنائية بمجموعة واسعة من التطبيقات، خاصة في الحالات التي تكون فيها الكفاءة الحسابية وتحسين التخزين أمرًا بالغ الأهمية. في أنظمة الذكاء الاصطناعي واسعة النطاق، مثل محركات البحث أو أنظمة التوصية، تعد المعالجة الآنية لكميات هائلة من البيانات أمرًا أساسيًا. من خلال تقليل حجم المتجهات، تساعد المتجهات الثنائية في تقليل زمن الاستجابة والتكاليف الحسابية دون التضحية بالدقة بشكل كبير. بالإضافة إلى ذلك، تُعدّ المتجهات الثنائية مفيدة في البيئات المحدودة الموارد، مثل الأجهزة المحمولة والأنظمة المدمجة، حيث تكون الذاكرة وقوة المعالجة محدودة. من خلال استخدام المتجهات الثنائية، يمكن تنفيذ وظائف الذكاء الاصطناعي المعقدة في هذه البيئات المحدودة مع الحفاظ على الأداء العالي.

نظرة عامة

المتجهات الثنائية هي طريقة لترميز الكائنات المعقدة (مثل الصور أو النصوص أو الصوت) إلى قيم ثنائية ذات طول ثابت. في ميلفوس، يتم تمثيل المتجهات الثنائية عادةً كمصفوفات بت أو مصفوفات بايت. على سبيل المثال، يمكن تمثيل متجه ثنائي ثنائي 8 أبعاد على شكل [1, 0, 1, 1, 0, 0, 1, 0].

يوضح الرسم البياني أدناه كيف تمثل المتجهات الثنائية وجود كلمات رئيسية في محتوى النص. في هذا المثال، يتم استخدام متجه ثنائي من 10 أبعاد لتمثيل نصين مختلفين(النص 1 والنص 2)، حيث يتوافق كل بُعد مع كلمة في المفردات: 1 يشير إلى وجود الكلمة في النص، بينما يشير 0 إلى غيابها.

Binary vector representation of text content التمثيل المتجه الثنائي لمحتوى النص

تتميز المتجهات الثنائية بالخصائص التالية.

  • كفاءة التخزين: يتطلب كل بُعد تخزين بت واحد فقط، مما يقلل من مساحة التخزين بشكل كبير.

  • الحساب السريع: يمكن حساب التشابه بين المتجهات بسرعة باستخدام عمليات متشابهة البتات مثل XOR.

  • طول ثابت: يظل طول المتجه ثابتًا بغض النظر عن طول النص الأصلي، مما يجعل الفهرسة والاسترجاع أسهل.

  • بسيط وبديهي: يعكس مباشرةً وجود الكلمات الرئيسية، مما يجعله مناسبًا لبعض مهام الاسترجاع المتخصصة.

يمكن إنشاء المتجهات الثنائية من خلال طرق مختلفة. في معالجة النصوص، يمكن استخدام المفردات المحددة مسبقًا لتعيين البتات المقابلة بناءً على وجود الكلمات. في معالجة الصور، يمكن لخوارزميات التجزئة الإدراكية (مثل pHash) توليد ميزات ثنائية للصور. في تطبيقات التعلّم الآلي، يمكن تحويل مخرجات النماذج إلى ثنائية للحصول على تمثيلات متجهات ثنائية.

بعد تحويلها إلى متجهات ثنائية، يمكن تخزين البيانات في ميلفوس للإدارة واسترجاع المتجهات. يوضح الرسم البياني أدناه العملية الأساسية.

Use binary vectors in Milvus استخدام المتجهات الثنائية في ملفوس

على الرغم من أن المتجهات الثنائية تتفوق في سيناريوهات محددة، إلا أن لها قيودًا في قدرتها التعبيرية، مما يجعل من الصعب التقاط العلاقات الدلالية المعقدة. لذلك، في سيناريوهات العالم الحقيقي، غالبًا ما تُستخدم المتجهات الثنائية جنبًا إلى جنب مع أنواع المتجهات الأخرى لتحقيق التوازن بين الكفاءة والتعبير. لمزيد من المعلومات، راجع المتجهات الكثيفة والمتجهات المتفرقة.

استخدام المتجهات الثنائية في ميلفوس

إضافة حقل متجه

لاستخدام المتجهات الثنائية في ملفوس، قم أولاً بتعريف حقل متجه لتخزين المتجهات الثنائية عند إنشاء مجموعة. تتضمن هذه العملية.

  1. تعيين datatype إلى نوع بيانات المتجه الثنائي المدعوم، أي BINARY_VECTOR.

  2. تحديد أبعاد المتجه باستخدام المعلمة dim. لاحظ أنه يجب أن يكون dim من مضاعفات العدد 8 حيث يجب تحويل المتجهات الثنائية إلى مصفوفة بايت عند الإدراج. سيتم تعبئة كل 8 قيم منطقية (0 أو 1) في بايت واحد. على سبيل المثال، إذا كان dim=128 ، يلزم وجود مصفوفة 16 بايت للإدراج.

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="binary_vector", datatype=DataType.BINARY_VECTOR, dim=128)

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("binary_vector")
        .dataType(DataType.BinaryVector)
        .dimension(128)
        .build());

import { DataType } from "@zilliz/milvus2-sdk-node";

schema.push({
  name: "binary vector",
  data_type: DataType.BinaryVector,
  dim: 128,
});

export primaryField='{
    "fieldName": "pk",
    "dataType": "VarChar",
    "isPrimary": true,
    "elementTypeParams": {
        "max_length": 100
    }
}'

export vectorField='{
    "fieldName": "binary_vector",
    "dataType": "BinaryVector",
    "elementTypeParams": {
        "dim": 128
    }
}'

export schema="{
    \"autoID\": true,
    \"fields\": [
        $primaryField,
        $vectorField
    ],
    \"enableDynamicField\": true
}"


في هذا المثال، تمت إضافة حقل متجه باسم binary_vector لتخزين المتجهات الثنائية. نوع بيانات هذا الحقل هو BINARY_VECTOR ، ببعد 128.

تعيين بارامترات الفهرس لحقل المتجه

لتسريع عمليات البحث، يجب إنشاء فهرس لحقل المتجه الثنائي. يمكن للفهرسة تحسين كفاءة استرجاع البيانات المتجهة واسعة النطاق بشكل كبير.

index_params = client.prepare_index_params()

index_params.add_index(
    field_name="binary_vector",
    index_name="binary_vector_index",
    index_type="BIN_IVF_FLAT",
    metric_type="HAMMING",
    params={"nlist": 128}
)

import io.milvus.v2.common.IndexParam;
import java.util.*;

List<IndexParam> indexParams = new ArrayList<>();
Map<String,Object> extraParams = new HashMap<>();
extraParams.put("nlist",128);
indexParams.add(IndexParam.builder()
        .fieldName("binary_vector")
        .indexType(IndexParam.IndexType.BIN_IVF_FLAT)
        .metricType(IndexParam.MetricType.HAMMING)
        .extraParams(extraParams)
        .build());

import { MetricType, IndexType } from "@zilliz/milvus2-sdk-node";

const indexParams = {
  indexName: "binary_vector_index",
  field_name: "binary_vector",
  metric_type: MetricType.HAMMING,
  index_type: IndexType.BIN_IVF_FLAT,
  params: {
    nlist: 128,
  },
};

export indexParams='[
        {
            "fieldName": "binary_vector",
            "metricType": "HAMMING",
            "indexName": "binary_vector_index",
            "indexType": "BIN_IVF_FLAT",
            "params":{"nlist": 128}
        }
    ]'

في المثال أعلاه، يتم إنشاء فهرس باسم binary_vector_index للحقل binary_vector ، باستخدام نوع الفهرس BIN_IVF_FLAT. تم تعيين metric_type على HAMMING ، مما يشير إلى استخدام مسافة هامينج لقياس التشابه.

إلى جانب BIN_IVF_FLAT ، يدعم ميلفوس أنواع الفهارس الأخرى للمتجهات الثنائية. لمزيد من التفاصيل، راجع فهارس المتجهات الثنائية. بالإضافة إلى ذلك، يدعم ميلفوس مقاييس تشابه أخرى للمتجهات الثنائية. لمزيد من المعلومات، راجع أنواع المقاييس.

إنشاء مجموعة

بمجرد اكتمال إعدادات المتجه الثنائي والفهرس الثنائي، قم بإنشاء مجموعة تحتوي على متجهات ثنائية. يستخدم المثال أدناه طريقة create_collection لإنشاء مجموعة باسم my_binary_collection.

client.create_collection(
    collection_name="my_binary_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_binary_collection")
        .collectionSchema(schema)
        .indexParams(indexParams)
        .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_binary_collection\",
    \"schema\": $schema,
    \"indexParams\": $indexParams
}"

إدراج البيانات

بعد إنشاء المجموعة، استخدم الأسلوب insert لإضافة بيانات تحتوي على متجهات ثنائية. لاحظ أنه يجب توفير المتجهات الثنائية على شكل مصفوفة بايت، حيث يمثل كل بايت 8 قيم منطقية.

على سبيل المثال، بالنسبة إلى متجه ثنائي مكون من 128 بُعدًا، يلزم توفير مصفوفة من 16 بايت (بما أن 128 بت ÷ 8 بت/بايت = 16 بايت). فيما يلي مثال على شيفرة لإدخال البيانات.

def convert_bool_list_to_bytes(bool_list):
    if len(bool_list) % 8 != 0:
        raise ValueError("The length of a boolean list must be a multiple of 8")

    byte_array = bytearray(len(bool_list) // 8)
    for i, bit in enumerate(bool_list):
        if bit == 1:
            index = i // 8
            shift = i % 8
            byte_array[index] |= (1 << shift)
    return bytes(byte_array)


bool_vectors = [
    [1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0] + [0] * 112,
    [0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1] + [0] * 112,
]

data = [{"binary_vector": convert_bool_list_to_bytes(bool_vector) for bool_vector in bool_vectors}]

client.insert(
    collection_name="my_binary_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;

private static byte[] convertBoolArrayToBytes(boolean[] booleanArray) {
    byte[] byteArray = new byte[booleanArray.length / Byte.SIZE];
    for (int i = 0; i < booleanArray.length; i++) {
        if (booleanArray[i]) {
            int index = i / Byte.SIZE;
            int shift = i % Byte.SIZE;
            byteArray[index] |= (byte) (1 << shift);
        }
    }

    return byteArray;
}

List<JsonObject> rows = new ArrayList<>();
Gson gson = new Gson();
{
    boolean[] boolArray = {true, false, false, true, true, false, true, true, false, true, false, false, true, true, false, true};
    JsonObject row = new JsonObject();
    row.add("binary_vector", gson.toJsonTree(convertBoolArrayToBytes(boolArray)));
    rows.add(row);
}
{
    boolean[] boolArray = {false, true, false, true, false, true, false, false, true, true, false, false, true, true, false, true};
    JsonObject row = new JsonObject();
    row.add("binary_vector", gson.toJsonTree(convertBoolArrayToBytes(boolArray)));
    rows.add(row);
}

InsertResp insertR = client.insert(InsertReq.builder()
        .collectionName("my_binary_collection")
        .data(rows)
        .build());

const data = [
  { binary_vector: [1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1] },
  { binary_vector: [1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1] },
];

client.insert({
  collection_name: "my_binary_collection",
  data: data,
});

curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/insert" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d "{
    \"data\": $data,
    \"collectionName\": \"my_binary_collection\"
}"

البحث عن التشابه هو أحد الميزات الأساسية في ميلفوس، مما يسمح لك بالعثور بسرعة على البيانات الأكثر تشابهًا مع متجه الاستعلام بناءً على المسافة بين المتجهات. لإجراء بحث تشابه باستخدام متجهات ثنائية، قم بإعداد متجه الاستعلام ومعلمات البحث، ثم قم باستدعاء الطريقة search.

أثناء عمليات البحث، يجب أيضًا توفير المتجهات الثنائية في شكل مصفوفة بايت. تأكد من أن أبعاد متجه الاستعلام تتطابق مع البعد المحدد عند تحديد dim وأن كل 8 قيم منطقية يتم تحويلها إلى بايت واحد.

search_params = {
    "params": {"nprobe": 10}
}

query_bool_list = [1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0] + [0] * 112
query_vector = convert_bool_list_to_bytes(query_bool_list)

res = client.search(
    collection_name="my_binary_collection",
    data=[query_vector],
    anns_field="binary_vector",
    search_params=search_params,
    limit=5,
    output_fields=["pk"]
)

print(res)

# Output
# data: ["[{'id': '453718927992172268', 'distance': 10.0, 'entity': {'pk': '453718927992172268'}}]"] 

import io.milvus.v2.service.vector.request.SearchReq;
import io.milvus.v2.service.vector.request.data.BinaryVec;
import io.milvus.v2.service.vector.response.SearchResp;

Map<String,Object> searchParams = new HashMap<>();
searchParams.put("nprobe",10);

boolean[] boolArray = {true, false, false, true, true, false, true, true, false, true, false, false, true, true, false, true};
BinaryVec queryVector = new BinaryVec(convertBoolArrayToBytes(boolArray));

SearchResp searchR = client.search(SearchReq.builder()
        .collectionName("my_binary_collection")
        .data(Collections.singletonList(queryVector))
        .annsField("binary_vector")
        .searchParams(searchParams)
        .topK(5)
        .outputFields(Collections.singletonList("pk"))
        .build());
        
 System.out.println(searchR.getSearchResults());
 
 // Output
 //
 // [[SearchResp.SearchResult(entity={pk=453444327741536775}, score=0.0, id=453444327741536775), SearchResp.SearchResult(entity={pk=453444327741536776}, score=7.0, id=453444327741536776)]]

query_vector = [1,0,1,0,1,1,1,1,1,1,1,1];

client.search({
    collection_name: 'my_binary_collection',
    data: query_vector,
    limit: 5,
    output_fields: ['pk'],
    params: {
        nprobe: 10
    }
});

export searchParams='{
        "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_binary_collection\",
    \"data\": $data,
    \"annsField\": \"binary_vector\",
    \"limit\": 5,
    \"searchParams\":$searchParams,
    \"outputFields\": [\"pk\"]
}"

لمزيد من المعلومات حول معلمات بحث التشابه، راجع بحث ANN الأساسي.

جرب Managed Milvus مجاناً

Zilliz Cloud خالي من المتاعب، ويعمل بواسطة Milvus ويعمل بسرعة 10 أضعاف.

ابدأ
التعليقات

هل كانت هذه الصفحة مفيدة؟