-
Notifications
You must be signed in to change notification settings - Fork 144
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implementation of Random Rotation Matrix and Query Scaling Matrix with 1-bit Binary Quantization #2524
base: main
Are you sure you want to change the base?
Conversation
…above and below thresholds for 1 bit Binary Quantization Signed-off-by: Vikasht34 <[email protected]>
Signed-off-by: Vikasht34 <[email protected]>
Signed-off-by: Vikasht34 <[email protected]>
Signed-off-by: Vikasht34 <[email protected]>
f5e801f
to
dad6872
Compare
Signed-off-by: Vikasht34 <[email protected]>
* Represents the mean of all values below the threshold for each dimension. | ||
*/ | ||
@Builder.Default | ||
private float[] belowThresholdMeans = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add examples for these, as was done for meanThresholds?
@Builder.Default | ||
private float[] aboveThresholdMeans = null; | ||
@Builder.Default | ||
private double averageL2L1Ratio = 0.0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a comment on this?
@@ -51,6 +76,20 @@ public void writeTo(StreamOutput out) throws IOException { | |||
out.writeVInt(Version.CURRENT.id); // Write the version | |||
quantizationParams.writeTo(out); | |||
out.writeFloatArray(meanThresholds); | |||
out.writeOptionalArray(belowThresholdMeans != null ? new FloatArrayWrapper[] { new FloatArrayWrapper(belowThresholdMeans) } : null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For BWC purposes, writeOptionalArray wont work in a mixed cluster state. We need to check the stream version.
@Builder.Default | ||
private double averageL2L1Ratio = 0.0; | ||
/** | ||
* Rotation matrix used when L2/L1 ratio > 0.6 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add more detail? For instance, what are the properties of this matrix. Also, what will happen if L2/L1 ratio is < 0.6
@@ -63,6 +102,23 @@ public OneBitScalarQuantizationState(StreamInput in) throws IOException { | |||
int version = in.readVInt(); // Read the version | |||
this.quantizationParams = new ScalarQuantizationParams(in, version); | |||
this.meanThresholds = in.readFloatArray(); | |||
if (Version.fromId(version).onOrAfter(Version.V_3_0_0)) { | |||
// Deserialize belowThresholdMeans using readOptionalArray | |||
FloatArrayWrapper[] wrappedBelowThresholdMeans = in.readOptionalArray(FloatArrayWrapper::new, FloatArrayWrapper[]::new); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why optional on this? Is there a case where its null?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes ..for Version less than 3.0.0
this.array = in.readFloatArray(); | ||
} | ||
|
||
public float[] getArray() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: lombok getter
float[] belowThresholdMeans = belowAboveMeans.getA(); | ||
float[] aboveThresholdMeans = belowAboveMeans.getB(); | ||
|
||
// Apply the same rotation to below and above threshold means if rotation was applied |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In line 60, we apply the rotation on the meanThresholds. Then we calculate the belowAboveMeans with this rotated meanThresholds in line 65. So, shouldnt the returned thresholds already be rotated?
Instead, can we apply rotations to all thresholds at the end (including menathresholds)?
* @throws IOException If an I/O error occurs while retrieving vector data. | ||
* @throws IllegalArgumentException If any vector at the sampled indices is null. | ||
*/ | ||
private static Pair<float[], Double> calculateMeanAndL2L1Ratio(TrainingRequest<float[]> trainingRequest, int[] sampledIndices) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of a pair, can we make this into some kind of object so that we can continue to extend with additional data?
} | ||
} | ||
|
||
// Step 2: Orthogonalize the matrix using the Gram-Schmidt process |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there any libraries we can delegate this computation to?
@@ -63,6 +102,23 @@ public OneBitScalarQuantizationState(StreamInput in) throws IOException { | |||
int version = in.readVInt(); // Read the version |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this going to be bwc? We need to check if the segment was created in a previous version as opposed to the node it is coming from.
@Vikasht34 For this, I think we probably can break up the random rotation and the computation of mean centers into 2 separate features. I think that they can be added independently. |
IMO ..it should be part of whole ADC ...We have seen random rotation giving advantage of some data sets , It's beeter we get combo of ADC + Random Rotation. |
Description
This change enhances the One-Bit Scalar Quantization process in by refining the Below and Above Threshold Means computation and introducing Random Gaussian Rotation. These improvements optimize both quantization accuracy during indexing and query scaling during retrieval, ensuring better recall and efficiency in k-NN search.
Below and Above Threshold Means for Query Scaling
These means help in query-time scaling, enabling better similarity approximation.
Random Gaussian Rotation for Robustness
Applies a Gaussian orthonormal rotation matrix to input vectors before quantization.
Used only when the L2/L1 ratio exceeds 0.6, ensuring that rotation is applied selectively for improved data distribution.
Related Issues
Resolves #[Issue number to be closed when this PR is merged]
Check List
--signoff
.By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.