Skip to content

Repository files navigation

NameGuard.ML.Core

Detect whether a name input is a real human name or fake / junk. Fast (microseconds per call), self-contained (embedded model), runs entirely offline. Targets net8.0 and net9.0.

NuGetDownloadsCILicense: MIT

Install

dotnet add package NameGuard.ML.Core

Use

usingNameGuard.ML.Core;varguard=newNameGuard();varresult=guard.Check("Mary Johnson");result.IsReal// trueresult.Score // 1.00 (0..1, higher = more likely real)
result.Reason // "ML model"

ASP.NET Core integration

Drop-in [RealName] attribute:

usingSystem.ComponentModel.DataAnnotations;usingNameGuard.ML.Core;publicsealedclassRealNameAttribute:ValidationAttribute{privatestaticreadonlyNameGuardGuard=new();publicfloatMinScore{get;set;}=0.5f;publicoverrideboolIsValid(object?value){if(valueis not stringname)returntrue;varresult=Guard.Check(name);returnresult.IsReal&&result.Score>=MinScore;}}publicsealedclassSignupRequest{[Required,RealName(MinScore=0.7f,ErrorMessage="Please enter a valid name.")]publicstringFullName{get;set;}="";}

ModelState.IsValid is now false for asdfgh, qwerty, aaaa, etc.

How it works

Two-stage pipeline:

  1. Heuristic fast-path (~0.2 µs) — catches obvious junk: keyboard rolls (qwerty), no vowels (xkqzpw), repeating chars (aaaa), all-digits, length bounds.
  2. ML.NET FastTree classifier (~22 µs) — character n-grams (1–4, TF-IDF) trained on 175 countries × 40 tokens = 17,500 real samples.

The trained model (~1 MB) is embedded in the assembly. No runtime downloads, no Python, no external services.

Sample predictions

Mary Johnson -> REAL (1.00) ML model
Khaled Hossain -> REAL (1.00) ML model
Yuki Tanaka -> REAL (1.00) ML model
Nikolai Lobachevsky -> REAL (1.00) ML model
asdfgh -> FAKE (0.00) Keyboard roll detected
xkqzpw -> FAKE (0.00) No vowels
aaaaaaa -> FAKE (0.00) Repeating character
12345 -> FAKE (0.00) No letters

Quality

Holdout (20%)5-fold CV
AUC0.99970.9996
Accuracy0.99420.9919
F10.99420.9919

Verified on 197 names from every UN member state + observers: 197/197 REAL at score ≥ 0.98.

API

namespaceNameGuard.ML.Core;publicinterfaceINameGuard{NamePredictionCheck(stringname);}publicsealedclassNameGuard:INameGuard,IDisposable{publicNameGuard(floatthreshold=0.5f);// threshold must be in [0, 1]publicNameGuard(StreammodelStream,floatthreshold=0.5f);publicNamePredictionCheck(stringname);// thread-safepublicvoidDispose();}publicsealedclassNamePrediction{publicboolIsReal{get;}// Score >= thresholdpublicfloatScore{get;}// 0..1publicstringReason{get;}// Why this verdict was returned}

Limitations

  • Single-token names (Akihito, Pyotr) score lower — pass full names where possible. Multi-token inputs are scored both as a whole and per token, so rare components don't drag down strong ones.
  • Dictionary-word combos (Lorem Ipsum, Test Test) pass — layer a stop-word check above if needed.
  • Latin-script only — Cyrillic / CJK / Arabic / Greek / Hebrew etc. are rejected with reason "Non-Latin script". Romanize before calling Check().

Check() is thread-safe — a single NameGuard instance can be shared across requests / threads. It pools PredictionEngine instances internally and grows the pool on contention. Call Dispose() on shutdown.

Links

Releases

Packages

Used by

Contributors

Languages