event2vector 0.4.0__tar.gz → 0.4.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. {event2vector-0.4.0 → event2vector-0.4.1}/CHANGELOG.md +23 -0
  2. {event2vector-0.4.0 → event2vector-0.4.1}/CITATION.cff +13 -6
  3. event2vector-0.4.1/PKG-INFO +349 -0
  4. event2vector-0.4.1/README.md +314 -0
  5. {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/__init__.py +1 -1
  6. event2vector-0.4.1/event2vector.egg-info/PKG-INFO +349 -0
  7. {event2vector-0.4.0 → event2vector-0.4.1}/pyproject.toml +1 -1
  8. event2vector-0.4.0/PKG-INFO +0 -262
  9. event2vector-0.4.0/README.md +0 -227
  10. event2vector-0.4.0/event2vector.egg-info/PKG-INFO +0 -262
  11. {event2vector-0.4.0 → event2vector-0.4.1}/MANIFEST.in +0 -0
  12. {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/baselines.py +0 -0
  13. {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/data.py +0 -0
  14. {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/datasets/__init__.py +0 -0
  15. {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/datasets/arithmetic.py +0 -0
  16. {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/datasets/brown.py +0 -0
  17. {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/datasets/decay.py +0 -0
  18. {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/datasets/groups.py +0 -0
  19. {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/datasets/lifepath.py +0 -0
  20. {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/datasets/realdata.py +0 -0
  21. {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/eval/__init__.py +0 -0
  22. {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/eval/figures.py +0 -0
  23. {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/eval/harness.py +0 -0
  24. {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/geometries.py +0 -0
  25. {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/metrics.py +0 -0
  26. {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/models.py +0 -0
  27. {event2vector-0.4.0 → event2vector-0.4.1}/event2vector.egg-info/SOURCES.txt +0 -0
  28. {event2vector-0.4.0 → event2vector-0.4.1}/event2vector.egg-info/dependency_links.txt +0 -0
  29. {event2vector-0.4.0 → event2vector-0.4.1}/event2vector.egg-info/requires.txt +0 -0
  30. {event2vector-0.4.0 → event2vector-0.4.1}/event2vector.egg-info/top_level.txt +0 -0
  31. {event2vector-0.4.0 → event2vector-0.4.1}/setup.cfg +0 -0
  32. {event2vector-0.4.0 → event2vector-0.4.1}/tests/test_affine.py +0 -0
  33. {event2vector-0.4.0 → event2vector-0.4.1}/tests/test_device.py +0 -0
@@ -4,6 +4,28 @@ All notable changes to `event2vector` are documented here. The format follows
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project uses
5
5
  [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.4.1] - 2026-10-15
8
+
9
+ Documentation and metadata only; the code is unchanged from 0.4.0.
10
+
11
+ ### Changed
12
+
13
+ - The paper is published in the Proceedings of Machine Learning Research
14
+ (vol. 282): the README citation, the "Paper" link and `CITATION.cff` (GitHub's
15
+ "Cite this repository" and Zenodo) now point to
16
+ [PMLR](https://proceedings.mlr.press/v282/sulc26a.html); arXiv is kept as the
17
+ preprint.
18
+ - Rewritten README: quickstart, how training works, the geometries with a figure
19
+ of the same events composed by each geometry, a parameter and method
20
+ reference, devices, datasets, examples, citation, and the event2vec logo.
21
+ - The Brown corpus example's extra requirements are documented
22
+ (`pip install "event2vector[viz,manifold,nlp]" nltk`).
23
+
24
+ ### Added
25
+
26
+ - `images/make_readme_figures.py`, which redraws the README's logo and geometry
27
+ figure from the library's own model classes.
28
+
7
29
  ## [0.4.0] - 2026-10-15
8
30
 
9
31
  ### Added
@@ -59,6 +81,7 @@ All notable changes to `event2vector` are documented here. The format follows
59
81
 
60
82
  Earlier releases are listed on [PyPI](https://pypi.org/project/event2vector/#history).
61
83
 
84
+ [0.4.1]: https://pypi.org/project/event2vector/0.4.1/
62
85
  [0.4.0]: https://pypi.org/project/event2vector/0.4.0/
63
86
  [0.3.1]: https://pypi.org/project/event2vector/0.3.1/
64
87
  [0.3.0]: https://pypi.org/project/event2vector/0.3.0/
@@ -1,11 +1,12 @@
1
1
  cff-version: 1.2.0
2
- message: "If you use event2vector, please cite the paper below."
2
+ message: "If you use event2vector, please cite the paper below (PMLR vol. 282)."
3
3
  title: "event2vector: geometric embeddings for event sequences"
4
4
  type: software
5
5
  authors:
6
6
  - family-names: Sulc
7
7
  given-names: Antonin
8
- version: 0.4.0
8
+ version: 0.4.1
9
+ doi: 10.5281/zenodo.23399003
9
10
  date-released: 2026-10-15
10
11
  license: MIT
11
12
  repository-code: "https://github.com/sulcantonin/event2vec_public"
@@ -16,11 +17,17 @@ keywords:
16
17
  - representation-learning
17
18
  - geometric deep learning
18
19
  preferred-citation:
19
- type: article
20
+ type: conference-paper
20
21
  title: "Event2Vec: A Geometric Approach to Learning Composable Representations of Event Sequences"
21
22
  authors:
22
23
  - family-names: Sulc
23
24
  given-names: Antonin
24
- journal: "arXiv preprint arXiv:2509.12188"
25
- year: 2025
26
- url: "https://arxiv.org/abs/2509.12188"
25
+ collection-title: "Proceedings of the 4th (2025) and 3rd (2024) NeurIPS Workshops on Symmetry and Geometry in Neural Representations"
26
+ collection-type: proceedings
27
+ volume: 282
28
+ start: 492
29
+ end: 512
30
+ year: 2026
31
+ publisher:
32
+ name: PMLR
33
+ url: "https://proceedings.mlr.press/v282/sulc26a.html"
@@ -0,0 +1,349 @@
1
+ Metadata-Version: 2.4
2
+ Name: event2vector
3
+ Version: 0.4.1
4
+ Summary: Scikit-learn-style geometric embeddings for event sequences.
5
+ Author: Antonin Sulc
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/sulcantonin/event2vec_public
8
+ Project-URL: Repository, https://github.com/sulcantonin/event2vec_public
9
+ Project-URL: Issues, https://github.com/sulcantonin/event2vec_public/issues
10
+ Project-URL: Changelog, https://github.com/sulcantonin/event2vec_public/blob/main/CHANGELOG.md
11
+ Keywords: sequence-embedding,event-sequences,representation-learning,word2vec,scikit-learn,time-series
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
15
+ Classifier: Intended Audience :: Science/Research
16
+ Requires-Python: >=3.9
17
+ Description-Content-Type: text/markdown
18
+ Requires-Dist: numpy>=1.21
19
+ Requires-Dist: torch>=1.13
20
+ Requires-Dist: scikit-learn>=1.0
21
+ Requires-Dist: tqdm>=4.0
22
+ Provides-Extra: viz
23
+ Requires-Dist: matplotlib; extra == "viz"
24
+ Requires-Dist: seaborn; extra == "viz"
25
+ Provides-Extra: manifold
26
+ Requires-Dist: openTSNE; extra == "manifold"
27
+ Provides-Extra: nlp
28
+ Requires-Dist: gensim; extra == "nlp"
29
+ Provides-Extra: hyperbolic
30
+ Requires-Dist: geoopt>=0.5; extra == "hyperbolic"
31
+ Provides-Extra: dev
32
+ Requires-Dist: pytest; extra == "dev"
33
+ Requires-Dist: black; extra == "dev"
34
+ Requires-Dist: ruff; extra == "dev"
35
+
36
+ <div align="center">
37
+
38
+ <a href="https://event2vec.com">
39
+ <picture>
40
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/sulcantonin/event2vec_public/main/images/logo-dark.svg">
41
+ <img alt="event2vec" src="https://raw.githubusercontent.com/sulcantonin/event2vec_public/main/images/logo-light.svg" width="300">
42
+ </picture>
43
+ </a>
44
+
45
+ **Interpretable, composable embeddings for sequences of discrete events.**
46
+
47
+ [![PyPI version](https://badge.fury.io/py/event2vector.svg)](https://badge.fury.io/py/event2vector)
48
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.23399003.svg)](https://doi.org/10.5281/zenodo.23399003)
49
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
50
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
51
+ [![PMLR](https://img.shields.io/badge/PMLR-vol.%20282-1f4e79.svg)](https://proceedings.mlr.press/v282/sulc26a.html)
52
+ [![arXiv](https://img.shields.io/badge/arXiv-2509.12188-b31b1b.svg)](https://arxiv.org/abs/2509.12188)
53
+
54
+ **[event2vec.com](https://event2vec.com)** · [Paper](https://proceedings.mlr.press/v282/sulc26a.html) · [Changelog](https://github.com/sulcantonin/event2vec_public/blob/main/CHANGELOG.md) · [Issues](https://github.com/sulcantonin/event2vec_public/issues)
55
+
56
+ ![Event2Vector teaser](https://raw.githubusercontent.com/sulcantonin/event2vec_public/main/images/teaser.png)
57
+
58
+ </div>
59
+
60
+ ## What it is
61
+
62
+ Event2Vector learns one vector per event type and represents a whole sequence as
63
+ the **composition of its events**. In the default Euclidean geometry that
64
+ composition is a plain sum, so a sequence's embedding is *exactly* the sum of its
65
+ events' vectors. This makes the representation interpretable by construction:
66
+
67
+ - **Decomposition**: every coordinate of a sequence is attributable to the events in it.
68
+ - **Composition**: sub-sequences combine by vector arithmetic.
69
+ - **Counterfactuals**: removing an event from a sequence is one subtraction.
70
+
71
+ Other geometries (hyperbolic, spherical, rotation, Heisenberg, affine, product)
72
+ keep this compositional structure while capturing hierarchy, cycles or order. All
73
+ of them sit behind one scikit-learn-style estimator.
74
+
75
+ ## Installation
76
+
77
+ ```bash
78
+ pip install event2vector
79
+ ```
80
+
81
+ From source:
82
+
83
+ ```bash
84
+ git clone https://github.com/sulcantonin/event2vec_public.git
85
+ cd event2vec_public
86
+ pip install .
87
+ ```
88
+
89
+ Requires Python 3.9+ and PyTorch 1.13+.
90
+
91
+ ## Quickstart
92
+
93
+ Sequences are lists of integer event ids (`0 … num_event_types - 1`) and can have
94
+ different lengths.
95
+
96
+ ```python
97
+ import numpy as np
98
+ from event2vector import Event2Vec
99
+
100
+ vocab = ["start", "login", "search", "buy", "logout"]
101
+ sequences = [[0, 1, 2, 3, 4], [0, 1, 2, 2, 4], [0, 2, 3, 4], [0, 1, 4]] * 50
102
+
103
+ model = Event2Vec(
104
+ num_event_types=len(vocab),
105
+ embedding_dim=8,
106
+ geometry="euclidean",
107
+ pad_sequences=True, # vectorized batches of variable-length sequences
108
+ num_epochs=20,
109
+ random_state=0,
110
+ )
111
+ model.fit(sequences)
112
+
113
+ embeddings = model.transform(sequences) # (n_sequences, 8)
114
+
115
+ # A sequence is exactly the sum of its event vectors:
116
+ event_vectors = model.model.embedding.weight.detach().cpu().numpy()
117
+ assert np.allclose(embeddings[0], event_vectors[sequences[0]].sum(axis=0), atol=1e-5)
118
+
119
+ # gensim-style nearest events to an event or a whole sequence
120
+ print(model.most_similar(positive=3, topn=2)) # [(event_id, similarity), ...]
121
+ print(model.most_similar(positive=[[0, 1, 2]], topn=2))
122
+ ```
123
+
124
+ ## How it works
125
+
126
+ A sequence is read one event at a time. The state starts at the identity and each
127
+ event updates it, `h_t = h_{t-1} ⊕ e_t`, where `⊕` is the geometry's composition
128
+ (vector addition in the Euclidean case). Training minimizes three terms at every
129
+ step:
130
+
131
+ | term | weight | what it enforces |
132
+ |---|---|---|
133
+ | next-event prediction | 1 | a linear decoder predicts event `t+1` from `h_t` (cross-entropy) |
134
+ | reconstruction | `lambda_reconstruction` | the step `e_t` can be recovered from `h_{t-1}` and `h_t`, so the update stays invertible |
135
+ | consistency | `lambda_consistency` | two dropout passes over the same step agree |
136
+
137
+ There is no attention and no hidden nonlinearity in the state update, which is
138
+ what keeps every embedding a readable composition of its events. See the
139
+ [paper](https://proceedings.mlr.press/v282/sulc26a.html) for details.
140
+
141
+ ## Geometries
142
+
143
+ Choose the composition with `geometry=`. Every geometry uses the same estimator
144
+ and a generic left-cancellation reconstruction loss.
145
+
146
+ | `geometry` | update | best for |
147
+ |---|---|---|
148
+ | `euclidean` | vector addition | order-invariant bag of events, exact decomposition |
149
+ | `hyperbolic` | Möbius addition (curvature `curvature > 0`) | hierarchical, tree-like structure |
150
+ | `stereographic` | κ-gyroaddition (signed `kappa`) | one curvature dial: `kappa < 0` hyperbolic, `0` Euclidean, `> 0` spherical |
151
+ | `spherical` | κ-gyroaddition (`kappa > 0`) | cyclic / periodic structure |
152
+ | `rotation` | left `SO(n)` product | non-commutative orientation (order matters) |
153
+ | `heisenberg` | Heisenberg group product | order-dependent signed (Lévy) area |
154
+ | `affine` | `x ↦ exp(M_e) x + v_e` on the left | events that act on the history (shrink, stretch, rotate it), not only add to it |
155
+ | `product` | per-factor update | two structure types at once, e.g. hyperbolic × spherical |
156
+
157
+ ![The same three events composed by each geometry](https://raw.githubusercontent.com/sulcantonin/event2vec_public/main/images/geometries.png)
158
+
159
+ *The same three events composed by each geometry, in order a·b·c (blue) and c·b·a
160
+ (red). The Euclidean sum ends in the same place either way; where the endpoints
161
+ separate, the geometry remembers order. Drawn by the library's own model classes
162
+ with `python images/make_readme_figures.py`.*
163
+
164
+ ```python
165
+ Event2Vec(num_event_types=len(vocab), geometry="hyperbolic", curvature=1.0)
166
+ Event2Vec(num_event_types=len(vocab), geometry="stereographic", kappa=-1.0)
167
+ Event2Vec(num_event_types=len(vocab), geometry="rotation", rotation_n=3)
168
+ Event2Vec(num_event_types=len(vocab), geometry="product", product_kappas=(-1.0, 1.0))
169
+ ```
170
+
171
+ Hyperbolic embeddings live in the Poincaré ball; use the matching operations on them:
172
+
173
+ ```python
174
+ from event2vector import HyperbolicUtils
175
+
176
+ hyp = Event2Vec(num_event_types=len(vocab), geometry="hyperbolic", curvature=1.0,
177
+ pad_sequences=True, num_epochs=20).fit(sequences)
178
+ z = hyp.transform(sequences, as_numpy=False)
179
+ combined = HyperbolicUtils.mobius_add(z[0:1], z[1:2], hyp.curvature)
180
+ distance = HyperbolicUtils.poincare_dist_sq(z[0:1], z[1:2], hyp.curvature).sqrt()
181
+ ```
182
+
183
+ ### Affine geometry
184
+
185
+ In the additive geometries an event always pushes the state the same way. With
186
+ `geometry="affine"` each event is an invertible affine map `x ↦ exp(M_e) x + v_e`,
187
+ so the same event contributes differently depending on what came before, while
188
+ the model remains a group:
189
+
190
+ - with every `M_e = 0` (the initialization) the result is exactly the Euclidean sum,
191
+ so training starts from the additive model;
192
+ - every step is invertible, and the reconstruction loss recovers it exactly;
193
+ - any sub-sequence composes into a single affine map, so its effect on *any*
194
+ history is one `A x + v`.
195
+
196
+ The state is the whole map `[vec(A), b]`; the point to plot is `b`, the image of the
197
+ origin. The singular values of a sub-sequence's `A` measure how strongly it
198
+ overrides what came before: `1` passes the history through, values below `1`
199
+ erase it along that direction.
200
+
201
+ ```python
202
+ aff = Event2Vec(num_event_types=len(vocab), geometry="affine", embedding_dim=2,
203
+ pad_sequences=True, num_epochs=20).fit(sequences)
204
+
205
+ states = aff.transform(sequences, as_numpy=False) # [vec(A), b] per sequence
206
+ points = aff.model.point(states) # (n_sequences, 2), ready to plot
207
+
208
+ A, v = aff.model.compose([1, 2, 3]) # one map for a sub-sequence
209
+ print(aff.model.override_strength([1, 2, 3])) # its singular values
210
+ ```
211
+
212
+ `affine_readout="full"` lets the decoder read `A` as well as `b`, and
213
+ `affine_max_log_scale` bounds how strongly a single event can stretch or shrink
214
+ the state.
215
+
216
+ ## API reference
217
+
218
+ ### `Event2Vec` parameters
219
+
220
+ | parameter | default | meaning |
221
+ |---|---|---|
222
+ | `num_event_types` | required | size of the event vocabulary |
223
+ | `embedding_dim` | `64` | dimension of the event vectors (the plotted point for `affine`) |
224
+ | `geometry` | `"euclidean"` | see [Geometries](#geometries) |
225
+ | `curvature` | `1.0` | curvature `c > 0` for `hyperbolic` |
226
+ | `kappa` | `None` | signed curvature for `stereographic` / `spherical` |
227
+ | `rotation_n` | `3` | `n` of `SO(n)` for `rotation` |
228
+ | `heisenberg_m` | `1` | the state is the `(2m+1)`-dimensional Heisenberg group |
229
+ | `affine_readout` | `"point"` | `"point"` or `"full"`: what the decoder reads for `affine` |
230
+ | `affine_max_log_scale` | `None` | bound on how much one event can stretch the `affine` state |
231
+ | `product_kappas` | `(-1.0, 1.0)` | one curvature per factor for `product` |
232
+ | `dropout_p` | `0.2` | dropout on each step's increment |
233
+ | `max_norm` | `10.0` | norm clipping of the Euclidean state |
234
+ | `lambda_reconstruction` | `0.2` | weight of the reconstruction loss |
235
+ | `lambda_consistency` | `0.2` | weight of the consistency loss |
236
+ | `learning_rate` | `1e-3` | AdamW learning rate |
237
+ | `batch_size` | `32` | sequences per batch |
238
+ | `num_epochs` | `50` | training epochs |
239
+ | `pad_sequences` | `False` | vectorized padded batches (much faster on large corpora) |
240
+ | `use_gpu` / `device` | `True` / `None` | automatic CUDA / MPS / CPU choice, or an explicit device |
241
+ | `random_state` | `None` | seed for reproducible runs |
242
+ | `deterministic` | `False` | request deterministic kernels |
243
+ | `riemannian` | `False` | Riemannian Adam for `hyperbolic` (needs `geoopt`) |
244
+
245
+ ### Methods
246
+
247
+ | method | returns |
248
+ |---|---|
249
+ | `fit(sequences, epochs=None, verbose=False)` | the fitted estimator; per-epoch losses in `training_loss_` |
250
+ | `transform(sequences, as_numpy=True)` | one state per sequence (NumPy array or tensor) |
251
+ | `fit_transform(sequences, ...)` | `fit`, then `transform` on the same sequences |
252
+ | `most_similar(positive, negative=None, topn=10)` | nearest event ids to events or whole sequences, with similarities |
253
+
254
+ The underlying PyTorch module is `model.model` (event vectors in
255
+ `model.model.embedding.weight`).
256
+
257
+ ### Devices
258
+
259
+ By default the estimator uses CUDA, then Apple MPS, then the CPU. On Apple
260
+ Silicon the `rotation` and `affine` geometries default to the CPU, because MPS has
261
+ no `matrix_exp` kernel and the CPU is faster for them; pass `device="mps"` to
262
+ override. Use `use_gpu=False` to force the CPU, or `device="cuda:0"` to pick a
263
+ device.
264
+
265
+ ## Datasets, metrics and baselines
266
+
267
+ The package ships domains with *exact ground truth* for the additive structure,
268
+ so interpretability can be measured rather than only visualized. Datasets live in
269
+ `event2vector.datasets` and return a uniform record (`sequences`,
270
+ `processed_sequences`, `vocab`, `labels`, `graph`):
271
+
272
+ - `make_decay()`: radioactive decay chains; each event is an exact `(ΔZ, ΔN)`, so
273
+ additivity coincides with conservation laws (metric: `operator_recovery`).
274
+ - `make_group(name)`: Cayley-graph walks on abelian and non-abelian groups; the
275
+ additive endpoint provably equals the abelianization (metric: `abelianization_gap`).
276
+ - `make_lifepath()`, `load_brown()`: a controlled synthetic workbench and real
277
+ part-of-speech sequences.
278
+ - `load_gdelt()`, `load_sec_8k()`, `load_synthea()`, …: real-world event streams
279
+ (each needs a public data download; see the loader's docstring).
280
+
281
+ Metrics are in `event2vector.metrics`, a seeded evaluation harness in
282
+ `event2vector.eval`, and GRU / LSTM / Transformer / Word2Vec baselines in
283
+ `event2vector.baselines`.
284
+
285
+ ## Examples
286
+
287
+ A minimal end-to-end run (loss, embeddings, nearest events):
288
+
289
+ ```bash
290
+ python3 examples/minimal_example.py
291
+ ```
292
+
293
+ Part-of-speech sequences from the Brown corpus (the scripts need a few extra
294
+ packages: NLTK for the corpus, t-SNE and Word2Vec for the comparison plots):
295
+
296
+ ```bash
297
+ pip install "event2vector[viz,manifold,nlp]" nltk
298
+ python3 -m examples.prepare_brown_data
299
+ python3 -m examples.train_brown_data
300
+ python3 -m examples.visualize_brown_corpus
301
+ ```
302
+
303
+ Applications:
304
+
305
+ - [The Geometry of Groceries](https://sulcantonin.substack.com/p/the-geometry-of-groceries)
306
+ - [The Geometry of Language Families](https://sulcantonin.substack.com/p/the-geometry-of-language-families)
307
+
308
+ ## Development
309
+
310
+ ```bash
311
+ pip install -e . pytest
312
+ pytest tests/ -q
313
+ ```
314
+
315
+ Changes are listed in [CHANGELOG.md](https://github.com/sulcantonin/event2vec_public/blob/main/CHANGELOG.md).
316
+ Bug reports and questions are welcome in the
317
+ [issue tracker](https://github.com/sulcantonin/event2vec_public/issues).
318
+
319
+ ## Citation
320
+
321
+ If you use Event2Vector, please cite the paper, published in the
322
+ [Proceedings of Machine Learning Research](https://proceedings.mlr.press/v282/sulc26a.html) (vol. 282, NeurIPS Workshops
323
+ on Symmetry and Geometry in Neural Representations):
324
+
325
+ ```bibtex
326
+ @InProceedings{pmlr-v282-sulc26a,
327
+ title = {Event2Vec: A Geometric Approach to Learning Composable Representations of Event Sequences},
328
+ author = {Sulc, Antonin},
329
+ booktitle = {Proceedings of the 4th (2025) and 3rd (2024) NeurIPS Workshops on Symmetry and Geometry in Neural Representations},
330
+ pages = {492--512},
331
+ year = {2026},
332
+ editor = {Acosta, Francisco and Azeglio, Simone and Tolooshams, Bahareh and van de Geijn, Chase and Shewmake, Christian and Sanborn, Sophia and Miolane, Nina},
333
+ volume = {282},
334
+ series = {Proceedings of Machine Learning Research},
335
+ publisher = {PMLR},
336
+ url = {https://proceedings.mlr.press/v282/sulc26a.html}
337
+ }
338
+ ```
339
+
340
+ A preprint is on [arXiv:2509.12188](https://arxiv.org/abs/2509.12188).
341
+
342
+ To cite the software itself, use its Zenodo DOI
343
+ [10.5281/zenodo.23399003](https://doi.org/10.5281/zenodo.23399003), which always
344
+ resolves to the latest version (each release also has its own DOI). GitHub's
345
+ "Cite this repository" button reads the same metadata from `CITATION.cff`.
346
+
347
+ ## License
348
+
349
+ MIT. See the license badge above.