Current section
Files
Jump to
Current section
Files
lib/tsne.ex
defmodule Tsne do
@moduledoc """
t-distributed stochastic neighbor embedding (t-SNE) is a statistical method for
visualizing high-dimensional data in two or three dimensions.
This library provides bindings to fast exact and
[Barnes-Hut](http://lvdmaaten.github.io/publications/papers/JMLR_2014.pdf)
implementations of t-SNE in Rust using the
[`bhtsne`](https://github.com/lvdmaaten/bhtsne) crate.
"""
alias Tsne.Native
@tsne_options [
embedding_dimensions: [type: :integer, default: 2, doc: "Dimension of the embedded space."],
learning_rate: [
type: :float,
default: 200.0,
doc:
"The learning rate for t-SNE is usually in the range [10.0, 1000.0]. If the learning rate is too high, the data may look like a ‘ball’ with any point approximately equidistant from its nearest neighbours. If the learning rate is too low, most points may look compressed in a dense cloud with few outliers. If the cost function gets stuck in a bad local minimum increasing the learning rate may help."
],
epochs: [
type: :integer,
default: 1000,
doc: "Maximum number of iterations for the optimization. Should be at least 250."
],
perplexity: [
type: :float,
default: 30.0,
doc:
"The perplexity is related to the number of nearest neighbors that is used in other manifold learning algorithms. Larger datasets usually require a larger perplexity. Consider selecting a value between 5 and 50. Different values can result in significantly different results. The perplexity must be less than the number of samples."
],
final_momentum: [
type: :float,
default: 0.8,
doc:
"The value for momentum after the initial early exaggeration phase. See`momentum` for more info."
],
momentum: [
type: :float,
default: 0.5,
doc:
"Gradient descent with momentum keeps a sum exponentially decaying weights from previous iterations, speeding up convergence. In early stages of the optimization, this is typically set to a lower value (0.5 in most implementations) since points generally move around quite a bit in this phase and increased after the initial early exaggeration phase (typically to 0.8, see: `final_momentum`) to speed up convergence."
],
metric: [
type: {:in, [:euclidean, :cosine]},
default: :euclidean,
doc: "The distance metric to use. Must be either `:euclidean` or `:cosine`."
]
]
@barnes_hut_options @tsne_options
|> Keyword.merge(
theta: [
type: :float,
default: 0.5,
doc: "The tradeoff parameter between accuracy (0) and speed (1)."
]
)
|> NimbleOptions.new!()
@doc """
Barnes Hut t-SNE.
[Barnes-Hut](http://lvdmaaten.github.io/publications/papers/JMLR_2014.pdf) is a
tree-based algorithm for accelerating t-SNE. It runs in O(NlogN) time (while exact
runs in O(N^2)) time.
## Options
#{NimbleOptions.docs(@barnes_hut_options)}
"""
def barnes_hut(data, opts \\ []) do
opts = NimbleOptions.validate!(opts, @barnes_hut_options)
original_dimensions = data |> List.first() |> length()
data = List.flatten(data)
Native.barnes_hut(
data,
original_dimensions,
opts[:embedding_dimensions],
opts[:learning_rate],
opts[:epochs],
opts[:perplexity],
opts[:theta],
opts[:final_momentum],
opts[:momentum],
opts[:metric]
)
end
@exact_options NimbleOptions.new!(@tsne_options)
@doc """
Exact t-SNE.
## Options
#{NimbleOptions.docs(@barnes_hut_options)}
"""
def exact(data, opts \\ []) do
opts = NimbleOptions.validate!(opts, @exact_options)
original_dimensions = data |> List.first() |> length()
data = List.flatten(data)
Native.exact(
data,
original_dimensions,
opts[:embedding_dimensions],
opts[:learning_rate],
opts[:epochs],
opts[:perplexity],
opts[:final_momentum],
opts[:momentum],
opts[:metric]
)
end
end