Weighted k-NN Zero-Shot Transfer
Problem Statement
A strong training-free baseline (Tip-Adapter, and CLIP's own linear-probe cousins) classifies a query image by a similarity-weighted vote of its nearest neighbors in a labeled support set of embeddings. Implement it.
Background
Given a query embedding q and a support set of (embedding, label) pairs, score every support example by cosine similarity to q, take the top-k most similar, and let each vote for its label with a weight of exp(beta * (sim - 1)) (the sharpening used by Tip-Adapter; beta > 0). The predicted class is the label with the greatest total weight.
Tie-breaking, in order:
- Highest total vote weight.
- If tied, the label whose single best (highest-similarity) neighbor is more similar.
- If still tied, the smaller label value.
Assume all embeddings are already L2-normalized, so cosine similarity is the dot product.
Your Task
Implement:
def knn_zero_shot(query, support_embs, support_labels, k, beta):
Return the predicted label (an int).
Input Format
- query: list of floats (unit vector).
- support_embs: M x D nested list (unit vectors).
- support_labels: list of M int labels.
- k (int), beta (float).
Output Format
- A single int label.
Sample
q = [1.0, 0.0]
se = [[1.0, 0.0], [0.9, 0.44], [0.0, 1.0]]
sl = [0, 0, 1]
print(knn_zero_shot(q, se, sl, 2, 5.0))
Output:
0
Example:
q = [1.0, 0.0] se = [[1.0, 0.0], [0.9, 0.44], [0.0, 1.0]] sl = [0, 0, 1] print(knn_zero_shot(q, se, sl, 2, 5.0))
0
The two nearest neighbors both carry label 0 (sims 1.0 and 0.9), so label 0 wins the weighted vote outright.
Constraints:
1 <= k <= M <= 5000,1 <= D <= 1024,beta > 0.- Similarity is the dot product (inputs are unit vectors).
- Top-k by similarity; ties within selection go to the smaller support index.
- Apply the three-level tie-break for the final label exactly as described.