cwLeeDev's picture
Add fail-closed real P formula data contract
52585d7 verified
|
Raw
History Blame
11.2 kB
metadata
language:
  - ko
  - en
library_name: pytorch
license: other
pipeline_tag: feature-extraction
tags:
  - online-handwriting
  - mathematical-expression-recognition
  - trajectory
  - temporal-convolution
  - on-device
  - pytorch

AIFlow Math Ink 0.6

AIFlow Math Ink 0.6์€ ์ˆ˜ํ•™ ํ•„๊ธฐ๋ฅผ ์ด๋ฏธ์ง€๋ณด๋‹ค point/stroke sequence๋กœ ๋จผ์ € ์ฒ˜๋ฆฌํ•˜๋Š” ์˜จ๋””๋ฐ”์ด์Šค ์—ฐ๊ตฌ ๋ชจ๋ธ์ด๋‹ค. ์›๋ณธ touch event๋ฅผ ๋ณด์กดํ•˜๋ฉด์„œ ๋ชจ๋ธ ์ž…๋ ฅ๋งŒ 6Hz canonical tap์œผ๋กœ ์žฌํ‘œ๋ณธํ™”ํ•˜๊ณ , ๊ฐ ๊ณ ๋ฆฝ ๊ธฐํ˜ธ์˜ 378-class top-k์™€ visual-family ํ™•๋ฅ ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

ํ˜„์žฌ ๊ณต๊ฐœ๋ณธ์€ seed 17ยท31ยท47์˜ ์—ฐ๊ตฌ checkpoint์™€ grouping/behavior head๋ฅผ ํฌํ•จํ•œ๋‹ค. ์ „์ฒด ์ˆ˜์‹ LaTeX decoder๋‚˜ ์™„์„ฑ๋œ Android LiteRT ๋ฐฐํฌ๋ณธ์€ ์•„๋‹ˆ๋‹ค.

AIFlow Math Ink 0.6 architecture

ํ•ต์‹ฌ ์ž…๋ ฅ ๊ณ„์•ฝ

Stroke encoding

์‹ค์ œ ํŽœ ์ž…๋ ฅ์€ ๋‹ค์Œ ์ˆœ์„œ๋กœ ์ฒ˜๋ฆฌํ•œ๋‹ค.

  1. ๊ธฐ๊ธฐ์˜ ๋ชจ๋“  touch event๋ฅผ ์›๋ณธ timestamp์™€ ํ•จ๊ป˜ ๋ฉ”๋ชจ๋ฆฌ์— ๋ณด์กดํ•œ๋‹ค.
  2. stroke๋ณ„ ์‹œ์ž‘์ ยท๋์ ยทpen-up์„ ํ•„์ˆ˜ anchor๋กœ ๋‚จ๊ธด๋‹ค.
  3. ๋ชจ๋ธ์šฉ temporal view๋งŒ 6Hz๋กœ ์žฌํ‘œ๋ณธํ™”ํ•œ๋‹ค.
  4. ์ข…ํšก๋น„๋ฅผ ๋ณด์กดํ•ด 128ร—128 ink space์— ์ค‘์•™ ์ •๊ทœํ™”ํ•œ๋‹ค.
  5. ์ตœ๋Œ€ 128 event, 19๊ฐœ feature๋ฅผ 128ร—19 tensor๋กœ ๋งŒ๋“ ๋‹ค.

19๊ฐœ channel:

shape_x, shape_y,
canvas_x, canvas_y,
direction_x, direction_y,
curvature, pen_up, stroke_progress,
aspect_ratio,
bbox_top, bbox_bottom, bbox_height, center_y,
baseline_available,
time_delta, speed, missing_mask, source_modality
  • timestamp๊ฐ€ ์‹ค์ œ๋กœ ์žˆ์œผ๋ฉด timestamp_mode=observed
  • ์ •์  ์ด๋ฏธ์ง€์ฒ˜๋Ÿผ ์‹œ๊ฐ„์ด ์—†์œผ๋ฉด timestamp_mode=canonical, missing_mask=1
  • ์ถ”์ • ์‹œ๊ฐ„์„ ์‹ค์ œ ๊ด€์ธก ์‹œ๊ฐ„์ฒ˜๋Ÿผ ์ €์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค.

