Downloads · 30 days
92
34% of all-time downloads
NagaYu/crowd-anon-0.1b
crowd-anon-0.1b is a text classification model from NagaYu. Use it when you need a label for a piece of text. It is set up for crowd. The card lists the license as apache-2.0.
Ethical conditions (read before anything else) This model does not identify people, and cannot be made to. It maps a description to how many people in a reference population could match it. The reference population is…
Downloads · 30 days
92
34% of all-time downloads
All-time downloads
270
Public
Repo size
1.5 GB
Likes
0
Public
Click a slice to open those files.
.pt441 MB · 30%
From the Hugging Face model README
Ethical conditions (read before anything else)
This model does not identify people, and cannot be made to. It maps a description to how many people in a reference population could match it. The reference population is a probability model built from published aggregate statistics; there is no index of individuals anywhere in the system, nothing takes a person as input, and no output type has a field that could carry an identity. This is enforced by
tests/test_no_identification_path.py, not promised in prose.Outputs are a risk estimate and a set of masking candidates. Nothing else. There is no code path that produces "this description refers to X".
Counts are censored at a reporting floor of 5. Any combination matching fewer than five people is reported as "≤5". The model is trained with a censored (Tobit) likelihood so that it learns to say that, rather than learning to interpolate below the floor. A model that could tell one person from two would be a re-identification oracle.
The attack code that evaluates this model reproduces published techniques only, and is applied only to this project's own outputs. No new attack is developed, and the attack modules do not take a person as input.
This model does not guarantee anonymity and must not be described as if it did. Information usable for re-identification is unbounded in principle. This is a tool for estimation and prioritisation. Every number it emits is conditional on the reference population and the assumptions listed below.
Input: a Japanese (or English) description of a person.
Output: μ, σ over log10(number of people in the reference population matching
the quasi-identifiers in the text), converted to a calibrated interval by a
split-conformal wrapper fitted on held-out data.
from crowd.estimator import NeuralEstimator
est = NeuralEstimator("crowd-anon-0.1b")
e = est.predict(["都内で四十代前半の男性が子どもの心臓を診る医師として働いている。"])[0]
print(e.human()) # "~33 people (90% interval 6–190)"
print(e.meets(k=1000)) # False -> this description needs masking
Paired with crowd.optimize.MinimalMaskOptimizer it becomes a redactor that
hides the minimum needed to reach a target crowd size.
| parameters | 110.3M (0.11B — inside the 0.1–0.3B design target) |
| layers / d_model / heads | 12 / 768 / 12 |
| feed-forward | 3072 |
| context | 48 tokens (corpus p99 = 31) |
| vocabulary | 32,000, byte-level BPE trained on this corpus |
| head | mean-pooled → MLP → (μ, log σ²) |
| loss | censored Gaussian (Tobit) NLL at the reporting floor |
| base model | none — trained from scratch, no download |
Attention is written out in plain matmuls rather than using a fused op, because ONNX, Core ML and the hand-written numpy runtime each lower a fused attention differently (or refuse). Plain matmuls export identically to all three, which is what makes "same weights, four runtimes" a checkable claim.
About an eighth of the corpus sits at or below the reporting floor. Training
those rows as exact observations of the floor teaches the model that very rare
combinations sit at exactly five people, which pulls its estimate for the
rarest — most dangerous — descriptions upward. Over-estimating a crowd is the
failure mode that gets someone identified. The Tobit term instead maximises
P(Y ≤ floor), which is both true and safe.
Exported and verified by scripts/export.py, which fails the export if any
backend disagrees with the torch reference by more than 0.05 log10 (about a tenth
of the calibrated 90% interval width):
mlprogram, fp16, iOS 16+), verified with coremltoolscrowd/gguf.py's pure-numpy runtime (no torch, no tokenizers)general.architecture is crowd-anon, which llama.cpp does not know: the file
is valid GGUF and any tool can read its metadata and tensors, but the bundled
numpy runtime is the reference implementation and the one the benchmark measures.
crowd-anonymity-sets — ~250k synthetic descriptions paired
with exactly computed anonymity-set sizes. The label is not annotated: it is
belief propagation over a tree-structured log-linear model raked to published
Japanese marginals. Splits are on a hash of the attribute combination, so the
test set contains crowds the model has never been told the size of.
The data describes nobody. It is generated from a distribution, not sampled from a population of people.
All figures produced by scripts/evaluate.py, scripts/export.py and
benchmarks/ in this repository; the artefacts they were read from are
committed at github.com/NagaYu/crowd.
| estimator | MAE | RMSE | bias | ECE | 90% interval coverage | ms/doc | peak RSS |
|---|---|---|---|---|---|---|---|
analytic (no model) | 0.289 | 1.186 | -0.288 | 0.289 | 93.0% (nominal 90%, width 0.83 log10) | 0.89 | 84 MB |
crowd-anon-0.1b | 0.350 | 0.543 | +0.025 | 0.169 | 85.3% (nominal 90%, width 1.71 log10) | 4.12 | 1284 MB |
| same weights via GGUF + numpy | 0.347 | 0.557 | +0.061 | 0.170 | 86.6% (nominal 90%, width 1.61 log10) | 85.1 | 1384 MB |
All errors are in log10 head-count units: 0.30 means a factor of two.
The analytic path has the lower MAE and a much worse RMSE — it is exact when its lexicon matches and catastrophically wrong when it does not. Its PIT statistic is 0.50 (a point mass, not a distribution) against 0.17 for the model. The learned model is the better probabilistic estimator; the lexicon is the better point estimator on text it was built for.
Plain-form MAE 0.255 vs oblique-form 0.282 — a penalty of +0.028 log10 over 3000 pairs that differ only in register.
40 hand-written sentences using only expressions absent from the reference bundle. Over-estimating the crowd is the unsafe direction: it declares a dangerous description safe and no masking follows.
| estimator | MAE | bias | over-estimated by >1 log10 (unsafe) |
|---|---|---|---|
analytic | 2.89 | +2.89 | 95% |
neural | 3.80 | -3.80 | 0% |
ensemble | 3.80 | -3.80 | 0% |
Neither estimator is trustworthy here. They fail asymmetrically, and that is
the point: the lexicon fails unsafely, the model fails safely. EnsembleEstimator
takes the minimum of the two for exactly this reason.
An export fails if any backend disagrees with the torch reference by more than 0.05 log10.
| format | size | max diff vs torch | ms/doc | verified |
|---|---|---|---|---|
onnx | 441.1 MB | 0.0000 log10 | 25.2 | yes |
coreml | 220.7 MB | 0.0011 log10 | 30.8 | yes |
gguf:f16 | 224.4 MB | 0.0001 log10 | 93.4 | yes |
gguf:q8_0 | 121.2 MB | 0.0052 log10 | 93.0 | yes |
3046 steps of a requested 4000 (stopped at a 91-minute wall-clock budget), batch 64, lr 0.00015, on mps. The model is not trained to convergence — validation loss was still improving when the budget ran out.
published / approximate / derived / illustrative
per entry. Rebuild from authoritative extracts before any real disclosure
decision.crowd.robustness's aggregation attack
measures the size of that gap but the model does not close it.The four-condition comparison (direct-identifiers-only / NER-mask-all / prompted
LLM / Crowd), the Pareto frontier, the attack-resistance numbers and the figures
are in the repository README at
github.com/NagaYu/crowd, generated from
artifacts/*.json so the prose cannot drift from the measurements.
The calibration protocol is: reliability diagram + nominal-vs-empirical coverage
make all # reference bundle -> dataset -> train -> export -> evaluate -> figures
Deterministic given the seeds. No network access required at any stage.
Apache-2.0 for the code and weights. The reference statistics derive from
Japanese government publications released under 政府標準利用規約(第2.0版)
(CC BY 4.0 compatible, attribution required); sources are listed in the bundle's
provenance block and by crowd reference.