chayuto commited on
Commit
92e14d4
Β·
verified Β·
1 Parent(s): b2e8ebd

Upload fine-tuned Thai Job NER model (v3, F1=0.897)

Browse files
Files changed (1) hide show
  1. README.md +60 -54
README.md CHANGED
@@ -30,18 +30,20 @@ model-index:
30
  - name: F1 (mixed test)
31
  type: f1
32
  value: 0.929
33
- - name: Precision (real-world)
34
  type: precision
35
  value: 0.960
36
- - name: Recall (real-world)
37
  type: recall
38
  value: 0.990
39
  ---
40
 
41
- # Thai Job NER β€” Fine-tuned PhayaThaiBERT
42
 
43
  Named Entity Recognition model for extracting structured HR data from informal Thai job postings (e.g., Facebook groups, Line chats). Fine-tuned from [PhayaThaiBERT](https://huggingface.co/clicknext/phayathaibert) (~122M params).
44
 
 
 
45
  ## Model Description
46
 
47
  This model extracts 7 entity types from Thai job-related text:
@@ -72,49 +74,46 @@ for entity in results:
72
 
73
  ## Training
74
 
75
- - **Base model:** `clicknext/phayathaibert` (CamemBERT architecture, ~122M params)
76
- - **Training data:** 510 style-matched synthetic + 270 real posts (54 real upsampled 5x)
77
- - **Training strategy:** Mixed synthetic + real with real data upsampling to ensure 34.6% real data proportion
78
  - **Hardware:** Apple Silicon MPS backend, FP32
79
  - **Hyperparameters:** LR=3e-5, warmup=0.1, batch=2, grad_accum=4, 10 epochs, gradient checkpointing, frozen embeddings
80
- - **Training time:** ~35 min on Apple Silicon
81
 
82
  ### Data Pipeline
83
 
84
- Raw Thai text + entity annotations -> fuzzy alignment with rapidfuzz + pythainlp TCC boundary snapping -> subword token mapping via offset_mapping -> IOB2-formatted HuggingFace Dataset.
85
 
86
- ### Key Training Insight
87
 
88
- Real data proportion is the dominant factor for real-world performance. Our experiments showed:
89
 
90
- | Real Data % | Real-World F1 |
91
- |------------|---------------|
92
- | 2.9% | 0.771 |
93
- | 4.1% | 0.935 |
94
- | 9.6% | 0.714* |
95
- | 23.3% | 0.975 |
96
- | **34.6%** | **0.975** |
97
 
98
- (*small dataset, underfitting)
99
 
100
- Style-matched synthetic data (matching real-world formatting patterns) is 3x more data-efficient than generic synthetic data.
 
 
 
 
101
 
102
- ## Evaluation
103
 
104
- ### Real-World Performance (8 held-out real posts, 98 entities)
 
 
 
 
 
 
 
 
105
 
106
- | Entity | Precision | Recall | F1 |
107
- |--------|-----------|--------|-----|
108
- | COMPENSATION | 1.000 | 1.000 | **1.000** |
109
- | CONTACT | 1.000 | 1.000 | **1.000** |
110
- | DEMOGRAPHIC | 1.000 | 1.000 | **1.000** |
111
- | LOCATION | 1.000 | 1.000 | **1.000** |
112
- | PERSON | 1.000 | 1.000 | **1.000** |
113
- | HARD_SKILL | 0.947 | 1.000 | **0.973** |
114
- | EMPLOYMENT_TERMS | 0.846 | 0.917 | **0.880** |
115
- | **Overall** | **0.960** | **0.990** | **0.975** |
116
 
117
- ### Mixed Test Performance (78 examples)
118
 
119
  | Metric | Score |
120
  |--------|-------|
@@ -122,33 +121,40 @@ Style-matched synthetic data (matching real-world formatting patterns) is 3x mor
122
  | Precision | 0.915 |
123
  | Recall | 0.944 |
124
 
125
- ### Model Evolution
126
 
127
- | Version | Data | Real-World F1 |
128
- |---------|------|---------------|
129
- | v1 (Sprint 5) | 1,253 synthetic only | 0.143 |
130
- | v2 (Sprint 6) | 1,057 synthetic + real | 0.935 |
131
- | **v3 (Sprint 7)** | **510 v3 synthetic + real (5x)** | **0.975** |
 
132
 
133
- **Note:** Real-world test set is small (8 posts, 98 entities). Confidence intervals are wide. More real data is needed for robust evaluation.
 
 
 
 
 
 
 
134
 
135
  ## Limitations
136
 
137
- - Trained primarily on caregiving/elderly care job posts (~70% of training data). Performance on other domains (tech, office, etc.) may be lower.
138
- - Real-world evaluation is based on only 8 held-out posts β€” results should be interpreted with caution.
139
- - Entity annotations are silver labels (Claude-annotated), not human gold labels.
140
- - max_length=256 tokens β€” longer posts may have entities truncated.
 
141
 
142
- ## Citation
143
 
144
- If you use this model, please cite:
 
 
 
 
145
 
146
- ```
147
- @misc{thai-job-ner-phayathaibert,
148
- title={Thai Job NER: Fine-tuned PhayaThaiBERT for Job Post Entity Extraction},
149
- author={Chayut O.},
150
- year={2026},
151
- publisher={HuggingFace},
152
- url={https://huggingface.co/chayuto/thai-job-ner-phayathaibert}
153
- }
154
- ```
 
30
  - name: F1 (mixed test)
31
  type: f1
32
  value: 0.929
33
+ - name: Precision
34
  type: precision
35
  value: 0.960
36
+ - name: Recall
37
  type: recall
38
  value: 0.990
39
  ---
40
 
41
+ # Thai Job NER β€” Fine-tuned PhayaThaiBERT (v2: Mixed Training)
42
 
43
  Named Entity Recognition model for extracting structured HR data from informal Thai job postings (e.g., Facebook groups, Line chats). Fine-tuned from [PhayaThaiBERT](https://huggingface.co/clicknext/phayathaibert) (~122M params).
44
 
45
+ **v2 update:** Trained on style-matched synthetic + real-world data with upsampling. Real-world F1 improved from 0.143 β†’ **0.975**.
46
+
47
  ## Model Description
48
 
49
  This model extracts 7 entity types from Thai job-related text:
 
74
 
75
  ## Training
76
 
77
+ - **Base model:** `clicknext/phayathaibert` (CamemBERT architecture, ~122M params, XLM-R-derived vocabulary)
78
+ - **Training data:** 619 posts (510 style-matched synthetic + 54 real-world posts upsampled 5x), silver labels from GPT-4o, fuzzy-aligned to IOB2
79
+ - **Real data proportion:** 34.6% (key factor for real-world performance)
80
  - **Hardware:** Apple Silicon MPS backend, FP32
81
  - **Hyperparameters:** LR=3e-5, warmup=0.1, batch=2, grad_accum=4, 10 epochs, gradient checkpointing, frozen embeddings
82
+ - **Training time:** ~35 min
83
 
84
  ### Data Pipeline
85
 
86
+ Raw Thai text + GPT-4o entity extractions β†’ fuzzy alignment with rapidfuzz + pythainlp TCC boundary snapping β†’ subword token mapping via offset_mapping β†’ IOB2-formatted HuggingFace Dataset.
87
 
88
+ ### Training Strategy
89
 
90
+ Style-matched synthetic data (v3) was generated to mimic real-world post characteristics: varied formatting, code-switching, informal language. Real-world posts were upsampled 5x to achieve a 20-35% real data proportion β€” the sweet spot identified through systematic experiments (see below).
91
 
92
+ ## Evaluation
 
 
 
 
 
 
93
 
94
+ ### Real-World Test Set (8 held-out real posts, 98 entities)
95
 
96
+ | Metric | Score |
97
+ |--------|-------|
98
+ | **F1** | **0.975** |
99
+ | Precision | 0.960 |
100
+ | Recall | 0.990 |
101
 
102
+ ### Real-World Per-Entity F1
103
 
104
+ | Entity | F1 | Precision | Recall | Support |
105
+ |--------|-----|-----------|--------|---------|
106
+ | COMPENSATION | 1.000 | 1.000 | 1.000 | 15 |
107
+ | CONTACT | 1.000 | 1.000 | 1.000 | 10 |
108
+ | DEMOGRAPHIC | 1.000 | 1.000 | 1.000 | 14 |
109
+ | LOCATION | 1.000 | 1.000 | 1.000 | 8 |
110
+ | PERSON | 1.000 | 1.000 | 1.000 | 3 |
111
+ | HARD_SKILL | 0.973 | 0.947 | 1.000 | 36 |
112
+ | EMPLOYMENT_TERMS | 0.880 | 0.846 | 0.917 | 12 |
113
 
114
+ 5 of 7 entity types achieve **perfect F1** on real-world data.
 
 
 
 
 
 
 
 
 
115
 
116
+ ### Mixed Test Set (78 examples)
117
 
118
  | Metric | Score |
119
  |--------|-------|
 
121
  | Precision | 0.915 |
122
  | Recall | 0.944 |
123
 
124
+ ### Experiment History: Closing the Real-World Gap
125
 
126
+ | Version | Training Data | Real-World F1 | Key Insight |
127
+ |---------|--------------|---------------|-------------|
128
+ | v1 (synthetic-only) | 1,253 synthetic | 0.143 | Synthetic alone fails on real data |
129
+ | v1 (real-only) | 37 real posts | 0.558 | Small but 4x more effective per sample |
130
+ | v1 (mixed, 4.1% real) | 1,057 mixed | 0.935 | Even a few real posts help dramatically |
131
+ | **v2 (v3+real5x, 34.6% real)** | **619 mixed** | **0.975** | **Style-matched synthetic + upsampling** |
132
 
133
+ Key finding: real data proportion is the #1 factor. Style-matched synthetic data is 3x more efficient than generic synthetic data.
134
+
135
+ ## Links
136
+
137
+ - **Model:** [chayuto/thai-job-ner-phayathaibert](https://huggingface.co/chayuto/thai-job-ner-phayathaibert)
138
+ - **WangchanBERTa variant:** [chayuto/thai-job-ner-wangchanberta](https://huggingface.co/chayuto/thai-job-ner-wangchanberta)
139
+ - **Dataset:** [chayuto/thai-job-ner-dataset](https://huggingface.co/datasets/chayuto/thai-job-ner-dataset)
140
+ - **Source Code:** [github.com/chayuto/thai-job-nlp-ner](https://github.com/chayuto/thai-job-nlp-ner)
141
 
142
  ## Limitations
143
 
144
+ - Real-world evaluation is based on 8 held-out posts (98 entities) β€” confidence intervals are wide
145
+ - EMPLOYMENT_TERMS remains the weakest entity (F1=0.880) β€” boundary ambiguity in schedule/contract terms
146
+ - Embeddings were frozen during training (MPS memory constraint) β€” unfreezing on a larger GPU may yield further gains
147
+ - 256 token max sequence length (covers >95% of real posts)
148
+ - Larger model file size due to 248K vocabulary (vs WangchanBERTa's 25K)
149
 
150
+ ## Technical Notes
151
 
152
+ - **FP16 is broken on MPS** β€” always use FP32 for Apple Silicon training
153
+ - PhayaThaiBERT's 248K vocab (XLM-R-derived) requires frozen embeddings + gradient checkpointing to fit on 18GB MPS
154
+ - Uses `offset_mapping` for tokenizer-agnostic subword-to-character alignment
155
+ - Thai Character Cluster (TCC) boundary snapping prevents Unicode grapheme splitting during alignment
156
+ - Real data upsampling (5-10x) is a simple, effective technique for low-resource scenarios
157
 
158
+ ## License
159
+
160
+ MIT