๋ชจ๋ธ ๊ตฌ์กฐ

Online stroke
  โ†’ 6 Hz canonical taps (128ร—19)
  โ†’ online dual-TCN adapter
  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                                               โ”‚
Raster 128ร—128                                 โ”‚
  โ†’ spatial encoder                            โ”‚
  โ†’ causal virtual-trajectory decoder          โ”‚
  โ†’ top-4 stroke hypotheses                    โ”‚
  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
                                               โ–ผ
                                shared residual TCN (hidden=128)
                                     โ”œโ”€ exact head: 378 labels
                                     โ”œโ”€ family head: 324 families
                                     โ””โ”€ top-k probabilities

Local formula context + stroke tensor
  โ†’ 49-d context MLP + stroke TCN
  โ†’ identifier_lower / identifier_upper / multiply_operator

Segmentation lattice geometry
  โ†’ boundary behavior head
  โ†’ candidate crosses a symbol boundary?

Raster ๊ฒฝ๋กœ๋„ ์ตœ์ข… label shortcut์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. ์ด๋ฏธ์ง€์—์„œ top-4 virtual stroke๋ฅผ ๋งŒ๋“  ํ›„ ๋™์ผ trajectory encoder๋กœ ๋‹ค์‹œ ์ธ์‹ํ•œ๋‹ค.

๊ณต๊ฐœ checkpoint

๊ฐ seed๋Š” ์„ธ ํŒŒ์ผ๋กœ ๊ตฌ์„ฑ๋œ๋‹ค.

models/
  seed17/
    base_378.pt
    online_adapter.pt
    behavior_role_head.pt
  seed31/
    ...
  seed47/
    ...
  auxiliary/
    boundary_auxiliary_head.pt
    seed17/boundary_joint_delta.pt
    seed31/boundary_joint_delta.pt
    seed47/boundary_joint_delta.pt
artifacts/
  boundary_behavior_guard.joblib
ํŒŒ์ผ ์—ญํ•  ์ฃผ์š” ๊ณ„์•ฝ
base_378.pt ๊ณตํ†ต trajectory/raster base hidden 128, top-4 hypothesis, 378 exact, 324 family
online_adapter.pt ์‹ค์ œ ์˜จ๋ผ์ธ stroke ๋ณด์ • dual_tcn_v3, top4-skeleton-128x19
behavior_role_head.pt x/X/ร— ์—ญํ•  ๋ฌธ๋งฅ 128ร—19 stroke + 49 context feature
boundary_behavior_guard.joblib ์ž˜๋ชป๋œ ๋‹ค๊ธฐํ˜ธ ๋ณ‘ํ•ฉ ์–ต์ œ geometry 17 feature, threshold 0.5, weight 6
boundary_auxiliary_head.pt shared embedding์šฉ P-track boundary smoke 384โ†’1, main exact/family head ๋น„ํ‡ดํ–‰
boundary_joint_delta.pt seed๋ณ„ ์ œํ•œ joint fine-tuning delta last TCN + attention + exact/family/boundary heads

์„ธ seed teacher๋ฅผ ๊ทธ๋Œ€๋กœ ๋ชจ๋ฐ”์ผ์— ๋„ฃ๋Š” ๊ฒƒ์ด ์ตœ์ข… ๋ชฉํ‘œ๋Š” ์•„๋‹ˆ๋‹ค. release ๊ฒฝ๋กœ๋Š” seed ensemble์„ ํ•˜๋‚˜์˜ student๋กœ distillationํ•œ ๋’ค LiteRT INT8/FP16์„ ๋น„๊ตํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

Checkpoint metadata ํ™•์ธ

์•„๋ž˜ ์ฝ”๋“œ๋Š” network๋ฅผ ์‹คํ–‰ํ•˜์ง€ ์•Š๊ณ  checkpoint ๊ณ„์•ฝ์„ ํ™•์ธํ•œ๋‹ค.

from pathlib import Path
import torch

root = Path("models/seed17")

base = torch.load(root / "base_378.pt", map_location="cpu", weights_only=False)
adapter = torch.load(root / "online_adapter.pt", map_location="cpu", weights_only=False)
role = torch.load(root / "behavior_role_head.pt", map_location="cpu", weights_only=False)

