• Stars
    star
    175
  • Rank 218,059 (Top 5 %)
  • Language
    Scala
  • License
    MIT License
  • Created over 9 years ago
  • Updated over 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Approximate Nearest Neighbors in Spark

Cosine LSH Join Spark

A spark library for approximate nearest neighbours (ANN).

Background

In many computational problems such as NLP, Recommendation Systems and Search, items (e.g. words) are represented as vectors in a multidimensional space. Then given a specific item it's nearest neighbours need to be find e.g. given a query find the most similar ones. A naive liner scan over the data set might be too slow for most data sets.

Hence, more efficient algorithms are needed. One of the most widely used approaches is Locality Sensitive Hashing (LSH). This family of algorithms are very fast but might not give the exact solution and are hence called approximate nearest neighbours (ANN). The trade off between accuracy and speed is generally set via parameters of the algorithm.

Joiner Interface

This is an interface to find the k nearest neighbors from a data set for every other object in the same data set. Implementations may be either exact or approximate.

trait Joiner {
    def join(matrix: IndexedRowMatrix): CoordinateMatrix
}

matrix is a row oriented matrix. Each row in the matrix represents an item in the dataset. Items are identified by their matrix index. Returns a similarity matrix with MatrixEntry(itemA, itemB, similarity).

Example

// item_a --> (1.0, 1.0, 1.0)
// item_b --> (2.0, 2.0, 2.0)
// item_c --> (6.0, 3.0, 2.0)

val rows = Seq(
  IndexedRow(1, Vectors.dense(1.0, 1.0, 1.0)),
  IndexedRow(2, Vectors.dense(2.0, 2.0, 2.0)),
  IndexedRow(5, Vectors.dense(6.0, 3.0, 2.0))
)
val matrix = new IndexedRowMatrix(sc.parallelize(rows))
val similariyMatrix = joiner.join(matrix)

val results = similariyMatrix.entries.map {
      entry =>
        "item:%d item:%d cosine:%.2f".format(entry.i, entry.j, entry.value)
    }

results.foreach(println)

// above will print:
// item:2 item:3 cosine:0,87
// item:1 item:3 cosine:0,87
// item:1 item:2 cosine:1,00

Please see included Main.scala file for a more detailed example.

Implementations of the joiner interface

LSH

This is an implementation of the following paper for Spark:

Randomized Algorithms and NLP: Using Locality Sensitive Hash Function for High Speed Noun Clustering

-- Ravichandran et al.

The algorithm determines a set of candidate items in the first stage and only computes the exact cosine similarity for those candidates. It has been succesfully used in production with typical run times of a couple of minutes for millions of items.

Note that candidates are ranked by their exact cosine similarity. Hence, this algorithm will not return any false positives (items that the system thinks are nearby but are actually not). Most real world applications require this e.g. in recommendation systems it is ok to return similar items which are almost as good as the exact nearest neighbours but showing false positives would result in senseless recommendations.

val lsh = new Lsh(
  minCosineSimilarity = 0.5,
  dimensions = 2,
  numNeighbours = 3,
  numPermutations = 1,
  partitions = 1,
  storageLevel = StorageLevel.MEMORY_ONLY
)

Please see the original publication for a detailed description of the parameters.

NearestNeighbours

Brute force method to compute exact nearest neighbours. As this is a very expensive computation O(n^2) an additional sample parameter may be passed such that neighbours are just computed for a random fraction. This interface may be used to tune parameters for approximate solutions on a small subset of data.

QueryJoiner Interface

An interface to find the nearest neighbours in a catalog matrix for each entry in a query matrix. Implementations may be either exact or approximate.

trait QueryJoiner {
  def join(queryMatrix: IndexedRowMatrix, catalogMatrix: IndexedRowMatrix): CoordinateMatrix
}

Implementations of the QueryJoiner Interface

QueryLsh

Standard Lsh implementation. A query matrix is hashed multiple times and exact hash matches are searched for in a catalog Matrix. These candidates are used to compute the exact cosine distance.

QueryHamming

Implementation based on approximated cosine distances. The cosine distances are approximated using hamming distances which are way faster to compute. The catalog matrix is broadcasted. This implementation is therefore suited for tasks where the catalog matrix is very small compared to the query matrix.

QueryNearestNeighbours

Brute force O(size(query) * size(catalog)) method to compute exact nearest neighbours for rows in the query matrix. As this is a very expensive computation additional sample parameters may be passed such that neighbours are just computed for a random fraction of the data set. This interface may be used to tune parameters for approximate solutions on a small subset of data.

