Given a set S⊂US \subset U of nn points, a metric dd defined on UU, and a query point vv, the nearest neighbor search (NNS) problem finds vv's nearest point in SS:

u=arg⁡min⁡s∈Sd(v,s) u = \arg\min_{s \in S} d(v, s)

Potential applications include web search and clustering.

If UU is a Euclidean space Rd\mathcal{R}^d for some dd, the hardness of NNS depends largely on the value of dd. Suppose d=1d = 1, then we can pre-process the points by building a balanced binary search tree on SS. Finding the nearest point to v∉Sv \notin S reduces to searching for its predecessor and successor, which takes O(log⁡n)O(\log n) time. For d=2d = 2, we can construct a Voronoi diagram.

For higher dimensions dd it is not easy to extend the index structures. A naïve search loops over all points and takes O(nd)O(nd) time. It is natural to ask whether we can do better. If we are willing to sacrifice accuracy for efficiency, this is possible. Instead of finding the exact nearest neighbor, we relax our goal to finding an approximate nearest neighbor whose distance is within 1+ϵ1 + \epsilon of the minimum one.

One possible solution is Johnson–Lindenstrauss decomposition. We can generate a matrix A∈RO(log⁡nϵ2)×dA \in R^{ O( \frac{ \log n }{ \epsilon^2 } )\times d} and multiply it with every element in SS. The mapping u→Auu \rightarrow Au preserves pair-wise distance up to a relative error of ϵ\epsilon. The pre-processing takes O(ndlog⁡nϵ2)O( \frac{n d \log n}{\epsilon^2} ) time. To answer an query, we map vv to AvAv, which takes O(dlog⁡nϵ2)O(\frac{ d\log n }{ \epsilon^2 } ) time. Then we perform a loop over all elements of {Au:u∈S}\{ Au : u \in S\}, which takes O(nlog⁡nϵ2)O(\frac{ n \log n }{ \epsilon^2 } ) time. Therefore, the total time complexity is O((n+d)log⁡nϵ2)O(\frac{ (n + d) \log n }{ \epsilon^2 } ).

Hashing

[1] solves the problem by hashing. We call the pair of points that are close to each other the similar pair and the pair that are far from each other the dissimilar pair. Intuitively, we want similar pairs to be hashed to the same bucket and that dissimilar pairs to be hashed to different buckets.

Instead of finding the (1+ϵ)(1 + \epsilon) approximate nearest neighbor directly, [1] further reduces it to the (c,r)(c, r)-approximate neighbor search (ANNS(c,r)(c, r)) problem, which is defined as follows:

Given a query point vv, if ∃s∈S\exists s \in S, then return a point uu, such that

d(v,u)≤c⋅r d(v, u) \le c \cdot r

The reduction from 1+ϵ1 + \epsilon to ANNS(c,rc, r) is not easy. Here we show one that returns the (1+ϵ)2(1 + \epsilon)^2 approximate nearest neighbor. Let dmax⁡=max⁡s,s′d(s,s′)d_{\max} = \max_{s, s'} d(s, s') and dmin⁡=min⁡s,s′d(s,s′)d_{\min} = \min_{s, s'} d(s, s'). We build a set of structures that answers ANNS(1+ϵ1 + \epsilon, r) queries for the values of rr:

dmin⁡, dmin⁡(1+ϵ), dmin(1+ϵ)2, ..., dmax⁡ d_{\min}, \ d_{\min} (1 + \epsilon ), \ d_{min} (1 + \epsilon)^2,\ ...,\ d_{\max}

Then given the query point vv, we do a binary search to find the smallest rr that returns a point. This imposes an additional cost of ln⁡ln⁡dmax⁡dmin⁡ln⁡(1+ϵ)\ln {\ln \frac{d_{\max} }{d_{\min} } \over \ln (1 + \epsilon) }.

NNS⟶(1+ϵ)NNS⟶ANNS(c,r)⟶(r,cr,p1,p2)-LSH⟶Boosting Probability\text{NNS} \longrightarrow (1+\epsilon) \text{NNS} \longrightarrow \text{ANNS}(c, r) \longrightarrow (r, cr, p_1, p_2)\text{-LSH} \longrightarrow \text{Boosting Probability}
The Problem Reduction Chain

(r,cr,p1,p2)(r, cr, p_1, p_2)-Locality Sensitive Hashing Family

