File size: 6,736 Bytes
a131386
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
---

license: apache-2.0
language:
- en
library_name: sentence-transformers
pipeline_tag: sentence-similarity
base_model: sentence-transformers/all-MiniLM-L6-v2
datasets:
- FronkonGames/steam-games-dataset
tags:
- transformers.js
- onnx
- sentence-transformers
- sentence-similarity
- feature-extraction
- recommendation
- video-games
- steam
---


# gamespace.2

gamespace.2 embeds video games into a 128-dimensional space where games that the same people enjoy
sit close together. It powers the [GameMerge](https://huggingface.co/spaces/GulkoA/gamemerge)
recommender. Output vectors are L2-normalised, so a dot product is the cosine similarity.

It is [all-MiniLM-L6-v2](https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2) fine-tuned on
Steam store data, like [gamespace.1](https://huggingface.co/GulkoA/gamespace.1). It also learns from
player behaviour: pairs of games that the same Steam reviewers engaged with are positive examples.
The model still reads only a game's store text, so it works for any game, including new ones with no
players yet.

## Steam next-game benchmark

The benchmark follows the protocol of SASRec (Kang & McAuley, ICDM 2018) on their Steam review crawl.
Each user's most recent reviewed game is held out and ranked against 100 randomly sampled games, and
also against the whole catalog. Text models score candidates by cosine similarity to the mean of the
user's earlier games. Games no longer on the Steam store have no text to embed, so they were removed
before the five-review filter. That leaves 250,955 users, 10,318 games and 3.05M interactions. The
paper had 334,730 users and 13,047 games. Popularity and SASRec were re-run on this exact split.

| Model | Learns from user histories | Hit@10, 100 negatives | NDCG@10, 100 negatives | Hit@10, all games | NDCG@10, all games |
|---|---|---|---|---|---|
| SASRec, reproduced | yes | 0.836 | 0.581 | 0.115 | 0.060 |
| Popularity | yes | 0.688 | 0.420 | 0.050 | 0.025 |
| **gamespace.2, soft-max over history** | **pairs from training histories** | **0.518** | **0.308** | **0.046** | **0.025** |
| gamespace.2, mean of history | pairs from training histories | 0.511 | 0.301 | 0.034 | 0.018 |
| gamespace.2 + CLIP header art | pairs from training histories | 0.520 | 0.309 | 0.037 | 0.019 |
| gamespace.1 | no | 0.438 | 0.251 | 0.027 | 0.014 |
| e5-large-v2 | no | 0.404 | 0.234 | 0.030 | 0.016 |
| Qwen3-Embedding-0.6B | no | 0.336 | 0.185 | 0.018 | 0.010 |
| bge-large-en-v1.5 | no | 0.334 | 0.191 | 0.026 | 0.014 |
| all-MiniLM-L6-v2 | no | 0.306 | 0.162 | 0.017 | 0.010 |
| CLIP header art only | no | 0.288 | 0.158 | 0.014 | 0.007 |

For reference, the SASRec paper reports 0.873 and 0.631 on its full 13,047-game set.

The soft-max row scores each candidate by a soft maximum (log-mean-exp, temperature 0.1, chosen on
the validation split) of its cosine similarity to each earlier game, instead of similarity to their
mean. Mixed histories are not pulled toward one average point, which matters most when ranking the
whole catalog. GameMerge uses it to combine your picks.

gamespace.2 is the best of the text embedding models, ahead of much larger general-purpose embedders.
Sequential recommenders trained on the interaction data remain far stronger at predicting the next
game, because they also learn popularity and order. gamespace.2 trades that for working on any game
from its description alone.

## Training

- **Data.** The [Steam Games Dataset](https://huggingface.co/datasets/FronkonGames/steam-games-dataset)
  has 147,352 apps. Soundtracks, demos, playtests, servers, SDKs, and empty records were removed,
  leaving 138,920 games.
- **Objective.** Contrastive training uses `CachedMultipleNegativesRankingLoss` with 128 in-batch
  negatives. There are three kinds of positive pairs:
  - 70,000 pairs are two randomly degraded views of the same game.
  - 70,000 pairs are games whose vote-weighted user-tag profiles have a cosine of at least 0.6.
  - 66,904 pairs are co-liked games. There are 36,371 distinct pairs, each shown in both orders.
    They are mined from the benchmark's training histories only, so no validation or test game is

    used. A pair must be shared by at least 5 reviewers, it is scored by normalised PMI, and each

    game keeps its 10 strongest partners.

- **Settings.** The projection is `Dense(384→128)`, initialised from PCA. Training runs one epoch at

  learning rate 3e-5, with 128-token documents.


A looser pair set, with at least 3 shared reviewers and 20 partners per game, scored lower on
validation, with 0.477 against 0.503 Hit@10. Pair quality matters more than quantity.

## Usage

The model reads one short document per game. Build it with `docs.py` from this repo, using the same
format as gamespace.1:

```

Hollow Knight. Genres: Action, Adventure, Indie. Tags: Metroidvania, Souls-like, ... Modes: Single-player. Developer: Team Cherry. Forge your own path...

```

```python

from sentence_transformers import SentenceTransformer

model = SentenceTransformer("GulkoA/gamespace.2")

vec = model.encode("Hollow Knight. Genres: Action, Adventure, Indie. Tags: Metroidvania, Souls-like.")

```

### In the browser

`onnx/model_quantized.onnx` is 22 MB, per-channel int8, with cosine 0.995 to the PyTorch model. It
runs with [transformers.js](https://huggingface.co/docs/transformers.js). Apply the 128x384 projection
in `dense.bin`, which holds float32 weights in row-major order followed by the 128 biases, to the
mean-pooled output:

```js

import { pipeline } from "@huggingface/transformers";



const extractor = await pipeline("feature-extraction", "GulkoA/gamespace.2", { dtype: "q8" });

const w = new Float32Array(await (await fetch("https://huggingface.co/GulkoA/gamespace.2/resolve/main/dense.bin")).arrayBuffer());

const { data: x } = await extractor("cozy farming game with fishing", { pooling: "mean", normalize: false });

const y = Array.from({ length: 128 }, (_, i) => w[128 * 384 + i] + x.reduce((s, xj, j) => s + w[i * 384 + j] * xj, 0));

const norm = Math.hypot(...y);

const vec = y.map((v) => v / norm);

```

## Limitations

- The behaviour pairs come from reviews written between 2010 and January 2018. Newer games benefit
  only through what the model generalises from text.
- Steam display names identify reviewers, and different people can share a name.
- Similarity ignores popularity and quality, so obscure games rank alongside well-known ones.

## License

The model is licensed under Apache 2.0, the same as the base model. The store data is MIT-licensed.
The review crawl is from the UCSD Steam datasets (Kang & McAuley, 2018).