File size: 9,456 Bytes
1f71c7d | 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 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | """Generate benchmark datasets for ENSEMBLE vs transformer comparison.
Three corpora, each probing a different axis:
1. ``facts`` — declarative factual statements (recall / next-token accuracy).
This is ENSEMBLE's home turf: pure memorization+recall.
2. ``qa`` — question/answer pairs (associative retrieval accuracy).
3. ``prose`` — natural prose (fluence / general language modeling).
Each is generated deterministically so results are reproducible.
"""
from __future__ import annotations
import json
import random
from pathlib import Path
# ----------------------------------------------------------------- facts
FACTS = [
"the mitochondria is the powerhouse of the cell and produces atp",
"photosynthesis converts sunlight into chemical energy in plants",
"the speed of light is approximately 299792458 meters per second",
"water boils at 100 degrees celsius at standard atmospheric pressure",
"the great wall of china stretches across northern china",
"dna contains the genetic instructions for living organisms",
"the amazon river is the largest river by volume in the world",
"mount everest is the highest mountain above sea level at 8848 meters",
"the human body has 206 bones in the adult skeleton",
"jupiter is the largest planet in the solar system",
"the pacific ocean is the largest and deepest ocean on earth",
"iron rusts when exposed to oxygen and moisture over time",
"honey never spoils and can remain edible for thousands of years",
"octopuses have three hearts and blue blood",
"a group of flamingos is called a flamboyance",
"the statue of liberty was a gift from france to the united states",
"the freezing point of water is zero degrees celsius",
"sound travels at approximately 343 meters per second in air",
"venus is the hottest planet in the solar system",
"a jiffy is an actual unit of time equal to one hundredth of a second",
"bananas are berries but strawberries are not",
"the eiffel tower can grow more than fifteen centimeters in summer",
"there are more possible chess games than atoms in the universe",
"the unicorn is the national animal of scotland",
"a single cloud can weigh more than a million pounds",
"the hawaiian alphabet has only twelve letters",
"cows have best friends and get stressed when separated",
"the inventor of the frisbee was turned into a frisbee after he died",
"wombat poop is shaped like a cube",
"the shortest war in history lasted 38 minutes",
]
def gen_facts(n_repeat: int = 8) -> str:
"""Declarative facts, repeated to give the LM enough transitions."""
rng = random.Random(42)
lines = []
for _ in range(n_repeat):
block = list(FACTS)
rng.shuffle(block)
lines.extend(block)
return ". ".join(lines) + "."
# ----------------------------------------------------------------- QA
QA = [
("what is the powerhouse of the cell", "the powerhouse of the cell is the mitochondria"),
("what is the speed of light", "the speed of light is 299792458 meters per second"),
("how many bones are in the human body", "the human body has 206 bones"),
("what is the largest planet", "the largest planet is jupiter"),
("what is the largest ocean", "the largest ocean is the pacific"),
("what is the largest river by volume", "the largest river by volume is the amazon"),
("what is the highest mountain", "the highest mountain is mount everest at 8848 meters"),
("at what temperature does water boil", "water boils at 100 degrees celsius"),
("at what temperature does water freeze", "water freezes at zero degrees celsius"),
("what contains genetic instructions", "dna contains the genetic instructions"),
("what is the hottest planet", "the hottest planet is venus"),
("what is the capital of france", "the capital of france is paris"),
("what is the capital of japan", "the capital of japan is tokyo"),
("what is the capital of italy", "the capital of italy is rome"),
("what is the capital of egypt", "the capital of egypt is cairo"),
("what is the capital of brazil", "the capital of brazil is brasilia"),
("what is the capital of spain", "the capital of spain is madrid"),
("what is the capital of germany", "the capital of germany is berlin"),
("what is the capital of russia", "the capital of russia is moscow"),
("what is the capital of india", "the capital of india is new delhi"),
("what is the capital of china", "the capital of china is beijing"),
("what is the capital of canada", "the capital of canada is ottawa"),
("what is the capital of australia", "the capital of australia is canberra"),
("what is the capital of greece", "the capital of greece is athens"),
("what is the capital of portugal", "the capital of portugal is lisbon"),
("what is two plus two", "two plus two equals four"),
("what is three times three", "three times three equals nine"),
("what is the square root of nine", "the square root of nine is three"),
("what is pi", "pi is approximately three point one four"),
("what is ten minus four", "ten minus four equals six"),
]
def gen_qa(n_repeat: int = 6) -> list[tuple[str, str]]:
"""Q/A pairs (held-out split returned separately by gen_splits)."""
rng = random.Random(42)
pairs = []
for _ in range(n_repeat):
block = list(QA)
rng.shuffle(block)
pairs.extend(block)
return pairs
def gen_qa_splits(
train_repeat: int = 6, holdout_frac: float = 0.25,
) -> tuple[list[tuple[str, str]], list[tuple[str, str]]]:
"""Return (train, holdout) splits. Holdout is a fraction of *unique* pairs."""
rng = random.Random(7)
unique = list(dict.fromkeys(QA)) # preserve order, dedupe
rng.shuffle(unique)
n_hold = max(1, int(len(unique) * holdout_frac))
holdout = unique[:n_hold]
train_unique = unique[n_hold:]
train: list[tuple[str, str]] = []
for _ in range(train_repeat):
b = list(train_unique)
rng.shuffle(b)
train.extend(b)
return train, holdout
# ----------------------------------------------------------------- prose
PROSE_SENTENCES = [
"the old lighthouse stood alone on the rocky cliff overlooking the grey sea",
"every morning she walked the same path through the quiet pine forest",
"the library smelled of old paper and quiet promises of forgotten stories",
"rain tapped gently against the window as the fire crackled in the hearth",
"he had never seen the ocean before and the sight of it took his breath away",
"the little bakery on the corner opened at dawn and filled the street with warmth",
"she collected maps of places she had never been and dreamed of visiting each one",
"the train arrived late as always but no one at the station seemed to mind",
"in the garden the bees moved lazily from flower to flower in the afternoon sun",
"the clock on the wall had stopped at midnight and no one remembered when",
"children laughed in the distance as the kite climbed higher into the blue sky",
"the river wound through the valley like a silver ribbon under the pale moon",
"an old man sat on the bench feeding pigeons from a paper bag in his lap",
"the city looked different at night all neon and noise and restless energy",
"somewhere in the attic a box of letters waited to be found and read again",
"the dog bounded across the field chasing shadows that were never quite there",
"she painted the sky in shades of orange and pink as the sun dipped below the hills",
"the café was nearly empty save for a student hunched over a thick textbook",
"footsteps echoed down the empty corridor long after everyone had gone home",
"the first snow of winter fell softly covering the town in a blanket of white",
]
def gen_prose(n_repeat: int = 10) -> str:
rng = random.Random(99)
lines = []
for _ in range(n_repeat):
block = list(PROSE_SENTENCES)
rng.shuffle(block)
lines.extend(block)
return ". ".join(lines) + "."
# ----------------------------------------------------------------- driver
def generate_all(out_dir: str | Path) -> dict[str, Path]:
out = Path(out_dir)
out.mkdir(parents=True, exist_ok=True)
paths = {}
facts_text = gen_facts()
(out / "facts.txt").write_text(facts_text, encoding="utf-8")
paths["facts"] = out / "facts.txt"
train, holdout = gen_qa_splits()
with open(out / "qa_train.json", "w", encoding="utf-8") as f:
json.dump([{"question": q, "answer": a} for q, a in train], f,
ensure_ascii=False)
with open(out / "qa_holdout.json", "w", encoding="utf-8") as f:
json.dump([{"question": q, "answer": a} for q, a in holdout], f,
ensure_ascii=False)
paths["qa_train"] = out / "qa_train.json"
paths["qa_holdout"] = out / "qa_holdout.json"
prose_text = gen_prose()
(out / "prose.txt").write_text(prose_text, encoding="utf-8")
paths["prose"] = out / "prose.txt"
return paths
if __name__ == "__main__":
import argparse
p = argparse.ArgumentParser()
p.add_argument("-o", "--out", default="bench_data")
args = p.parse_args()
paths = generate_all(args.out)
for k, v in paths.items():
size = v.stat().st_size
print(f" {k:12s} {size:>8,} bytes {v}")
|