print(base["model_version"])
print(base["max_events"], base["sample_hz"])
print(len(base["feature_names"]), len(base["exact_labels"]), len(base["family_labels"]))
print(adapter["adapter_architecture"], adapter["feature_contract"])
print(role["role_labels"], role["context_features"])

state_dict๋ฅผ ์‹ค์ œ module์— ์ ์žฌํ•˜๋ ค๋ฉด ์ด ์ €์žฅ์†Œ์˜ snapshot ์ฝ”๋“œ๋ฟ ์•„๋‹ˆ๋ผ ์ „์ฒด AIFlow ์—ฐ๊ตฌ ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•˜๋‹ค. checkpoint ๋‚ด๋ถ€ ๊ฒฝ๋กœ๋Š” lineage ๊ธฐ๋ก์ด๋ฉฐ ๋กœ์ปฌ ์ ˆ๋Œ€๊ฒฝ๋กœ์— ์˜์กดํ•ด ์ถ”๋ก ํ•˜์ง€ ์•Š๋Š”๋‹ค.

ํ˜„์žฌ ์„ฑ๋Šฅ

378-label trajectory classifier

์ตœ์‹  online case-context seed 17 ๊ธฐ์ค€:

split top-1 top-5 family top-1
writer validation, 4,261 samples 86.13% 99.48% 92.94%
paired writer-disjoint test, 3,782 samples 82.87% 97.73% 91.22%

Paired source๋Š” HWRT ๋‚ด๋ถ€ writer hash split๊ณผ UJI Pen v1/v2 writer-disjoint ๊ณ„์•ฝ์„ ์‚ฌ์šฉํ–ˆ๋‹ค. HWRT official test๋Š” ๊ฑฐ๋Œ€ writer ์ค‘๋ณต ๋•Œ๋ฌธ์— ์ œ์™ธํ–ˆ๋‹ค.

์ˆ˜์‹ ํ–‰๋™ head

์ •๋‹ต symbol grouping ์ดํ›„์˜ CROHME ์กฐ๊ฑด๋ถ€ ์—ญํ•  ํ‰๊ฐ€:

์ง€ํ‘œ 3-seed ํ‰๊ท 
role accuracy 93.33%
macro-F1 76.41%
lowercase identifier recall 95.66%
uppercase identifier recall 55.91%
multiplication recall 88.89%
ECE 4.88%

Grouping boundary head

์ง€ํ‘œ ์ด์ „ boundary ์ ์šฉ
CROHME exact partition 60.04% 60.25%
pair-F1 91.07% 91.26%
overmerge formula rate 21.72% 20.49%

P boundary shared-state ์ •์ •

์ดˆ๊ธฐ ๊ณต๊ฐœ P delta๋Š” online_adapter.pt์˜ shared_state_dict๋ฅผ ์ ์šฉํ•˜์ง€ ์•Š์€ loader ๊ฒฐํ•จ์„ ์ƒ์†ํ–ˆ๋‹ค. ์ด ๋•Œ๋ฌธ์— ๊ฐ•ํ•œ main encoder๋ฅผ ๋น ๋œจ๋ฆฐ ๋‚ฎ์€ ๊ธฐ์ค€์„ ๊ณผ ๋น„๊ตํ–ˆ์œผ๋ฉฐ, ํ•ด๋‹น auxiliary/joint checkpoint์™€ ์„ฑ๋Šฅ ์ฃผ์žฅ์„ ์ฒ ํšŒํ–ˆ๋‹ค.

์˜ฌ๋ฐ”๋ฅธ ํ•ฉ์„ฑ ์ˆœ์„œ์ธ base โ†’ adapter shared state โ†’ modality adapter โ†’ optional head๋กœ ์„ธ seed๋ฅผ ๋‹ค์‹œ ํ•™์Šตํ•œ ๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

paired proxy test ์ •์ •๋œ main baseline joint ๊ฒฐ๊ณผ ๋ณ€ํ™”
exact top-1 83.03% 82.81% -0.22%p
family top-1 91.37% 90.88% -0.49%p
single-symbol recall โ€” 92.83% 95% floor ์‹คํŒจ
cross-boundary recall โ€” 98.47% ํ†ต๊ณผ

