File size: 11,248 Bytes
2948983 f6e614c 2948983 f6e614c 2948983 f6e614c 2948983 f6e614c 2948983 f6e614c 2948983 f6e614c 2948983 f6e614c 2948983 f6e614c 2948983 f6e614c 2948983 f6e614c 2948983 f6e614c 2948983 f6e614c 2948983 f6e614c bf8ae1c 50549ab f6e614c 2948983 f6e614c bf8ae1c 50549ab 2948983 f6e614c 2948983 f6e614c 2948983 f6e614c c07793c bf8ae1c c07793c bf8ae1c c07793c 50549ab c07793c 50549ab c07793c 50549ab c07793c 5aff889 c07793c 5aff889 c07793c 5aff889 c07793c 5aff889 f6e614c 2948983 f6e614c c07793c f6e614c 2948983 f6e614c 2948983 f6e614c c07793c 52585d7 f6e614c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 | ---
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 ๋ฐฐํฌ๋ณธ์ ์๋๋ค.

## ํต์ฌ ์
๋ ฅ ๊ณ์ฝ

์ค์ ํ ์
๋ ฅ์ ๋ค์ ์์๋ก ์ฒ๋ฆฌํ๋ค.
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:
```text
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`
- ์ถ์ ์๊ฐ์ ์ค์ ๊ด์ธก ์๊ฐ์ฒ๋ผ ์ ์ฅํ์ง ์๋๋ค.
## ๋ชจ๋ธ ๊ตฌ์กฐ
```text
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๋ ์ธ ํ์ผ๋ก ๊ตฌ์ฑ๋๋ค.
```text
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 ๊ณ์ฝ์ ํ์ธํ๋ค.
```python
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:
```text
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์ ํ์ธํ๊ณ ์ ๋ขฐ๋ ํ๊ฒฝ์์๋ง ์ฌ์ฉํ๋ค.
## ์ฐ๊ตฌ ์๋ฃ
- ์ ์ฒด ๊ธฐ์ ๋ณด๊ณ ์: [`reports/RESEARCH_REPORT.md`](reports/RESEARCH_REPORT.md)
- boundary ํ์ต ๊ฒฐ๊ณผ: [`reports/boundary_behavior_guard_report.json`](reports/boundary_behavior_guard_report.json)
- 3-seed ํ๋ head: [`reports/behavior_role_3seed_summary.json`](reports/behavior_role_3seed_summary.json)
- P boundary ์ ์ 3-seed: [`reports/p_boundary_joint_sharedfix_3seed_summary.json`](reports/p_boundary_joint_sharedfix_3seed_summary.json)
- ์ ์ main device stress: [`reports/p_boundary_device_stress_sharedfix_3seed.json`](reports/p_boundary_device_stress_sharedfix_3seed.json)
- Seed-17 composite export: [`exports/seed17/export_manifest.json`](exports/seed17/export_manifest.json)
- ์ค์ P formula schema: [`contracts/aiflow_p_formula_v1.schema.json`](contracts/aiflow_p_formula_v1.schema.json)
- ํ์ผ checksum: [`MANIFEST.json`](MANIFEST.json)
|