typingnorm
人類打字的常模,以及據此判斷一段輸入是否為真人的判準。
每條判準的誤判率都在一份獨立資料集上量過,數字寫在程式碼裡,方法寫在 METHOD.md,擬合與驗證的腳本都在這個 repo 裡,你可以自己重跑。
from typingnorm import check
report = check(events) # events: [(毫秒, 'D'|'U', 實體鍵碼, key), ...]
report.verdict # 'human-consistent' | 'synthetic-signals' | 'insufficient-data'
report.flags # ['zero_rollover']
report.measures # {'wpm': 61.2, 'rollover_pct': 0.0, 'dwell_cv': 0.31, ...}
report.false_positive_budget # 0.0031,觸發判準當中最高的誤判率
判準
只有三條,而且都是刻意選的。
| 判準 | 內容 | 在 2,245 位真人上的誤判率 |
|---|---|---|
same_key_overlap |
同一個實體鍵在放開前又被按下 | 0.00% |
constant_dwell |
每個鍵按住的時間幾乎完全一樣 | 0.00% |
zero_rollover |
完全沒有按鍵重疊(僅 35 WPM 以上套用) | 0.31% |
選擇的原則是只用不受打字速度影響的判準。打字快與慢的人,重疊率、間隔、按住時間 全都差很多,任何「離人類平均多遠」的判準都會系統性誤判速度極端的人,而那恰好是最 不該被誤傷的族群:密碼管理器、語音輸入、切換式存取、螢幕小鍵盤的使用者在時序上都 長得像機器人。
被排除在外的例子:換手比值(左右手交替是否比同手快)看起來是很好的特徵,實測卻在 慢速端反轉,用它當硬判準會誤判 15.46% 的真人。詳見 METHOD.md 第 7.2 節。
這個方法擋得住什麼、擋不住什麼
擋得住不用心的自動化。擋不住刻意模仿真人時序的程式,包括本套件自己的模擬器。
所以 check() 回傳的是訊號不是判決,也刻意不提供 is_human 這種布林值:那會誘導
呼叫端拿它當閘門。請把它當成風險分數的其中一個輸入,不要當成身分驗證。
樣本不足時會回 insufficient-data 而不是猜。少於 150 次擊鍵的統計不可靠,登入表單
那種二三十個按鍵的長度做不了任何判斷。
速度指標
同一份原始資料可以用不同國家的慣用指標計分,因為分數不儲存,只在顯示時現算。
from typingnorm import score, load_session
s = load_session("session.json")
score(s) # 依語言自動選當地慣用指標
score(s, "kdph_ssc") # 換成印度公職考試的單位
| 指標 | 單位 | 出處 |
|---|---|---|
cpm_tqc |
字/分 | TQC 中文輸入,專業級 80 |
cpm_jp |
字/分 | 全商速度部門,1 級 70 |
tasu |
타수 | 워드프로세서 1급 300,按字母鍵計數 |
kdph_ssc |
KDPH | SSC 公職考試,10,500 = 35 WPM |
wpm_net_5 |
WPM | 英文慣例,五字元一詞 |
wpm_4 |
คำ/นาที | 泰文慣例,四字元一詞 |
kpm |
打鍵/分 | 跨語言比較用的共同分母 |
標為 authoritative=False 的指標沒有官方標準,介面上不應出現「合格」「專業級」
這類字眼。
模擬器
typingnorm.simulate 從同一份常模抽樣,產生帶時間戳的按鍵事件流。它存在的主要理由
是給偵測端當測試對手:本套件的測試就是拿它產生的真人樣本,驗證判準不會誤判。
python -m typingnorm.simulate --validate # 輸出分佈與常模對帳
python -m typingnorm.simulate --selftest # 修正邏輯與按鍵序列合法性
資料來源
常模擬合自 KeyRecs(99 位受試者、562,372 筆 digraph,CC BY 4.0,允許商業使用):
Dias, T., Vitorino, J., Maia, E., Sousa, O., & Praça, I. (2023). KeyRecs: A keystroke dynamics and typing pattern recognition dataset. Data in Brief, 50, 109509.
誤判率則在 Aalto 136M Keystrokes 的 2,245 位受試者上獨立量測。該資料集授權限研究與 非商業用途,其導出參數未進入本套件,僅用於驗證,且驗證結果不回頭調整參數。
授權
MIT。
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file typingnorm-0.1.0.tar.gz.
File metadata
- Download URL: typingnorm-0.1.0.tar.gz
- Upload date:
- Size: 55.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dae8bbebc64a54690ee3a69ca0defe5797f0ffe55701b21012de6ed98f32aade
|
|
| MD5 |
b3780b14346a90c230e867861544523f
|
|
| BLAKE2b-256 |
ff2f9ff10e3ada7f4fe05c3940eb72c2e3aef80041c527c705d5a9b1e582963e
|
Provenance
The following attestation bundles were made for typingnorm-0.1.0.tar.gz:
Publisher:
ci.yml on gba3124/typingnorm
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
typingnorm-0.1.0.tar.gz -
Subject digest:
dae8bbebc64a54690ee3a69ca0defe5797f0ffe55701b21012de6ed98f32aade - Sigstore transparency entry: 2450590710
- Sigstore integration time:
-
Permalink:
gba3124/typingnorm@18a4acba9eb9fef28b47fa2c026774d71495887a -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/gba3124
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@18a4acba9eb9fef28b47fa2c026774d71495887a -
Trigger Event:
push
-
Statement type:
File details
Details for the file typingnorm-0.1.0-py3-none-any.whl.
File metadata
- Download URL: typingnorm-0.1.0-py3-none-any.whl
- Upload date:
- Size: 28.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d3c255d9a9625383e2c1afef07283829b1035a3390880f2b40a2d1d04fb8a3ee
|
|
| MD5 |
9f37708a9c15f8d89b7f00849137ce31
|
|
| BLAKE2b-256 |
ce163e5f38eaaf8c11f6843582d6697c6330c4b866c871ea9d9abfb87faa9bc3
|
Provenance
The following attestation bundles were made for typingnorm-0.1.0-py3-none-any.whl:
Publisher:
ci.yml on gba3124/typingnorm
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
typingnorm-0.1.0-py3-none-any.whl -
Subject digest:
d3c255d9a9625383e2c1afef07283829b1035a3390880f2b40a2d1d04fb8a3ee - Sigstore transparency entry: 2450590788
- Sigstore integration time:
-
Permalink:
gba3124/typingnorm@18a4acba9eb9fef28b47fa2c026774d71495887a -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/gba3124
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@18a4acba9eb9fef28b47fa2c026774d71495887a -
Trigger Event:
push
-
Statement type: