Linear problems (advanced)#
This example shows an advanced linear problems usage like TemporalProblem
, and the SinkhornProblem
.
See also
See Linear problems for an introduction on how to solve linear problems.
See Quadratic problems for an introduction on how to quadratic problems.
See Quadratic problems (advanced) for an advanced example on how to solve quadratic problems.
Imports and data loading#
from moscot import datasets
from moscot.problems.generic import SinkhornProblem
Simulate data using simulate_data()
.
adata = datasets.simulate_data(n_distributions=2, key="day")
adata
AnnData object with n_obs × n_vars = 40 × 60
obs: 'day', 'celltype'
Threshold#
The threshold
parameter defines the convergence criterion. In the balanced setting the threshold
denotes the deviation between prior and posterior marginals, while in the unbalanced setting the threshold
corresponds to a Cauchy sequence stopping criterion.
Initializer#
Different initializers can help to improve convergence. For the full-rank case we can set the initializer to the trivial initalizing method denoted by default
. The gaussian
initializer [Thornton and Cuturi, 2022] computes Gaussian approximations of two point clouds and leverages the closed-form solution of optimal transport problems between Gaussians, while the sorting
initializer [Thornton and Cuturi, 2022] solves a simplified (sorting) optimal transport problem and uses its solution as initializer. For low-rank problems, different initializers are available: random
, rank2
, k-means
or generalized-k-means
[Scetbon and Cuturi, 2022].
Some initializers can have additional arguments that can be provided as a dictionary, e.g., min_iterations
and max_iterations
can be provided for the k_means()
algorithm used by
the k-means
initializer.
For more information, see ott.initializers.linear
.
sp = SinkhornProblem(adata)
sp = sp.prepare(key="day")
ik = {"min_iterations": 5, "max_iterations": 200}
sp = sp.solve(epsilon=0, rank=3, initializer="k-means", initializer_kwargs=ik)
INFO Computing pca with `n_comps=30` for `xy` using `adata.X`
INFO Solving problem OTProblem[stage='prepared', shape=(20, 20)].
Number of iterations#
There are three types of iterations, which can be set. min_iterations
is the
minimum number of iterations of the algorithm. max_iterations
is the
maximum number of iterations. If the convergence criterion is not met
after completing max_iterations
, the model has not converged. inner_iterations
is the number of iterations after which the model checks the convergence criterion.
If max_iterations
is too low, the model won’t converge:
sp = sp.solve(epsilon=1e-3, inner_iterations=1, min_iterations=0, max_iterations=2)
INFO Solving problem OTProblem[stage='solved', shape=(20, 20)].
WARNING Solver did not converge
Low-rank hyperparameters#
The low-rank algorithm requires more hyperparameters, i.e., gamma
, the
a step size of the mirror descent algorithm and gamma_rescale
, a flag
indicating whether to rescale gamma
at every iteration. When tuning gamma
,
we recommend trying orders of \(10\). If gamma
is too small or too large, the algorithm might not converge.
sp = sp.solve(epsilon=0, rank=3, initializer="random", max_iterations=30, gamma=1000)
INFO Solving problem OTProblem[stage='solved', shape=(20, 20)].
WARNING Solver did not converge
sp = sp.solve(epsilon=0, rank=3, initializer="random", max_iterations=30, gamma=10)
INFO Solving problem OTProblem[stage='solved', shape=(20, 20)].
Keyword arguments and implementation details#
Whenever the solve()
method of a linear problem is called,
a backend-specific linear solver is instantiated. Currently, ott
is
the only supported, its corresponding linear solvers are Sinkhorn
,
which is used whenever rank = -1
, and LRSinkhorn
,
its counterpart whenever rank
is a positive integer. moscot
wraps these
classes in SinkhornSolver
which handles both full and
low-rank solvers.