Skip to content

Commit a100d92

Browse files
kolchfa-awsNaarcha-AWSnatebower
authored andcommitted
Add quantization techniques and links to byte vector (#4893)
* Add quantization techniquest and links to byte vector Signed-off-by: Fanit Kolchina <kolchfa@amazon.com> * Added cosine similarity space type quantization Signed-off-by: Fanit Kolchina <kolchfa@amazon.com> * Rewording Signed-off-by: Fanit Kolchina <kolchfa@amazon.com> * Tech review feedback Signed-off-by: Fanit Kolchina <kolchfa@amazon.com> * Tech review feedback Signed-off-by: Fanit Kolchina <kolchfa@amazon.com> * Remove redundant line Signed-off-by: Fanit Kolchina <kolchfa@amazon.com> * Update _field-types/supported-field-types/knn-vector.md Co-authored-by: Naarcha-AWS <97990722+Naarcha-AWS@users.noreply.github.com> Signed-off-by: kolchfa-aws <105444904+kolchfa-aws@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Nathan Bower <nbower@amazon.com> Signed-off-by: kolchfa-aws <105444904+kolchfa-aws@users.noreply.github.com> * Update _field-types/supported-field-types/knn-vector.md Signed-off-by: kolchfa-aws <105444904+kolchfa-aws@users.noreply.github.com> * Editorial feedback Signed-off-by: Fanit Kolchina <kolchfa@amazon.com> --------- Signed-off-by: Fanit Kolchina <kolchfa@amazon.com> Signed-off-by: kolchfa-aws <105444904+kolchfa-aws@users.noreply.github.com> Co-authored-by: Naarcha-AWS <97990722+Naarcha-AWS@users.noreply.github.com> Co-authored-by: Nathan Bower <nbower@amazon.com>
1 parent 732e775 commit a100d92

File tree

2 files changed

+112
-4
lines changed

2 files changed

+112
-4
lines changed

_field-types/supported-field-types/knn-vector.md

Lines changed: 108 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ title: k-NN vector
44
nav_order: 58
55
has_children: false
66
parent: Supported field types
7+
has_math: true
78
---
89

910
# k-NN vector
1011

11-
The k-NN plugin introduces a custom data type, the `knn_vector`, that allows users to ingest their k-NN vectors
12+
The [k-NN plugin]({{site.url}}{{site.baseurl}}/search-plugins/knn/index/) introduces a custom data type, the `knn_vector`, that allows users to ingest their k-NN vectors.
1213
into an OpenSearch index and perform different kinds of k-NN search. The `knn_vector` field is highly configurable and can serve many different k-NN workloads. In general, a `knn_vector` field can be built either by providing a method definition or specifying a model id.
1314

1415
## Example
@@ -47,7 +48,7 @@ PUT test-index
4748

4849
## Method definitions
4950

50-
Method definitions are used when the underlying Approximate k-NN algorithm does not require training. For example, the following `knn_vector` field specifies that *nmslib*'s implementation of *hnsw* should be used for Approximate k-NN search. During indexing, *nmslib* will build the corresponding *hnsw* segment files.
51+
[Method definitions]({{site.url}}{{site.baseurl}}/search-plugins/knn/knn-index#method-definitions) are used when the underlying [approximate k-NN]({{site.url}}{{site.baseurl}}/search-plugins/knn/approximate-knn/) algorithm does not require training. For example, the following `knn_vector` field specifies that *nmslib*'s implementation of *hnsw* should be used for approximate k-NN search. During indexing, *nmslib* will build the corresponding *hnsw* segment files.
5152

5253
```json
5354
"my_vector": {
@@ -77,7 +78,7 @@ model contains the information needed to initialize the native library segment f
7778
}
7879
```
7980

80-
However, if you intend to just use painless scripting or a k-NN score script, you only need to pass the dimension.
81+
However, if you intend to use Painless scripting or a k-NN score script, you only need to pass the dimension.
8182
```json
8283
"type": "knn_vector",
8384
"dimension": 128
@@ -91,6 +92,8 @@ By default, k-NN vectors are `float` vectors, where each dimension is 4 bytes. I
9192
Byte vectors are supported only for the `lucene` engine. They are not supported for the `nmslib` and `faiss` engines.
9293
{: .note}
9394

95+
In [k-NN benchmarking tests](https://github.com/opensearch-project/k-NN/tree/main/benchmarks/perf-tool), the use of `byte` rather than `float` vectors resulted in a significant reduction in storage and memory usage as well as improved indexing throughput and reduced query latency. Additionally, precision on recall was not greatly affected (note that recall can depend on various factors, such as the [quantization technique](#quantization-techniques) and data distribution).
96+
9497
When using `byte` vectors, expect some loss of precision in the recall compared to using `float` vectors. Byte vectors are useful in large-scale applications and use cases that prioritize a reduced memory footprint in exchange for a minimal loss of recall.
9598
{: .important}
9699

@@ -163,4 +166,105 @@ GET test-index/_search
163166
}
164167
}
165168
```
166-
{% include copy-curl.html %}
169+
{% include copy-curl.html %}
170+
171+
### Quantization techniques
172+
173+
If your vectors are of the type `float`, you need to first convert them to the `byte` type before ingesting the documents. This conversion is accomplished by _quantizing the dataset_---reducing the precision of its vectors. There are many quantization techniques, such as scalar quantization or product quantization (PQ), which is used in the Faiss engine. The choice of quantization technique depends on the type of data you're using and can affect the accuracy of recall values. The following sections describe the scalar quantization algorithms that were used to quantize the [k-NN benchmarking test](https://github.com/opensearch-project/k-NN/tree/main/benchmarks/perf-tool) data for the [L2](#scalar-quantization-for-the-l2-space-type) and [cosine similarity](#scalar-quantization-for-the-cosine-similarity-space-type) space types. The provided pseudocode is for illustration purposes only.
174+
175+
#### Scalar quantization for the L2 space type
176+
177+
The following example pseudocode illustrates the scalar quantization technique used for the benchmarking tests on Euclidean datasets with the L2 space type. Euclidean distance is shift invariant. If you shift both $$x$$ and $$y$$ by the same $$z$$, then the distance remains the same ($$\lVert x-y\rVert =\lVert (x-z)-(y-z)\rVert$$).
178+
179+
```python
180+
# Random dataset (Example to create a random dataset)
181+
dataset = np.random.uniform(-300, 300, (100, 10))
182+
# Random query set (Example to create a random queryset)
183+
queryset = np.random.uniform(-350, 350, (100, 10))
184+
# Number of values
185+
B = 256
186+
187+
# INDEXING:
188+
# Get min and max
189+
dataset_min = np.min(dataset)
190+
dataset_max = np.max(dataset)
191+
# Shift coordinates to be non-negative
192+
dataset -= dataset_min
193+
# Normalize into [0, 1]
194+
dataset *= 1. / (dataset_max - dataset_min)
195+
# Bucket into 256 values
196+
dataset = np.floor(dataset * (B - 1)) - int(B / 2)
197+
198+
# QUERYING:
199+
# Clip (if queryset range is out of datset range)
200+
queryset = queryset.clip(dataset_min, dataset_max)
201+
# Shift coordinates to be non-negative
202+
queryset -= dataset_min
203+
# Normalize
204+
queryset *= 1. / (dataset_max - dataset_min)
205+
# Bucket into 256 values
206+
queryset = np.floor(queryset * (B - 1)) - int(B / 2)
207+
```
208+
{% include copy.html %}
209+
210+
#### Scalar quantization for the cosine similarity space type
211+
212+
The following example pseudocode illustrates the scalar quantization technique used for the benchmarking tests on angular datasets with the cosine similarity space type. Cosine similarity is not shift invariant ($$cos(x, y) \neq cos(x-z, y-z)$$).
213+
214+
The following pseudocode is for positive numbers:
215+
216+
```python
217+
# For Positive Numbers
218+
219+
# INDEXING and QUERYING:
220+
221+
# Get Max of train dataset
222+
max = np.max(dataset)
223+
min = 0
224+
B = 127
225+
226+
# Normalize into [0,1]
227+
val = (val - min) / (max - min)
228+
val = (val * B)
229+
230+
# Get int and fraction values
231+
int_part = floor(val)
232+
frac_part = val - int_part
233+
234+
if 0.5 < frac_part:
235+
bval = int_part + 1
236+
else:
237+
bval = int_part
238+
239+
return Byte(bval)
240+
```
241+
{% include copy.html %}
242+
243+
The following pseudocode is for negative numbers:
244+
245+
```python
246+
# For Negative Numbers
247+
248+
# INDEXING and QUERYING:
249+
250+
# Get Min of train dataset
251+
min = 0
252+
max = -np.min(dataset)
253+
B = 128
254+
255+
# Normalize into [0,1]
256+
val = (val - min) / (max - min)
257+
val = (val * B)
258+
259+
# Get int and fraction values
260+
int_part = floor(var)
261+
frac_part = val - int_part
262+
263+
if 0.5 < frac_part:
264+
bval = int_part + 1
265+
else:
266+
bval = int_part
267+
268+
return Byte(bval)
269+
```
270+
{% include copy.html %}

_search-plugins/knn/knn-index.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ has_children: false
1111
The k-NN plugin introduces a custom data type, the `knn_vector`, that allows users to ingest their k-NN vectors
1212
into an OpenSearch index and perform different kinds of k-NN search. The `knn_vector` field is highly configurable and can serve many different k-NN workloads. For more information, see [k-NN vector]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/knn-vector/).
1313

14+
## Lucene byte vector
15+
16+
Starting with k-NN plugin version 2.9, you can use `byte` vectors with the `lucene` engine in order to reduce the amount of storage space needed. For more information, see [Lucene byte vector]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/knn-vector#lucene-byte-vector).
17+
1418
## Method definitions
1519

1620
A method definition refers to the underlying configuration of the Approximate k-NN algorithm you want to use. Method definitions are used to either create a `knn_vector` field (when the method does not require training) or [create a model during training]({{site.url}}{{site.baseurl}}/search-plugins/knn/api#train-model) that can then be used to [create a `knn_vector` field]({{site.url}}{{site.baseurl}}/search-plugins/knn/approximate-knn/#building-a-k-nn-index-from-a-model).

0 commit comments

Comments
 (0)