hug-gay hackersgame commited on
Commit
ff0a07d
·
0 Parent(s):

Duplicate from hackersgame/Free_Language_Embeddings

Browse files

Co-authored-by: David Hamner <hackersgame@users.noreply.huggingface.co>

Files changed (4) hide show
  1. .gitattributes +35 -0
  2. README.md +179 -0
  3. fle.py +152 -0
  4. fle_v34.npz +3 -0
.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ language:
3
+ - en
4
+ license: gpl-3.0
5
+ tags:
6
+ - word-embeddings
7
+ - word2vec
8
+ - embeddings
9
+ - nlp
10
+ - free-software
11
+ - dfsg
12
+ datasets:
13
+ - wikimedia/wikipedia
14
+ - pg19
15
+ metrics:
16
+ - accuracy
17
+ model-index:
18
+ - name: fle-v34
19
+ results:
20
+ - task:
21
+ type: word-analogy
22
+ name: Word Analogy
23
+ dataset:
24
+ type: custom
25
+ name: Google Analogy Test Set
26
+ metrics:
27
+ - type: accuracy
28
+ value: 66.5
29
+ name: Overall Accuracy
30
+ - type: accuracy
31
+ value: 61.4
32
+ name: Semantic Accuracy
33
+ - type: accuracy
34
+ value: 69.2
35
+ name: Syntactic Accuracy
36
+ library_name: numpy
37
+ pipeline_tag: feature-extraction
38
+ ---
39
+
40
+ # Free Language Embeddings (V34)
41
+
42
+ 300-dimensional word vectors trained from scratch on ~2B tokens of freely-licensed text using a single RTX 3090.
43
+
44
+ **66.5% on Google analogies** — beating the original word2vec (61% on 6B tokens) by 5.5 points with 1/3 the data.
45
+
46
+ ## Model Details
47
+
48
+ | | |
49
+ |---|---|
50
+ | **Architecture** | Dynamic masking word2vec skip-gram |
51
+ | **Dimensions** | 300 |
52
+ | **Vocabulary** | 100,000 whole words |
53
+ | **Training data** | ~2B tokens, all [DFSG-compliant](https://wiki.debian.org/DFSGLicenses) (see below) |
54
+ | **Training hardware** | Single NVIDIA RTX 3090 |
55
+ | **Training time** | ~4 days (2M steps) |
56
+ | **License** | GPL-3.0 |
57
+ | **Parameters** | 60M (30M target + 30M context embeddings) |
58
+
59
+ ### Training Data
60
+
61
+ All training data meets the [Debian Free Software Guidelines](https://wiki.debian.org/DFSGLicenses) for redistribution, modification, and use. No web scrapes, no proprietary datasets.
62
+
63
+ | Source | Weight | License |
64
+ |--------|--------|---------|
65
+ | Wikipedia | 30% | CC BY-SA 3.0 |
66
+ | Project Gutenberg | 20% | Public domain |
67
+ | arXiv | 20% | Various open access |
68
+ | Stack Exchange | 16% | CC BY-SA 4.0 |
69
+ | US Government Publishing Office | 10% | Public domain (US gov) |
70
+ | RFCs | 2.5% | IETF Trust |
71
+ | Linux kernel docs, Arch Wiki, TLDP, GNU manuals, man pages | 1.5% | GPL/GFDL |
72
+
73
+ ## Benchmark Results
74
+
75
+ | Model | Data | Google Analogies |
76
+ |-------|------|-----------------|
77
+ | **fle V34 (this model)** | **~2B tokens** | **66.5%** |
78
+ | word2vec (Mikolov 2013) | 6B tokens | 61.0% |
79
+ | GloVe (small) | 6B tokens | 71.0% |
80
+ | Google word2vec | 6B tokens | 72.7% |
81
+ | GloVe (Pennington 2014) | 840B tokens | 75.6% |
82
+ | FastText (Bojanowski 2017) | 16B tokens | 77.0% |
83
+
84
+ Breakdown: semantic 61.4%, syntactic 69.2%. Comparatives 91.7%, plurals 86.8%, capitals 82.6%.
85
+
86
+ ## Quick Start
87
+
88
+ ```bash
89
+ # Download
90
+ pip install huggingface_hub numpy
91
+ python -c "
92
+ from huggingface_hub import hf_hub_download
93
+ hf_hub_download('hackersgame/Free_Language_Embeddings', 'fle_v34.npz', local_dir='.')
94
+ hf_hub_download('hackersgame/Free_Language_Embeddings', 'fle.py', local_dir='.')
95
+ "
96
+
97
+ # Use
98
+ python fle.py king - man + woman
99
+ python fle.py --similar cat
100
+ python fle.py # interactive mode
101
+ ```
102
+
103
+ ### Python API
104
+
105
+ ```python
106
+ from fle import FLE
107
+
108
+ fle = FLE() # loads fle_v34.npz
109
+ vec = fle["cat"] # 300d numpy array
110
+ fle.similar("cat", n=10) # nearest neighbors
111
+ fle.analogy("king", "man", "woman") # king:man :: woman:?
112
+ fle.similarity("cat", "dog") # cosine similarity
113
+ fle.query("king - man + woman") # vector arithmetic
114
+ ```
115
+
116
+ ## Examples
117
+
118
+ ```
119
+ $ python fle.py king - man + woman
120
+ → queen 0.7387
121
+ → princess 0.6781
122
+ → monarch 0.5546
123
+
124
+ $ python fle.py paris - france + germany
125
+ → berlin 0.8209
126
+ → vienna 0.7862
127
+ → munich 0.7850
128
+
129
+ $ python fle.py --similar cat
130
+ kitten 0.7168
131
+ cats 0.6849
132
+ tabby 0.6572
133
+ dog 0.5919
134
+
135
+ $ python fle.py ubuntu - debian + redhat
136
+ centos 0.6261
137
+ linux 0.6016
138
+ rhel 0.5949
139
+
140
+ $ python fle.py brain
141
+ cerebral 0.6665
142
+ cerebellum 0.6022
143
+ nerves 0.5748
144
+ ```
145
+
146
+ ## What Makes This Different
147
+
148
+ - **Free as in freedom.** Every dataset is DFSG-compliant. Every weight is reproducible. GPL-3.0 licensed. The goal: word embeddings you could `apt install` from Debian main.
149
+ - **Dynamic masking.** Randomly masks context positions during training, forcing the model to extract signal from partial views. The result: geometry that crystallizes during cosine LR decay — analogies jump from 1.2% to 66.5% in the second half of training.
150
+ - **Whole-word vocabulary.** No subword tokenization. Subwords break word2vec geometry completely — they don't carry enough meaning individually for co-occurrence statistics to produce useful structure.
151
+
152
+ ## Training
153
+
154
+ Trained with cosine learning rate schedule (3e-4 → 1e-6). The training curve shows a striking crystallization pattern: near-zero analogy accuracy for the first 50% of training, then rapid emergence of geometric structure as the learning rate decays.
155
+
156
+ Full training code and visualizations: [github.com/ruapotato/Free-Language-Embeddings](https://github.com/ruapotato/Free-Language-Embeddings)
157
+
158
+ ## Interactive Visualizations
159
+
160
+ - [Embedding Spectrogram](https://ruapotato.github.io/Free-Language-Embeddings/spectrogram.html) — PCA waves, sine fits, cosine surfaces
161
+ - [3D Semantic Directions](https://ruapotato.github.io/Free-Language-Embeddings/semantic_3d.html) — See how semantic axes align in the learned geometry
162
+ - [Training Dashboard](https://ruapotato.github.io/Free-Language-Embeddings/dashboard.html) — Loss curves and training metrics
163
+
164
+ ## Citation
165
+
166
+ ```bibtex
167
+ @misc{hamner2026fle,
168
+ title={Free Language Embeddings: Dynamic Masking Word2Vec on DFSG-Compliant Data},
169
+ author={David Hamner},
170
+ year={2026},
171
+ url={https://github.com/ruapotato/Free-Language-Embeddings}
172
+ }
173
+ ```
174
+
175
+ ## License
176
+
177
+ GPL-3.0 — See [LICENSE](https://github.com/ruapotato/Free-Language-Embeddings/blob/main/LICENSE) for details.
178
+
179
+ Built by David Hamner.
fle.py ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Free Language Embeddings — load and query V34 word vectors.
3
+
4
+ Usage:
5
+ python fle.py # interactive mode
6
+ python fle.py king - man + woman # single query
7
+ python fle.py --similar cat # nearest neighbors
8
+
9
+ Requires: fle_v34.npz (download from GitHub releases)
10
+ """
11
+
12
+ import numpy as np
13
+ import sys
14
+ import os
15
+
16
+ EMBEDDINGS_FILE = os.path.join(os.path.dirname(__file__), "fle_v34.npz")
17
+
18
+
19
+ class FLE:
20
+ """Free Language Embeddings — 100K words, 300d, V34 dynamic masking word2vec."""
21
+
22
+ def __init__(self, path=EMBEDDINGS_FILE):
23
+ data = np.load(path, allow_pickle=True)
24
+ self.embeddings = data["embeddings"] # (100000, 300) float32
25
+ self.words = list(data["words"])
26
+ self.word2id = {w: i for i, w in enumerate(self.words)}
27
+ self._normed = None
28
+
29
+ @property
30
+ def normed(self):
31
+ if self._normed is None:
32
+ norms = np.linalg.norm(self.embeddings, axis=1, keepdims=True)
33
+ self._normed = self.embeddings / np.maximum(norms, 1e-8)
34
+ return self._normed
35
+
36
+ def __contains__(self, word):
37
+ return word in self.word2id
38
+
39
+ def __getitem__(self, word):
40
+ return self.embeddings[self.word2id[word]]
41
+
42
+ def similar(self, word, n=10):
43
+ """Find n most similar words."""
44
+ if word not in self.word2id:
45
+ return []
46
+ vec = self.normed[self.word2id[word]]
47
+ sims = self.normed @ vec
48
+ sims[self.word2id[word]] = -1
49
+ top = np.argsort(-sims)[:n]
50
+ return [(self.words[i], float(sims[i])) for i in top]
51
+
52
+ def analogy(self, a, b, c, n=5):
53
+ """a is to b as c is to ? (a - b + c)"""
54
+ for w in [a, b, c]:
55
+ if w not in self.word2id:
56
+ return []
57
+ vec = self.normed[self.word2id[a]] - self.normed[self.word2id[b]] + self.normed[self.word2id[c]]
58
+ vec = vec / (np.linalg.norm(vec) + 1e-8)
59
+ sims = self.normed @ vec
60
+ for w in [a, b, c]:
61
+ sims[self.word2id[w]] = -1
62
+ top = np.argsort(-sims)[:n]
63
+ return [(self.words[i], float(sims[i])) for i in top]
64
+
65
+ def similarity(self, a, b):
66
+ """Cosine similarity between two words."""
67
+ if a not in self.word2id or b not in self.word2id:
68
+ return None
69
+ return float(self.normed[self.word2id[a]] @ self.normed[self.word2id[b]])
70
+
71
+ def query(self, expression):
72
+ """Evaluate a vector arithmetic expression like 'king - man + woman'."""
73
+ tokens = expression.strip().split()
74
+ if not tokens:
75
+ return []
76
+
77
+ vec = np.zeros(self.embeddings.shape[1])
78
+ sign = 1.0
79
+ used = set()
80
+ for token in tokens:
81
+ if token == '+':
82
+ sign = 1.0
83
+ elif token == '-':
84
+ sign = -1.0
85
+ elif token in self.word2id:
86
+ vec += sign * self.normed[self.word2id[token]]
87
+ used.add(token)
88
+ sign = 1.0
89
+ else:
90
+ return [(f"'{token}' not in vocabulary", 0.0)]
91
+
92
+ vec = vec / (np.linalg.norm(vec) + 1e-8)
93
+ sims = self.normed @ vec
94
+ for w in used:
95
+ sims[self.word2id[w]] = -1
96
+ top = np.argsort(-sims)[:10]
97
+ return [(self.words[i], float(sims[i])) for i in top]
98
+
99
+
100
+ def main():
101
+ if not os.path.exists(EMBEDDINGS_FILE):
102
+ print(f"Error: {EMBEDDINGS_FILE} not found.")
103
+ print("Download from: https://github.com/ruapotato/Free-Language-Embeddings/releases")
104
+ sys.exit(1)
105
+
106
+ fle = FLE()
107
+ print(f"Loaded {len(fle.words):,} words, {fle.embeddings.shape[1]}d")
108
+
109
+ # CLI mode
110
+ if len(sys.argv) > 1:
111
+ if sys.argv[1] == "--similar":
112
+ word = sys.argv[2] if len(sys.argv) > 2 else "cat"
113
+ for w, s in fle.similar(word, 15):
114
+ print(f" {w:<20} {s:.4f}")
115
+ else:
116
+ expr = " ".join(sys.argv[1:])
117
+ print(f" {expr}")
118
+ for w, s in fle.query(expr):
119
+ print(f" → {w:<20} {s:.4f}")
120
+ return
121
+
122
+ # Interactive mode
123
+ print("\nExamples:")
124
+ print(" king - man + woman")
125
+ print(" similar cat")
126
+ print(" paris - france + germany")
127
+ print()
128
+
129
+ while True:
130
+ try:
131
+ line = input("fle> ").strip()
132
+ except (EOFError, KeyboardInterrupt):
133
+ print()
134
+ break
135
+
136
+ if not line:
137
+ continue
138
+
139
+ if line.startswith("similar "):
140
+ word = line.split()[1]
141
+ results = fle.similar(word, 15)
142
+ if not results:
143
+ print(f" '{word}' not in vocabulary")
144
+ for w, s in results:
145
+ print(f" {w:<20} {s:.4f}")
146
+ else:
147
+ for w, s in fle.query(line):
148
+ print(f" {w:<20} {s:.4f}")
149
+
150
+
151
+ if __name__ == "__main__":
152
+ main()
fle_v34.npz ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f053ec7187803979d3feda6cd6d8f7256852357b4297c98b140ebbba1e7517fd
3
+ size 112284219