cwLeeDev's picture
Add fail-closed P formula student distillation path
bb698e6 verified
|
Raw
History Blame
20 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/
    ...
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

์„ธ 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"])

์‹ค์ œ Python composite ์ถ”๋ก ์€ Colab bundle์„ ํ‘ผ ๋””๋ ‰ํ„ฐ๋ฆฌ์—์„œ ๋‹ค์Œ์ฒ˜๋Ÿผ ์‹คํ–‰ํ•œ๋‹ค. Adapter๋ฅผ ์ƒ๋žตํ•˜๋ฉด ์ •์ •๋œ ๋ฉ”์ธ ๋ชจ๋ธ์ด ์•„๋‹ˆ๋ผ base-only ๊ฒฝ๋กœ๊ฐ€ ๋˜๋ฏ€๋กœ ๋ฐ˜๋“œ์‹œ ํ•จ๊ป˜ ์ „๋‹ฌํ•œ๋‹ค.

from pathlib import Path
from math_grid_drawer.research.math_ink_06 import MathInk06Engine

engine = MathInk06Engine(
    Path("artifacts/base_378.pt"),
    adapter_checkpoint=Path("artifacts/online_adapter.pt"),
)

result = engine.recognize_online(
    strokes,
    canvas_width=128,
    canvas_height=128,
    top_k=5,
)

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%

ํ–‰๋™ head๋ฅผ ์‹ค์ œ teacher ์ถœ๋ ฅ ๋’ค์— ์—ฐ๊ฒฐํ•˜๊ณ  validation์—์„œ๋งŒ confidence threshold๋ฅผ ์„ ํƒํ•œ ๊ฒฐ๊ณผ, CROHME official test์˜ ๋Œ€์ƒ ๊ธฐํ˜ธ exact top-1์€ 33.65%์—์„œ 47.30%๋กœ ํ‰๊ท  13.65%p ์ƒ์Šนํ–ˆ๋‹ค. Rewrite precision์€ 81.35%์˜€๋‹ค. ๋‹ค๋งŒ ๊ฐ™์€ ๊ตฌ๊ฐ„์˜ teacher visual-family top-1์ด 53.02%์— ๋ถˆ๊ณผํ•ด, ํ–‰๋™ ๋ฌธ๋งฅ๋งŒ์œผ๋กœ ์ž˜๋ชป๋œ ํ˜•ํƒœ๊ตฐ์„ ๋ณต๊ตฌํ•  ์ˆ˜ ์—†์—ˆ๋‹ค.

R-track ์—ฐ์† ์ˆ˜์‹ ์–ด๋Œ‘ํ„ฐ

์ œํ’ˆ trajectory encoder์™€ online adapter๋Š” ๊ณ ์ •ํ•˜๊ณ , CROHME ์—ฐ์†์‹์˜ ์ •๋‹ต symbol group ์œ„์—์„œ 92KB zero-init formula adapter๋งŒ ํ•™์Šตํ–ˆ๋‹ค. ์ด checkpoint๋Š” ๊ตฌ์กฐ ๊ฒ€์ฆ์šฉ R_noncommercial_only ๋ชจ๋ธ์ด๋ฉฐ ์ œํ’ˆ weight ๋˜๋Š” distillation ์ž…๋ ฅ์ด ์•„๋‹ˆ๋‹ค.

3-seed ์ง€ํ‘œ ํ‰๊ท  ์ตœ์ €
writer-validation exact top-1 85.19% 82.91%
writer-validation visual-family top-1 93.30% 93.03%
official test exact top-1 82.38% 81.13%
official test visual-family top-1 88.17% 88.03%
visual-family ์ผ๋ฐ˜ํ™” gap 5.13%p โ€”