Now we show how to solve the ANNS(c,r)(c, r) problem with hashing. Designing a perfecting hashing that solves the problem directly is not easy. It is desirable to have some hashing which successes with some probability and then boost its probability systematically. To achieve this, we introduce the idea of (r,cr,p1,p2)(r, cr, p_1, p_2)-locality sensitive hashing family.

Given a set of point VV, a metric d(⋅,⋅)d(\cdot , \cdot) defined on VV, a collection of hash function H={h:V→Z}\mathcal{H} = \{ h: V \rightarrow Z\} is called (r,cr,p1,p2)(r, cr, p_1, p_2) locality sensitive if for any v,u∈Vv, u \in V and an hh sampled uniformly from H\mathcal{H}, it holds that

  1. If d(v,u)<rd(v, u) < r, then Pr⁡h∈H[h(v)=h(u)]≥p1\Pr_{h \in \mathcal{H} } [h(v) = h(u)] \ge p_1.
  2. If d(v,u)≥crd(v, u) \ge cr, then Pr⁡h∈H[h(v)=h(u)]≤p2\Pr_{h \in \mathcal{H} } [h(v) = h(u)] \le p_2

where p2<p1≤1p_2 < p_1 \le 1. Intuitively, pairs near to each other should be more likely to collide. Hence p1=p2ρp_1 = p_2^{\rho} for some ρ=log⁡p1/log⁡p2<1\rho = \log p_1 / \log p_2 < 1.

Ideally, we have p1≈1p_1 \approx 1 and p2≈0p_2 \approx 0. For other cases we can magnify the gap between p1p_1 and p2p_2 and boost p1p_1 to approximate 11 and p2p_2 to approximate 00. The hardness of the boosting highly depends on the value of cc.

Example

Suppose that U={0,1}dU = \{0, 1\}^d, d(u,v)=u⊕v=∣u−v∣1d(u, v) = u \oplus v = |u - v|_1 and H={hi(u)=ui}i∈[d]\mathcal{H} = \{ h_i (u) = u_i \}_{i \in [d]}, where hih_i selects the iith bit of uu. Picking an hh uniformly from H\mathcal{H} and applying hh to uu is equivalent to selecting a bit uniformly from uu. Therefore,

  1. If d(v,u)<rd(v, u) < r (uu and vv has less then rr common bits), then Pr⁡h∈H[h(v)=h(u)]≥d−rd=1−rd=p1\Pr_{h \in \mathcal{H} } [h(v) = h(u)] \ge \frac{d - r}{d} = 1 - \frac{r}{d} = p_1.
  2. If d(v,u)≥crd(v, u) \ge cr, then Pr⁡h∈H[h(v)=h(u)]≤d−crd=1−crd=p2\Pr_{h \in \mathcal{H} } [h(v) = h(u)] \le \frac{d - cr}{d} = 1 - \frac{cr}{d} = p_2

Now p1≈exp⁡(−r/d)p_1 \approx \exp(- r / d) and p2≈exp⁡(−cr/d)p_2 \approx \exp(- cr / d). Hence ρ≈1c\rho \approx \frac{1}{c}. Indeed it can be proven rigorously that

ρ=ln⁡(1−rd)ln⁡(1−crd)≤1c \rho = \frac{\ln (1 - \frac{r}{d}) }{ \ln (1 - \frac{cr}{d}) } \le \frac{1}{c}

as (1−rd)c≥1−crd( 1 - \frac{r}{d})^c \ge 1 - \frac{cr}{d}. There are many ways to prove this. Since we are dealing with probability, we give a probabilistic interpretation of this inequality. Suppose that are cc independent events each happening with probability rd\frac{r}{d}. Then the probability that at least one of them happens is given by

1−Pr⁡[none of them happens ]=1−(1−rd)c 1 - \Pr[\textbf{none of them happens } ] = 1 - (1 - \frac{r}{d})^c

On the other hand, by union bound, this is upper bounded by crd\frac{cr}{d}.

Boosting the Probabilities

We would like the boost the probability such that p1≈1p_1 \approx 1 and p2≈0p_2 \approx 0. We follow a two-step approach. First we sample kk (to be determined) hash functions independently from H\mathcal{H} can concatenate them as a single hash function gg:

g(v)=[h1(v),h2(v),...,hk(v)] g(v) = [h_1(v), h_2(v), ... ,h_k(v)]

