# geoopt: Riemannian optimization that plugs into torch.optim

> A PyTorch library of manifolds, manifold-aware tensors and optimizers, from an unofficial implementation of the ICLR 2019 paper on Riemannian adaptive methods, still carrying a pre-alpha status on PyPI.

**geoopt/geoopt** — Riemannian Adaptive Optimization Methods with pytorch optim

- Repository: https://github.com/geoopt/geoopt
- Website: https://geoopt.readthedocs.io
- Stars: 1,100 · Forks: 98
- Language: Python
- License: NOASSERTION
- Published: 2026-10-06 · Updated: 2026-10-06 · Language: en
- Canonical page: https://hysenlabs.com/projects/geoopt-geoopt

## What the library is actually for

geoopt describes itself as manifold aware `torch.optim`, and the useful way to read that is: it changes what an optimizer is allowed to assume about the parameters it touches. In ordinary PyTorch training every parameter lives in unconstrained Euclidean space, and gradients point in directions that can be followed. On a manifold the constraint is part of the model: an orthonormal matrix stays orthonormal, a unit-norm vector stays unit norm, and a naive gradient step quietly violates that.

The project states that it is an unofficial implementation for "Riemannian Adaptive Optimization Methods" (ICLR 2019) and more. Unofficial is doing real work in that sentence. It is a community implementation of published methods rather than the original authors' code, which is exactly why the paper and the library are different things to cite.

The metadata is candid about maturity. The `pyproject.toml` classifies the package as `Development Status :: 2 - Pre-Alpha`, and the README says work is in progress but that you can already use it, warning that the API might change in future releases. Both of those are worth reading as descriptions of the current state rather than as boilerplate. The repository is not archived and the last push was on 2026-05-09, so it is maintained, while the newest tagged release is v0.5.1 from 2023-06-23.

## Installing from GitHub is the recommended path

PyTorch 2.0.1 or newer is the floor, and the README is unusually direct about preferring a source install:

```bash
pip install git+https://github.com/geoopt/geoopt.git
```

The PyPI alternative is a single command:

```bash
pip install geoopt
```

The README explains the tradeoff without hedging: GitHub is preferred because development is active, while PyPI might be significantly behind the master branch but is kept as fresh as possible. It also notes that the preferred way to install will change once the project reaches a stable stage. So the version you get depends on which you pick, and the project is telling you to pick the branch.

Dependencies are minimal and are exactly what the geometry needs:

```toml
dependencies = [
    "torch>=2.0.1",
    "numpy",
    "scipy",
]
```

The dev extras are conventional: pytest with coverage and HTML reporting, ruff, twine, wheel, seaborn and sphinx, plus matplotlib for the read-the-docs build. Packaging is flit with a dynamic version, and the project requires Python 3.8 or newer.

One licensing detail to sort out if you plan to use it in a commercial setting: the repository metadata reports no asserted licence while the package classifiers name the Apache Software License and `license` points at the `LICENSE` file in the repository root. The file is the thing to read.

## Manifold tensors carry the constraint with them

Two container types do the central work. `geoopt.ManifoldTensor` is a `torch.Tensor` with an additional `manifold` keyword argument, and `geoopt.ManifoldParameter` is the same idea recognised by `torch.nn.Module.parameters` as correctly subclassed. The second one is the one that matters for real models, because it means an optimizer sees a parameter that knows which space it lives in.

The methods on those containers are where the mathematics becomes concrete. `.proj_()` projects in place onto the manifold. `.proju(u)` projects a vector into the tangent space, which the README stresses you need for all the methods below it. `.egrad2rgrad(u)` converts a Euclidean gradient to a Riemannian one, `.inner(u, v)` takes the inner product of two tangent vectors already assumed to be projected, `.retr(u)` applies a retraction, `.expmap(u)` applies the exponential map, and `.transp(v, u)` transports a vector along a direction.

That list is the real API surface of the library and it tells you what geoopt considers a manifold. `retr_transp` exists alongside the individual operations because a retracting step and a parallel transport usually want to be done in one pass for efficiency.

The optimizers sit on top as thin subclasses: `geoopt.optim.RiemannianSGD` is a subclass of `torch.optim.SGD` with the same API, and `RiemannianAdam` is the Adam equivalent. Keeping the familiar API is deliberate, since it means existing training loops mostly survive the switch.

## The manifold catalogue is broader than the optimizer list

Where a library like this usually has two or three well-supported manifolds, geoopt lists thirteen, and the range is the point. `Euclidean` is the unconstrained control case. `Stiefel` covers matrices satisfying A^t A = I with n greater than or equal to p, which is what orthogonal projection methods produce. `Sphere` is the unit-norm constraint. `BirkhoffPolytope` handles doubly stochastic matrices, the permutation-matrix neighbourhood used in assignment problems.

The hyperbolic family is where the associated literature shows. `PoincareBall` and `Lorentz` implement two models of the same geometry, the disk model and the hyperboloid model, and picking between them is partly about numerical stability rather than taste. `Stereographic` and `SphereProjection` cover constant curvature stereographic projection models, and `UpperHalf` is the Siegel upper half manifold supporting both Riemannian and Finsler metrics. `BoundedDomain` is the Siegel bounded domain with the same dual metric support.

Two entries compose others rather than describing a space. `ProductManifold` builds products, and `Scaled` scales a manifold, with the README pointing at work on mixed-curvature product representations as the motivating case. `SymmetricPositiveDefinite` covers the SPD manifold, which is where Riemannian optimization most often shows up in practice because of its use in diffusion and covariance modelling.

