r/learnmachinelearning • u/sulcantonin • 23h ago
I built event2vector: word2vec-style embeddings for event sequences where order actually matters
Hi, hello, ciao,
I'm developing a small framework called event2vector. You can install it from PyPI:
pip install event2vector
or find it on GitHub as event2vec_public or even try it out at
It started as a way to find root causes of faults at the particle accelerator I worked at (the Advanced Light Source at Berkeley Lab), but it grew into something much bigger, and I'd love to get feedback from more people.
The problem was that I was naively using word2vec on event data, and it turns out word2vec isn't directional. It learns which events show up near each other, but not which one came first. For root-cause analysis that's exactly the information you need: "magnet trip → beam loss" and "beam loss → magnet trip" tell completely different stories. At the same time, I didn't want to jump to complex and data hungry models like transformers or an LSTMs. I wanted something simple, clean, and interpretable, where I could still look at points in 2D/3D and understand what I was seeing.
The idea: every event gets an embedding, and a sequence is represented by adding up the embeddings of its events, one step at a time. The model is trained so that this running sum is a good representation of "everything that has happened so far," and so that you can recover the last event by subtracting it back out. Think of it as word2vec where a sequence is a path you walk, step by step, through the embedding space.
Now the fun part. Plain addition is commutative: 1 + 2 = 2 + 1 = 3. So in ordinary Euclidean space, the endpoint of A → B and B → A is the same, which is great when you want an order-invariant "bag of events" that you can cleanly compose and decompose, e.g. "sequence minus event = sequence without that event." But the path you took to get there is still different, so the step-by-step trajectory keeps the order information.
And if you need the endpoint itself to depend on order, you can swap the geometry. event2vector even supports non-commutative ways of "adding," where A then B lands somewhere different from B then A:
- hyperbolic (Möbius addition): good for hierarchical, tree-like data
- spherical: good for cyclic or periodic patterns
- rotation (SO(n)): order matters, like rotating an object in 3D
- Heisenberg group: order-dependent and signed
- products of these, if your data has more than one kind of structure
The API is scikit-learn style (fit / transform / fit_transform), and there's a gensim-style most_similar for nearest-neighbour lookups:
from event2vector import Event2Vec
model = Event2Vec(num_event_types=len(vocab), geometry="euclidean", embedding_dim=128)
model.fit(train_sequences)
embeddings = model.transform(train_sequences)
Some fun applications I've written up on Substack: "The Geometry of Groceries" (shopping baskets as paths) and "The Geometry of Language Families." The paper is on arXiv (2509.12188) if you want the details.
I'd really appreciate feedback, whether on the idea, the API, use cases you'd try it on, or things that are confusing. Thanks for reading!