์„ธ seed ๋ชจ๋‘ release gate๋ฅผ ์‹คํŒจํ–ˆ์œผ๋ฏ€๋กœ joint delta๋Š” ๋ฐฐํฌํ•˜์ง€ ์•Š๋Š”๋‹ค. ํ˜„์žฌ ์œ ํšจํ•œ main ๊ตฌ์„ฑ์€ seed๋ณ„ base_378.pt + online_adapter.pt์ด๋ฉฐ adapter ์•ˆ์˜ shared_state_dict๋ฅผ ๋ฐ˜๋“œ์‹œ ๋จผ์ € ์ ์šฉํ•ด์•ผ ํ•œ๋‹ค.

Joint delta ์—†๋Š” main+shadow auxiliary device stress์—์„œ ์ตœ์•… exact/family ํ•˜๋ฝ์€ affine ๋ณ€ํ˜•์˜ -0.98%p/-1.08%p์˜€๋‹ค. Software stress๋Š” ํ†ต๊ณผํ–ˆ์ง€๋งŒ clean single recall์ด 91.42~94.50%์ด๋ฏ€๋กœ auxiliary head๋„ ์ œํ’ˆ ์ฑ„ํƒ ๋Œ€์ƒ์ด ์•„๋‹ˆ๋‹ค.

Composite torch.export

Export ๊ทธ๋ž˜ํ”„๋Š” ์ด์ œ base-only๊ฐ€ ์•„๋‹ˆ๋ผ online/raster modality adapter์™€ shared state๋ฅผ ํฌํ•จํ•œ๋‹ค. ์„ธ seed ๋ชจ๋‘ ๊ฐ ๊ฒฝ๋กœ ๋Œ€ํ‘œ ์ž…๋ ฅ 76๊ฐœ์—์„œ eager ๋Œ€๋น„ top-1 100% ์ผ์น˜, ์ตœ๋Œ€ logit ์ ˆ๋Œ€์˜ค์ฐจ 0.0์„ ๊ธฐ๋กํ–ˆ๋‹ค. Seed-17์˜ online/raster .pt2 ํ•ฉ๊ณ„๋Š” 18,657,779 bytes๋‹ค.

.pt2๋Š” Android์šฉ .tflite๊ฐ€ ์•„๋‹ˆ๋‹ค. LiteRT Torch 0.9.1 ๋ณ€ํ™˜๊ณผ Android runtime parity๋Š” ์•„์ง ์™„๋ฃŒ๋˜์ง€ ์•Š์•˜์œผ๋ฏ€๋กœ litert_exported=false๋ฅผ ์œ ์ง€ํ•œ๋‹ค.

์ถœ๋ ฅ ๋ฒ”์œ„

์˜๋„ํ•œ ๋ชจ๋ฐ”์ผ API:

recognizeOnline(strokes, canvas) โ†’ SymbolResult
recognizeRaster(bitmap)          โ†’ SymbolResult

SymbolResult:
  candidates[{token, probability}]
  confidence
  modelVersion
  latencyMs

์ด๋ฏธ์ง€, raw stroke, virtual stroke๋Š” ์„œ๋ฒ„ payload๋กœ ์ „์†กํ•˜์ง€ ์•Š๋Š”๋‹ค. virtual hypotheses๋Š” ๋กœ์ปฌ debug์—์„œ๋งŒ ๋…ธ์ถœํ•œ๋‹ค.