Validation์—์„œ๋Š” ์„ธ seed ๋ชจ๋‘ ํ˜•ํƒœ๊ตฐ 92%๋ฅผ ๋„˜๊ฒจ ํ˜„์žฌ TCN ๊ตฌ์กฐ๊ฐ€ ์—ฐ์† ์ˆ˜์‹์—๋„ ์ ์‘ํ•  ์ˆ˜ ์žˆ์Œ์„ ํ™•์ธํ–ˆ๋‹ค. ๋ฐ˜๋ฉด unseen official test์—์„œ๋Š” ๋ชจ๋‘ ์‹คํŒจํ–ˆ๋‹ค. ํ˜„ ๋ณ‘๋ชฉ์€ ๋ชจ๋ธ ์šฉ๋Ÿ‰๋ณด๋‹ค writer/source domain ์ผ๋ฐ˜ํ™”์ด๋ฉฐ, ๋‹ค์Œ gate๋Š” ์ƒ์šฉ ํ—ˆ์šฉ P-track ์—ฐ์†์‹์˜ writer/device-disjoint ์žฌํ•™์Šต์ด๋‹ค.

P ๊ณ ๋ฆฝ๊ธฐํ˜ธ ํ•ฉ์„ฑ ์ˆ˜์‹ proxy โ€” ๊ธฐ๊ฐ

์Šน์ธ HWRT/UJI trajectory 1,590๊ฐœ๋ฅผ ์ˆซ์ž anchor ์‚ฌ์ด์— ํ•ฉ์„ฑ ๋ฐฐ์น˜ํ•ด ํ–‰๋™ head์— weight 0.35๋กœ ์ถ”๊ฐ€ํ•œ seed-17 ์‹คํ—˜์€ accuracy๊ฐ€ 93.07%๋กœ ๊ฐ™์•˜์ง€๋งŒ macro-F1 76.64โ†’73.62%, uppercase recall 61.29โ†’45.16%๋กœ ์•…ํ™”๋๋‹ค. ์‹ค์ œ ์—ฐ์†์‹ validation๊ณผ ๋น„๊ตํ•œ formula-relative bbox width/height์˜ ์ตœ๋Œ€ ์ ˆ๋Œ€ SMD๋Š” 2.82๋กœ ํ˜ธํ™˜ ๊ธฐ์ค€ 0.5๋ฅผ ํฌ๊ฒŒ ๋„˜์—ˆ๋‹ค.

๊ณ ๋ฆฝ๊ธฐํ˜ธ์—๋Š” ์ „์ฒด formula bboxยทTrayยท์ด์›ƒ ๋ถ€์žฌ ๋ถ„ํฌ๊ฐ€ ์—†์œผ๋ฏ€๋กœ ์ž„์˜ ํ•ฉ์„ฑ ๋ฐฐ์น˜๋ฅผ ํ–‰๋™/formula ์ œํ’ˆ ํ•™์Šต์— ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. ์ด ๊ฒฝ๋กœ๋Š” rejected_no_3seed_expansion์ด๋ฉฐ ์‹คํŒจ checkpoint๋„ ๋ฐฐํฌํ•˜์ง€ ์•Š๋Š”๋‹ค. ์Šน์ธ ๊ณ ๋ฆฝ๊ธฐํ˜ธ๋Š” shape encoder์—๋งŒ ์œ ์ง€ํ•˜๊ณ , ํ–‰๋™ ํ•™์Šต์€ ์‹ค์ œ AIFlow P Formula v1 ์—ฐ์†์‹์„ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.

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์„ ๊ธฐ๋กํ–ˆ๋‹ค. Validation-only calibration์œผ๋กœ ๊ณ ์ •๋œ online family-fusion 0.15๋„ export์— ํฌํ•จ๋œ๋‹ค. Fresh seed-17 online/raster .pt2 ํ•ฉ๊ณ„๋Š” 24,300,116 bytes๋‹ค.

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

CPU latencyยทmemory proxy

Family-fusion 0.15๋ฅผ ํฌํ•จํ•œ Windows PyTorch CPU ์žฌ์ธก์ •์—์„œ online p95๋Š” 8.909.67ms, raster p95๋Š” 22.1026.63ms์˜€๋‹ค. Tensor state๋Š” 8.95MB, ๋ชจ๋ธ ๋กœ๋“œ ํ›„ inference RSS ์ฆ๊ฐ€๋ถ„์„ ํ•ฉ์นœ ๊ตฌ์กฐ proxy๋Š” 26.39MB๋‹ค. ์ „์ฒด Python process RSS๋Š” PyTorch runtime์„ ํฌํ•จํ•˜๋ฏ€๋กœ Android LiteRT memory ๊ทผ๊ฑฐ๊ฐ€ ์•„๋‹ˆ๋‹ค.