The `UpperHalf` and `BoundedDomain` entries cite a specific paper on symmetric spaces and Finsler-Riemannian graph embeddings, which is a good signal: the less common manifolds are there because someone needed them for a paper, not because someone enumerated every constant curvature space.

## Samplers and experimental layers round out the library

Beyond optimization there is a samplers module, which is the reason to reach for this library if you are doing probabilistic work on curved spaces rather than point estimation. `geoopt.samplers.RSGLD` is Riemannian Stochastic Gradient Langevin Dynamics, `RHMC` is Riemannian Hamiltonian Monte-Carlo, and `SGRHMC` is the stochastic gradient variant of the same. All three are the manifold-aware versions of techniques that are well established in the flat case, which is a convenient way to think about the whole library.

There is also a layers module, and the README labels it experimental. It exists to embed geoopt into deep learning models, which is the natural request from anyone who has used a manifold optimizer and then discovered they had to write the projection logic themselves in every layer.

The examples directory shows the intended uses rather than toy demonstrations. `examples/lorentz.ipynb` and `examples/hyperbolic_multiclass_classification.ipynb` point at hyperbolic embeddings, `examples/mobius_linear_example.py` shows a linear layer on a Möbius space, and `examples/visualizing_entailment_cones.ipynb` is about the cone geometry of entailment relations. That last one is a good example of the library being used for structure in the representation itself rather than for a constraint on weights.

For citation the README asks for a BibTeX entry with a paper title of Geoopt: Riemannian Optimization in PyTorch by Kochurov, Karimov and Kozlukov, with arXiv identifier 2005.02819.

## Continuous integration details reveal how the project is maintained

The repository ships a Makefile, a Nix file, a Gitpod configuration and a GitHub Actions workflow, and the details are informative. The test target runs doctests as part of the suite:

```bash
pytest -v geoopt tests --doctest-modules --html=testing-report.html --self-contained-html
```

Running doctests on the package means the examples in docstrings are expected to keep working, which is a reasonable proxy for a library whose value is that its methods do what their names say.

The lint target is ruff with a line length of 100, and the Sphinx build runs with warnings promoted to errors, so a documentation warning fails the build rather than scrolling past. Pytest is configured with `filterwarnings = ["error", ...]` for everything except `UserWarning` and `RuntimeWarning`, meaning warnings in the library itself are treated as failures. That is a strict setting for a package that calls into PyTorch internals.

The release history is small and tells a coherent story: v0.5.1 in 2023 moved to `pyproject.toml`, dropped the dev requirements file, added read-the-docs configuration and PyTorch 2.0 support. v0.5.0 added a StereographicProductManifold update, and v0.4.1 added tests for PyTorch 1.10 and fixed deepcopy and copy behaviour. Commits after that release are where the current PyTorch support lives, which is the practical reason to install from the branch.

## Conclusion

geoopt is a research library that takes the manifold constraint seriously rather than approximating it, and the method names on it map directly onto the papers people want to reproduce: Riemannian Adam and Riemannian SGD for optimization, Langevin and Hamiltonian samplers for sampling on curved spaces, and a manifold list that covers Stiefel, sphere, hyperbolic and SPD settings. What you accept to get it is an API the README warns may still change, a PyPI release from 2023 against a PyTorch requirement that has moved on, and a pre-alpha classifier in the package metadata. Read the manifolds documentation first, since the tangent space methods decide whether a given model is even expressible, then pin a commit from the master branch rather than trusting the PyPI version.

## FAQ

### What is geoopt used for in PyTorch?

It makes optimization and sampling aware of manifold constraints, so parameters that must stay on a manifold such as an orthonormal Stiefel matrix or a unit-norm sphere vector stay there. It provides manifold-aware tensors and parameters, Riemannian optimizers such as RiemannianSGD and RiemannianAdam, and Riemannian samplers including RSGLD, RHMC and SGRHMC.

### How do I install geoopt, and which version should I use?

The README prefers installing from GitHub with `pip install git+https://github.com/geoopt/geoopt.git`, because PyPI may lag behind the master branch while development is active. You need PyTorch 2.0.1 or newer plus numpy and scipy. The newest tagged release is v0.5.1 from 2023-06-23, so the branch is the more current option.

### Which manifolds does geoopt support?

Thirteen, including Euclidean, Stiefel, Sphere, BirkhoffPolytope, Stereographic, SphereProjection, PoincareBall, Lorentz, ProductManifold, Scaled, SymmetricPositiveDefinite, UpperHalf and BoundedDomain. The UpperHalf and BoundedDomain manifolds support both Riemannian and Finsler metrics, following the work on symmetric spaces for graph embeddings.

### Is geoopt stable enough for production use?

The package metadata classifies it as Pre-Alpha and the README says the API might change in future releases. The repository is not archived and was pushed on 2026-05-09, so it is still maintained, but the newest release is from 2023. Treat it as a research library and pin a specific commit.

### What are the key tangent space methods on a geoopt manifold tensor?

`.proj_()` projects in place, `.proju(u)` projects a vector into the tangent space, `.egrad2rgrad(u)` converts a Euclidean gradient to a Riemannian one, `.retr(u)` applies a retraction and `.expmap(u)` applies the exponential map. `.transp(v, u)` transports a vector along a direction, and `.inner(u, v)` takes an inner product of two tangent vectors.

## Sources

- [geoopt/geoopt on GitHub](https://github.com/geoopt/geoopt)
- [Issues](https://github.com/geoopt/geoopt/issues)
- [Project website](https://geoopt.readthedocs.io)
- [README](https://github.com/geoopt/geoopt/blob/master/README.md)
- [Releases](https://github.com/geoopt/geoopt/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/geoopt-geoopt