Maven

The artifacts are hosted on Maven Central. For Spark 1.x add the following line to your build.sbt file:

libraryDependencies += "com.soundcloud" % "cosine-lsh-join-spark_2.10" % "0.0.5"

For Spark 2.x use:

libraryDependencies += "com.soundcloud" % "cosine-lsh-join-spark_2.10" % "1.0.1"

or if you're on scala 2.11.x use:

libraryDependencies += "com.soundcloud" % "cosine-lsh-join-spark_2.11" % "1.0.1"

Releasing (maintainers only)

In order to release the library using the release plugin sbt release, you need to set up the following:

Contributors

Γ–zgΓΌr Demir

Rany Keddo

Alexey Rodriguez Yakushev

Aaron Levin

More Repositories

1

roshi

Roshi is a large-scale CRDT set implementation for timestamped events.
Go
3,107
star
2

lhm

Online MySQL schema migrations
Ruby
1,808
star
3

lightcycle

LightCycle lets self-contained classes respond to Android’s lifecycle events
Java
706
star
4

soundcloud-custom-player

The SoundCloud custom javascript based player
JavaScript
699
star
5

chunk-manifest-webpack-plugin

Allows exporting a manifest that maps entry chunk names to their output files, instead of keeping the mapping inside the webpack bootstrap.
JavaScript
393
star
6

soundcloud-javascript

Official SoundCloud Javascript SDK
JavaScript
382
star
7

areweplayingyet

html5 audio benchmarks
JavaScript
312
star
8

Axt

SwiftUI view testing library
Swift
163
star
9

Widget-JS-API

This is the official SoundCloud Widget Javascript API
JavaScript
149
star
10

delect

The Gradle Plugin for Dagger Reflect.
Kotlin
137
star
11

api

A public repo for our Developer Community to engage about bugs and feature requests on our Public API
136
star
12

periskop

Exception Monitoring Service
Go
123
star
13

project-dev-kpis

Key Performance Indicators of product development teams.
Python
119
star
14

soundcloud-python

A Python wrapper around the Soundcloud API
Python
95
star
15

split-by-name-webpack-plugin

Split a Webpack entry bundle into any number of arbitrarily defined smaller bundles
JavaScript
80
star
16

spark-pagerank

PageRank in Spark
Scala
74
star
17

intervene

A machine-in-the-middle proxy for development, enabling mocking and/or modification of API endpoints
JavaScript
71
star
18

normailize

Normalize emails like [email protected] into [email protected]
Ruby
67
star
19

SoundCloud-API-jQuery-plugin

SoundCloud API jQuery plugin
JavaScript
52
star
20

spdt

Streaming Parallel Decision Tree
Scala
51
star
21

twinagle

Twinagle = Twirp + Finagle
Scala
50
star
22

prometheus-clj

Clojure wrappers for the Prometheus java client
Clojure
49
star
23

simple_circuit_breaker

Simple Ruby implementation of the Circuit Breaker design pattern
Ruby
28
star
24

git-sha-webpack-plugin

Tag your webpack bundles with a Git SHA linked to the latest commit on that bundle
JavaScript
27
star
25

remixin

Mixin library for Javascript
JavaScript
24
star
26

cando

A simple access rights gem with users, roles and capabilities
Ruby
22
star
27

move-to-parent-merging-webpack-plugin

JavaScript
19
star
28

MinimalPerfectHashes.jl

An implementation of minimal perfect hash function generation as described in Czech et. al. 1992.
Julia
16
star
29

ogg

Mirror of http://svn.xiph.org/trunk/ogg/
C
11
star
30

sc-gaws

Glue code to wrap around AWS and do useful things in Go
Go
9
star
31

vorbis

Mirror of http://svn.xiph.org/trunk/vorbis/
C
8
star
32

collins_exporter

Simple Collins exporter for Prometheus
Go
8
star
33

dns-endpoint-pool

Manage and load-balance a pool of service endpoints retrieved from a DNS lookup for a service discovery name.
JavaScript
7
star
34

tremor

Mirror of http://svn.xiph.org/trunk/Tremor
C
5
star
35

soundcloud-ruby

Official SoundCloud API Wrapper for Ruby.
Ruby
5
star
36

periskop-scala

Scala low level client for Periskop
Scala
3
star
37

knife-scrub

Knife plugin to scrub normal attributes
Ruby
1
star
38

go-runit

go library wrapping runit service status
Go
1
star