Here gg hash a point vv to a kk dimensional vector. After this, g(v)=g(u)g(v) = g(u) happens only if hi(v)=hi(u)h_i(v) = h_i(u) for all i∈[k]i \in [k]. By independence of hih_i's,

  1. If d(v,u)≥crd(v, u) \ge cr, the collision probability of uu with vv drops to p2kp_2^k:

    Pr⁡[g(v)=g(u)]≤p2k \Pr [ g(v) = g(u) ] \le p_2^k
  2. On the other hand, if d(v,u)<rd(v, u) < r, the collision probability also drops to p1k=(p2k)ρp_1^k = (p_2^k)^\rho

    Pr⁡[g(v)=g(u)]≥p1k=p2ρk=(p2k)ρ \Pr [ g(v) = g(u) ] \ge p_1^k = p_2^{\rho k} = (p_2^{k})^\rho

    which is relatively small and not desirable.

We need a second level of boosting to increase the collision probability of similar pairs. Instead of using only one function gg, we use a collection of independent copies:

g1,g2,...,gl g_1, g_2, ..., g_l

where ll is the number to be determined. Now,

  • If d(v,u)<rd(v, u) < r, the probability that at least one of the gi(u)g_i(u) equals to gi(v)g_i(v) is given byPr⁡[∃i∈[l], s.t., gi(u)=gi(v)]=1−(1−p1k)l=1−(1−(p2k)ρ)l≥1−exp⁡(−(p2k)ρl) \begin{aligned} \Pr \left[ \exists i \in [l], \ s.t., \ g_i(u) = g_i(v) \right] &= 1 - (1 - p_1^k)^l \\ &= 1 - (1 - (p_2^k)^\rho)^l \\ &\ge 1 - \exp( - (p_2^k)^\rho l ) \end{aligned}

We can take

  1. p2k=1np_2^k = \frac{1}{n}, i.e., k=log⁡nlog⁡1/p2k = \frac{\log n }{ \log 1 / p_2 }.

  2. exp⁡(−(p2k)ρl)=1n\exp( - (p_2^k)^\rho l ) = \frac{1}{n}, i.e., l=1(p2k)ρln⁡n=nρln⁡nl = \frac{1}{(p_2^k)^\rho } \ln n = n^\rho \ln n.

For a fixed query point qq and for any fixed i∈[l]i \in [l], by linearity of expectation, the expected number of dissimilar collision is given by

E[∣{u∈S:d(q,u)≥cr∧gi(q)=gi(u)}∣]=∑u∈S: d(q,u)≥crPr⁡[gi(v)=gi(u)]≤n⋅1n=1 \begin{aligned} E \left[ |\{ u \in S: d(q, u) \ge cr \wedge g_i(q) = g_i(u) \}| \right] &= \sum_{ u \in S : \ d(q, u) \ge cr } \Pr[g_i(v)= g_i(u)] \\ &\le n \cdot \frac{1}{n} = 1 \end{aligned}

Therefore, there are ll of dissimilar collisions over all i∈[l]i \in [l]. This implies an expected overhead of ll examinations of dissimilar points. However, by Markov inequality, the number of such points is less than 2l2l with probability at least 1/21 / 2. The time for examination of dissimilar point is O(ld)=O(dnρln⁡n)O(ld) = O(d n^\rho \ln n).

Time and Space

Now, given a query point qq, computing gi(q)g_i(q) for a fixed ii takes O(k)O(k) time. Computing ll of them takes O(kl)O(kl) time. In expectation, there are ll dissimilar collision points with qq. Checking one collision point takes O(d)O(d) time. Therefore, the expected query time is given by (note that we stop upon finding the first ANN of qq):

O(kl+dl)=O(ln⁡nln⁡1p2nρln⁡n+dnρln⁡n)=O(nρln⁡2n/ln⁡1p2+dnρln⁡n)=O~(nρ) \begin{aligned} O(kl + dl) &= O(\frac{\ln n}{\ln \frac{1}{p_2}} n^\rho \ln n + d n^\rho \ln n) \\ &= O(n^{ \rho} \ln^2 n / \ln \frac{1}{p_2} + d n^\rho \ln n) \\ &= \tilde{O}( n^\rho ) \end{aligned}

As for the space usage, for each point uu in SS, we need to compute gi(u)g_i(u) and store this value (we need to store this, because gi(u)g_i(u) is self could be a large number and when putting {gi(u):u∈S}\{ g_i(u) : u \in S\} into a hash table, we need to treat gi(u)g_i(u) as the key and store it for later collision comparison. But is it possible that when there is a collision, we re-compute this value again to avoid storing it ?). We need to repeat this for ll hash functions. Therefore, the space usage is given by