์•Œ๋ ค์ง„ ํ•œ๊ณ„

  • 378-label paired writer/device-disjoint top-1 ๋ชฉํ‘œ 92%์— ์•„์ง ๋ฏธ๋‹ฌํ•œ๋‹ค.
  • ์ „์ฒด ์ˆ˜์‹ LaTeX, Tray decoder, gridding์€ 0.7 ๋ฒ”์œ„๋‹ค.
  • uppercase ์—ญํ•  recall๊ณผ O/0, styled-letter hard family๊ฐ€ ๋‚จ์€ ๋ณ‘๋ชฉ์ด๋‹ค.
  • raster virtual-stroke ๊ฒฝ๋กœ๋Š” digit/Greek slice์—์„œ๋Š” ๊ฐœ์„ ๋์ง€๋งŒ 378-label release gate๋ฅผ ํ†ต๊ณผํ•˜์ง€ ๋ชปํ–ˆ๋‹ค.
  • boundary/behavior head๋Š” CROHME R-track ํ•™์Šต๋ฌผ์ด๋ฏ€๋กœ ์ œํ’ˆ weight๋กœ distillํ•  ์ˆ˜ ์—†๋‹ค.
  • P boundary auxiliary/joint๋Š” shared-state ์ •์ • ํ›„ ์„ธ seed release gate๋ฅผ ์‹คํŒจํ•ด checkpoint๋ฅผ ์ฒ ํšŒํ–ˆ๋‹ค.
  • Device stress๋Š” ์ฑ„ํƒ๋˜์ง€ ์•Š์€ shadow auxiliary์˜ software perturbation ๊ฒฐ๊ณผ์ด๋ฉฐ ์‹ค์ œ stylus/device-disjoint ์„ฑ๋Šฅ ๊ทผ๊ฑฐ๊ฐ€ ์•„๋‹ˆ๋‹ค.
  • Android LiteRT ๋ณ€ํ™˜, PyTorch/LiteRT logit parity, ์ €๊ฐ€ยท์ค‘๊ธ‰ยท๊ณ ๊ธ‰ ๊ธฐ๊ธฐ benchmark๊ฐ€ ๋‚จ์•„ ์žˆ๋‹ค.

๋ฐ์ดํ„ฐ์™€ ๊ถŒ๋ฆฌ

์ด ์ €์žฅ์†Œ์—๋Š” ์›๋ณธ ํ•„๊ธฐ ๋ฐ์ดํ„ฐ, ์ด๋ฏธ์ง€, OCR cache๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š๋Š”๋‹ค.

  • HWRT database: ODbL-1.0 ์ทจ๊ธ‰, attribution ๋ฐ ํŒŒ์ƒ database ๊ฒ€ํ†  ํ•„์š”
  • UJI/Pendigits ๊ณ„์—ด: ๊ฐ ์› ์ถœ์ฒ˜ ์กฐ๊ฑด์„ ๋ณ„๋„๋กœ ๋”ฐ๋ผ์•ผ ํ•จ
  • CROHME/MathWriting: ๋น„์ƒ์—… R-track ํ‰๊ฐ€ ๋˜๋Š” ์—ฐ๊ตฌ head์—๋งŒ ์‚ฌ์šฉ
  • checkpoint์™€ report๋Š” ํ˜„์žฌ research-only / non-commercial ๊ณต๊ฐœ๋ฌผ์ด๋‹ค.
  • ์ƒ์šฉ checkpoint๋Š” ๊ถŒ๋ฆฌ ๊ฒ€ํ† ๋ฅผ ํ†ต๊ณผํ•œ P-track ๋ฐ์ดํ„ฐ๋กœ ์ฒ˜์Œ๋ถ€ํ„ฐ ์žฌํ•™์Šตํ•ด์•ผ ํ•œ๋‹ค.

์ด ๊ณต๊ฐœ๋Š” ์ œํ’ˆ ์ •ํ™•๋„ยท์ƒ์šฉ ๋ฐฐํฌ ๊ฐ€๋Šฅ์„ฑยทLiteRT ํ˜ธํ™˜์„ฑ์„ ๋ณด์ฆํ•˜์ง€ ์•Š๋Š”๋‹ค.

๋ณด์•ˆ

PyTorch checkpoint์™€ joblib/pickle์€ ์‹ ๋ขฐํ•  ์ˆ˜ ์—†๋Š” ์ถœ์ฒ˜์—์„œ ๋กœ๋“œํ•˜๋ฉด ์ž„์˜ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค. MANIFEST.json์˜ SHA-256์„ ํ™•์ธํ•˜๊ณ  ์‹ ๋ขฐ๋œ ํ™˜๊ฒฝ์—์„œ๋งŒ ์‚ฌ์šฉํ•œ๋‹ค.

์—ฐ๊ตฌ ์ž๋ฃŒ