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.
- {event2vector-0.4.0 → event2vector-0.4.1}/CHANGELOG.md +23 -0
- {event2vector-0.4.0 → event2vector-0.4.1}/CITATION.cff +13 -6
- event2vector-0.4.1/PKG-INFO +349 -0
- event2vector-0.4.1/README.md +314 -0
- {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/__init__.py +1 -1
- event2vector-0.4.1/event2vector.egg-info/PKG-INFO +349 -0
- {event2vector-0.4.0 → event2vector-0.4.1}/pyproject.toml +1 -1
- event2vector-0.4.0/PKG-INFO +0 -262
- event2vector-0.4.0/README.md +0 -227
- event2vector-0.4.0/event2vector.egg-info/PKG-INFO +0 -262
- {event2vector-0.4.0 → event2vector-0.4.1}/MANIFEST.in +0 -0
- {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/baselines.py +0 -0
- {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/data.py +0 -0
- {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/datasets/__init__.py +0 -0
- {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/datasets/arithmetic.py +0 -0
- {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/datasets/brown.py +0 -0
- {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/datasets/decay.py +0 -0
- {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/datasets/groups.py +0 -0
- {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/datasets/lifepath.py +0 -0
- {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/datasets/realdata.py +0 -0
- {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/eval/__init__.py +0 -0
- {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/eval/figures.py +0 -0
- {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/eval/harness.py +0 -0
- {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/geometries.py +0 -0
- {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/metrics.py +0 -0
- {event2vector-0.4.0 → event2vector-0.4.1}/event2vector/models.py +0 -0
- {event2vector-0.4.0 → event2vector-0.4.1}/event2vector.egg-info/SOURCES.txt +0 -0
- {event2vector-0.4.0 → event2vector-0.4.1}/event2vector.egg-info/dependency_links.txt +0 -0
- {event2vector-0.4.0 → event2vector-0.4.1}/event2vector.egg-info/requires.txt +0 -0
- {event2vector-0.4.0 → event2vector-0.4.1}/event2vector.egg-info/top_level.txt +0 -0
- {event2vector-0.4.0 → event2vector-0.4.1}/setup.cfg +0 -0
- {event2vector-0.4.0 → event2vector-0.4.1}/tests/test_affine.py +0 -0
- {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.
|
|
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:
|
|
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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
+
[](https://badge.fury.io/py/event2vector)
|
|
48
|
+
[](https://doi.org/10.5281/zenodo.23399003)
|
|
49
|
+
[](https://opensource.org/licenses/MIT)
|
|
50
|
+
[](https://www.python.org/downloads/)
|
|
51
|
+
[](https://proceedings.mlr.press/v282/sulc26a.html)
|
|
52
|
+
[](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
|
+

|
|
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
|
+

|
|
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.
|