Online ์˜ค๋ฅ˜ ํ•ฉ์˜ ๊ฐ์‚ฌ

์ •์ • composite ์„ธ seed๋ฅผ ์„ ํƒ์— ์“ฐ์ง€ ์•Š์€ paired writer/device-disjoint 3,782๊ฐœ์—์„œ ๋‹ค์‹œ ๊ฐ์‚ฌํ–ˆ๋‹ค.

์ง€ํ‘œ ๊ฒฐ๊ณผ
exact ensemble top-1 83.71%
exact ensemble top-5 98.02%
visual-family top-1 92.99%
seed oracle top-1 88.05%
์„ธ seed ๊ณตํ†ต ์˜ค๋ฅ˜ 11.95%

Exact ์˜ค๋ฅ˜์˜ 56.98%(์ „์ฒด 9.28%p)๋Š” O/0/o, ๋Œ€์†Œ๋ฌธ์ž, ์ˆ˜์ง์„ ยทcross์ฒ˜๋Ÿผ ๊ฐ™์€ visual family ์•ˆ์˜ ์˜๋ฏธ ํ˜ผ๋™์ด๋‹ค. ๋”ฐ๋ผ์„œ 0.6์˜ trajectory ๋‹จ๊ณ„๋Š” ํ˜•ํƒœ๊ตฐ ํ›„๋ณด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , exact ์˜๋ฏธ๋Š” ์‹ค์ œ ์ˆ˜์‹ ํ–‰์˜ ์ƒ๋Œ€ ํฌ๊ธฐ์™€ ํ–‰๋™ ๋ฌธ๋งฅ์ด ๊ฒฐ์ •ํ•ด์•ผ ํ•œ๋‹ค. ์‹ค์ œ P ์—ฐ์†์‹์ด ์—†์œผ๋ฏ€๋กœ formula-context exact 92% gate๋Š” ์•„์ง ํ†ต๊ณผํ•˜์ง€ ์•Š์•˜๋‹ค.

Validation์—์„œ family-fusion 0.15๋ฅผ ์„ ํƒํ•œ ๋’ค paired-test์— ํ•œ ๋ฒˆ ์ ์šฉํ•˜์ž exact top-1์€ 83.71โ†’83.82%(+0.11%p)์˜€๋‹ค. ์ด๋Š” ์ž‘์€ ๋ณด์ •์ด๋ฉฐ ๋ฌธ๋งฅ ๋ ˆ์ด์–ด๋ฅผ ๋Œ€์ฒดํ•˜์ง€ ์•Š๋Š”๋‹ค.

์ถœ๋ ฅ ๋ฒ”์œ„

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

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

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

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

Local P Formula intake

Drawer์˜ local-only AIFlow Ink v1์€ ์ž๋™์œผ๋กœ ํ•™์Šต ์ •๋‹ต์ด ๋˜์ง€ ์•Š๋Š”๋‹ค. ๋ณ„๋„ human annotation JSONL์ด ์‹ค์ œ ๋น„์‹๋ณ„ device_id, label_status=human_verified, ๋ชจ๋“  formula_cell_id โ†’ token ์ „๋‹จ์‚ฌ๋ฅผ ์ œ๊ณตํ•ด์•ผ ํ•œ๋‹ค.