O(nkl)=O(n1+ρln⁡2n/ln⁡1p2) O(nkl) = O(n^{1 + \rho} \ln^2 n / \ln \frac{1}{p_2})

Another Boosting Scheme

In last section, we have a scheme that checks O(nρln⁡n)O(n^\rho \ln n) dissimilar points in expectation. In this section we achieve it with high probability.

  1. First, to reduce the collision probability of dis-similar pairs, we concatenate kk functions from H\mathcal{H}. This gives a(r,cr,p1k,p2k) (r, cr, p_1^k, p_2^k) locative sensitive hash function. We determine the value of kk later.
  2. Second, to boost the collision probability of similar pairs, we use ll concatenated hash functions independently. The probability at least one collision occurs is given by1−(1−p1k)l≥1−e−p1k⋅l 1 - (1 - p_1^k)^l \ge 1 - e^{-p_1^k \cdot l} We require this to happen with constant probability 1−1e1 - \frac{1}{e}, hence we need to set l=1p1k=(1p2k)ρl = \frac{1}{p_1^k} = (\frac{1}{p_2^k})^\rho.
  3. Now consider a query point qq. We compute g1(q),g2(q),...,gl(q)g_1(q), g_2(q), ..., g_l(q) and check the points uu's such that gi(u)=gi(q)g_i(u) = g_i(q) for some i∈[l]i \in [l]. Note that we check at most the first 4np2kl+14 n p_2^k l + 1 points we found. Why 4np2kl+14 n p_2^k l + 1? In expectation, there are np2kln p_2^k l dissimilar collisions. By Markov inequality, the probability of dissimilar collisions is no more than 4l4l is at most 1/41 / 4. By union bound,Pr⁡[∃ more than 4l bad collision ∨∄ good collision ]≤1e+14≤12.5+14=516 \begin{aligned} &\Pr[\exists \text{ more than } 4l \text{ bad collision } \vee \nexists \text{ good collision }] \\ &\le \frac{1}{e} + \frac{1}{4} \\ &\le \frac{1}{2.5} + \frac{1}{4} \\ &= \frac{5}{16} \end{aligned}

Therefore, the boosting strategy successes with constant probability. Now consider the running time of such boosting strategy. When a query point qq comes, we need to compute g1(q),g2(q),...,gl(q)g_1(q), g_2(q), ..., g_l(q), which takes time klkl. Further, the strategy checks at most 4np2kl+14 n p_2^k l + 1 points and checking each point takes O(d)O(d) time. The overall time used is

O(kl+(4np2kl+1)d) O(kl + (4 n p_2^k l + 1)d)

To minimize the running time, we need to choose proper value of kk, such that

k=4np2kd→ln⁡k+kln⁡1p2=ln⁡(4nd) k = 4np_2^k d \rightarrow \ln k + k \ln \frac{1}{p_2} = \ln (4nd)

It suffice to take k=ln⁡4ndln⁡1p2k = \frac{\ln 4nd}{ \ln \frac{1}{p_2} }. It follows that

p2k=14ndl=(1p2k)ρ=(4nd)ρ p_2^k = \frac{1}{4nd} \\ l = \left( \frac{1}{p_2^k} \right)^\rho = (4nd)^\rho

and the running time is given by

O((4nd)ρln⁡(4nd)ln⁡1p2) O\left( (4nd)^\rho \frac{\ln (4nd)}{\ln \frac{1}{p_2} } \right)

As n≻dn \succ d, this is equivalent to

O((4nd)ρln⁡nln⁡1p2) O\left( (4nd)^\rho \frac{\ln n}{\ln \frac{1}{p_2} } \right)

We can repeat the above steps by ln⁡n/ln⁡165\ln n / \ln \frac{16}{5} times, to boost the success probability to 1−1n1 - \frac{1}{n}. The overall running time is given by

O((4nd)ρln⁡2nln⁡1p2) O\left( (4nd)^\rho \frac{\ln^2 n}{\ln \frac{1}{p_2} } \right)

Reference

  1. Indyk, P. and Motwani, R., 1998, May. Approximate nearest neighbors: towards removing the curse of dimensionality. In Proceedings of the thirtieth annual ACM symposium on Theory of computing (pp. 604-613).