Materializer๋Š” ๋‹ค์Œ ์กฐ๊ฑด์„ ๋ชจ๋‘ ํ†ต๊ณผํ•œ ๋’ค์—๋งŒ UTF-8 P Formula v1 JSONL์„ ์›์ž์ ์œผ๋กœ ์ƒ์„ฑํ•œ๋‹ค.

  • ๋ชจ๋“  raw stroke๊ฐ€ ์ •ํ™•ํžˆ ํ•œ symbol group์— ํฌํ•จ๋จ
  • timestampยทpressure ๊ฒฐ์ธก์„ ์›๋ณธ ๊ทธ๋Œ€๋กœ ๋ณด์กด
  • ๊ธฐ์ค€ checkpoint์˜ ์ค‘๋ณต ์—†๋Š” 378 exact vocabulary์™€ token ์ผ์น˜
  • origin/writer/device/source split ๋ˆ„์ˆ˜ 0
  • training/validation/test์™€ P ๊ถŒ๋ฆฌยท๋…๋ฆฝ source gate ํ†ต๊ณผ

์ „์ฒด AIFlow source checkout์—์„œ ์‹คํ–‰ํ•œ๋‹ค.

python scripts/materialize_math_ink_06_p_formula.py `
  --input path/to/curated `
  --annotations path/to/annotations.jsonl `
  --checkpoint path/to/base_378.pt `
  --output path/to/p_formula_v1.jsonl `
  --report path/to/preflight.json

์‹คํŒจ ์‹œ report๋งŒ ๋‚จ๊ณ  dataset์€ ์ƒ์„ฑ๋˜์ง€ ์•Š๋Š”๋‹ค. ์ด ๊ธฐ๋Šฅ์€ ์„œ๋ฒ„ ์ „์†ก์ด๋‚˜ ์ž๋™ ์ˆ˜์ง‘์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š๋Š”๋‹ค.

P-only formula adapter training

Materialize๋œ P Formula v1์€ ์ „์ฒด formula bbox ๊ธฐ์ค€ 128ร—19 symbol tensor๋กœ ๋ณ€ํ™˜๋œ๋‹ค. Product encoder์™€ online adapter๋Š” ๋™๊ฒฐํ•˜๊ณ  hidden-64 zero-init formula adapter๋งŒ ํ•™์Šตํ•œ๋‹ค.

family CE + exact CEร—0.10
context dropout 0.30
inverse-sqrt(source frequency ร— exact-label frequency) sampler
validation-only checkpoint selection

๊ฐ seed๋Š” test exact top-1 92%, top-5 99%, macro-F1 90%, writer floor 75%, ๊ฒฐ์ธก metadata slice ํ•˜๋ฝ 3%p ์ดํ•˜๋ฅผ ๋ชจ๋‘ ํ†ต๊ณผํ•ด์•ผ ํ•œ๋‹ค. Seed 17ยท31ยท47์ด ๊ฐœ๋ณ„ ํ†ต๊ณผํ•˜๊ณ  ์„ธ run์˜ ์›๋ณธ P Formula JSONL SHA-256์ด ์ •ํ™•ํžˆ ๊ฐ™์€ ๊ฒฝ์šฐ์—๋งŒ single mobile student distillation์„ ํ—ˆ์šฉํ•œ๋‹ค. Teacher ensemble ์ž์ฒด๋Š” ๊ธฐ๊ธฐ์— ํƒ‘์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค.

์‹ค์ œ seed-17 composite์™€ GTX 1650์„ ์‚ฌ์šฉํ•œ 1-epoch fixture smoke์—์„œ CUDA ํ•™์Šต๋ถ€ํ„ฐ report/checkpoint ์ƒ์„ฑ๊นŒ์ง€ ํ†ต๊ณผํ–ˆ๋‹ค. Fixture checkpoint๋Š” ์„ฑ๋Šฅ ๊ทผ๊ฑฐ๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ ์ด ๊ณต๊ฐœ ์ €์žฅ์†Œ์— ํฌํ•จํ•˜์ง€ ์•Š์•˜๋‹ค. ๊ณ ์ • recipe๋Š” configs/MATH-INK-06-P-FORMULA-v1.json์— ์žˆ๋‹ค.

Single-student distillation

ํ†ต๊ณผํ•œ ์„ธ teacher๋Š” base โ†’ shared online adapter โ†’ P formula adapter ์ˆœ์„œ๋กœ ํ•ฉ์„ฑํ•œ๋‹ค. Temperature 2.0์˜ exact/family ํ™•๋ฅ ์„ seed ์‚ฌ์ด์—์„œ ํ‰๊ท ํ•˜๊ณ  KL + hard-label CE๋กœ hidden-64 formula adapter ํ•˜๋‚˜๋งŒ ํ•™์Šตํ•œ๋‹ค. Student checkpoint์—๋Š” teacher weight๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š๋Š”๋‹ค.

Student๋Š” ์ž์ฒด 92/99ยทmacro-F1ยทwriter/missing gate๋ฟ ์•„๋‹ˆ๋ผ teacher ensemble ๋Œ€๋น„ exact top-1ยทtop-5ยทvisual-family ํ•˜๋ฝ 1%p ์ดํ•˜๋ฅผ ๋ชจ๋‘ ๋งŒ์กฑํ•ด์•ผ ํ•œ๋‹ค. 2/2/2-symbol fixture์˜ 3-teacherโ†’student CUDA ์‹คํ–‰ ๊ฒฝ๋กœ๋Š” ํ†ต๊ณผํ–ˆ์ง€๋งŒ ์ •์‹ student gate๋Š” ์‹คํŒจํ–ˆ๋‹ค. Fixture์™€ checkpoint๋Š” ์ด ๊ณต๊ฐœ ์ €์žฅ์†Œ์— ์—†์œผ๋ฉฐ, ์‹ค์ œ P ๋ฐ์ดํ„ฐ ์„ฑ๋Šฅ์ด๋‚˜ ์ œํ’ˆ ๊ฒ€์ฆ์„ ๋œปํ•˜์ง€ ์•Š๋Š”๋‹ค. LiteRT ๋ณ€ํ™˜๋„ ์•„์ง ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์•˜๋‹ค.

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

  • 378-label paired writer/device-disjoint top-1 ๋ชฉํ‘œ 92%์— ์•„์ง ๋ฏธ๋‹ฌํ•œ๋‹ค.
  • ์ „์ฒด ์ˆ˜์‹ LaTeX, Tray decoder, gridding์€ 0.7 ๋ฒ”์œ„๋‹ค.
  • uppercase ์—ญํ•  recall๊ณผ O/0, styled-letter hard family๊ฐ€ ๋‚จ์€ ๋ณ‘๋ชฉ์ด๋‹ค.
  • ํ–‰๋™ exact gate๋Š” ์œ ํšจํ•˜์ง€๋งŒ, ์—ฐ์†์‹ teacher ํ˜•ํƒœ๊ตฐ์ด ํ‹€๋ฆฌ๋ฉด ์—ญํ•  head๊ฐ€ ๋ณต๊ตฌํ•  ์ˆ˜ ์—†๋‹ค.
  • R-track formula adapter๋Š” validation ํ˜•ํƒœ๊ตฐ 93.30%๋ฅผ ๋‹ฌ์„ฑํ–ˆ์œผ๋‚˜ official test 88.17%์— ๊ทธ์ณ ์ œํ’ˆ ๊ฒ€์ฆ์„ ํ†ต๊ณผํ•˜์ง€ ๋ชปํ–ˆ๋‹ค.
  • ์Šน์ธ P ๊ณ ๋ฆฝ๊ธฐํ˜ธ ํ•ฉ์„ฑ ํ–‰๋™ proxy๋Š” layout SMD ์ตœ๋Œ€ 2.82์™€ uppercase recall ํ•˜๋ฝ ๋•Œ๋ฌธ์— ๊ธฐ๊ฐํ–ˆ๋‹ค.
  • raster virtual-stroke ๊ฒฝ๋กœ๋Š” digit/Greek slice์—์„œ๋Š” ๊ฐœ์„ ๋์ง€๋งŒ 378-label release gate๋ฅผ ํ†ต๊ณผํ•˜์ง€ ๋ชปํ–ˆ๋‹ค.
  • boundary/behavior/formula adapter๋Š” 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์„ ํ™•์ธํ•˜๊ณ  ์‹ ๋ขฐ๋œ ํ™˜๊ฒฝ์—์„œ๋งŒ ์‚ฌ์šฉํ•œ๋‹ค.

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